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),以上只是个人的简单理解,手写的大致汇编流程,一定有很多错误,求指点!
原创粉丝点击