C++分析淹没EIP
来源:互联网 发布:工业控制中的软件编程 编辑:程序博客网 时间:2024/04/29 17:15
# include <iostream>using namespace std;void g_func(){ int x = 0; int * p = & x; // 定位到ebp-4 p+=2; // p+1 定位到 当前EBP,然后EBP+4 == p+2 就是原来的EIP的地址 (*p) = 1111; // Exception Offset: 00000457 就是十进制的1111 }int main(){ //printf("hello"); g_func(); printf("hello"); system("pause"); return 0; }/* 一般函数的执行过程push arg3push arg2push arg1 ; call之前先压入参数,自右向左push eip ; 程序在执行完call后的下一条地址,也就是说下面的push ebp 已经是在新的函数栈中(这一步隐含在call里执行的)call g_fun() ; 跳转到函数入口执行那个g_fun(),或者可能去函数表找一下再跳过去------------------------------------------------------g_fun(){ push epb ; 保存老栈顶 mov ebp,esp ; 将新栈顶抬高 sub esp n*sizeof(type) ; 就是抬高栈顶,为局部变量腾出空间 (n个 类型为type的空间) 。。。。 ; 对局部变量的各种操作(操作局部变量是 ebp- n*size ,(n是第几个声明的局部变量),操作参数是ebp+n*size n, ; 是倒数第几个压栈的参数(自右向左))------------------------------------------------------- ; 假如说下面的一段asm是这样的 push ebp mov ebp,esp sub esp, 8 ; 估计是开辟了两个整形的局部变量 push edx push edi push esi ; int x = 1; mov dword ptr[ebp-4],1 ; 将1的值以双字的大小copy到栈位置是栈里第一个变量(距离站低是4 byte)的位置 ; int * p = &x; lea eax, [ebp-4] ; 加载(load effective address 加载有效地址)ebp-4变量所在位置的地址到eax mov dword ptr[ebp-8],eax ; 将第一个变量的地址放入栈中ebp-8的位置,就是变量p的位置 ; p += 2; mov ecx, dword ptr[ebp-8] ; 将 p变量放入 ecx里面 add ecx, 8 ; 这里是给ecx加上指针变量类型字节数的二倍 mov dword ptr[ebp-8], ecx ; 就是将刚才的值乘二之后再放回p变量中 ,这里定位到eip的位置并修改了eip的值 ; (*p) = 1111; mov edx,dword ptr[ebp-8] ; 将指向的位置的变量放入edx mov dword ptr[edx],457h ; 将1111copy到以 edx(p变量的值) 指向的位置 ; 这里补充一下要是局部变量 返回 一般就是多一句 mov eax, dword ptr[ebp-4] ; 将局部变量复制一份放在 eax中 }---------------------所谓的被调负责平衡堆栈------------------ pop edi ; 恢复先前压栈的的寄存器现场(前三个一般不用关心,所以在call 前 压栈的时候没有着重提) pop esi pop ebx mov esp,ebp ; 降低栈顶 pop ebp ; 还原老栈低 ret ; 神秘的ret实际上是负责清除局部变量的 隐含执行两句 分别是 add esp,8h 和 pop eip *//* 反汇编分析call 前原来的 esp = 0x0012fef8 ebp = 0012ff48call 后的下一条指令 eip = 4010adcall 后esp 0x12fef4 ; 这里说明在call的过程中有一个4字节的数据进栈了,到底是啥哪?我们只需要到; 那段占空间去看看就知道了, 在内存窗口看看是 AD 10 40 00 的数据,(注意这里是windows的栈是小尾的存储方法,所以这里数据需要是自右向左读的),一看正等于 call 后的下一条地址 004010ad这下恍然大悟吧,call 时已经隐含执行了push eip,不用怀疑 在调用完函数时 也会有 pop eip 并且这是程序正常向下执行的关键!!!等到执行了 int x = 0;int * p = &x;p+=2;(*p) = 1111;之后 原来老eip的地址的值由004010ad eip的值变成00000457 就是1111的十六进制值所以在后面的 pop eip 就惨了,直接说eip指向的地址有问题,程序开始蹦了.....今天到这,如果写的有问题,请指点*/
可定位的EIP位置,利用数据段数据给EIP位置赋值,强行转移程序的执行流程,也就是关键是pop EIP时栈顶的数据决定,因为EIP会把pop过来的数据当指令地址去寻址执行,这下问题就清晰了,应该是可以把它转移到一个可执行代码段(比如自己的ShellCode),以上只是个人的简单理解,手写的大致汇编流程,一定有很多错误,求指点!