汇编语言11堆栈修改

1.下面这段代码运行的结果是什么?

#include <stdio.h>
#include <Windows.h>
DWORD dz=0;
DWORD dz1=0;
void fun1()
{
  __asm
  {
  mov eax, dz
  push eax
  ret
  }
}
void main()
{
  HMODULE h = GetModuleHandle(NULL);
  dz1= dz =(DWORD)h;
  dz+=0x1062;//0x1062为 printf("2222
")相对于代码段基址的偏移
  dz1+=0x0;
  __asm
  {
  call fun1
  }
  printf("1111
");
  printf("2222
");
}

不仔细思考,运行结果为:
2222

实际运行结果:
2222
1111
2222
为什么会这样,分析下原因:
1. call fun1语句执行后: printf("1111 ") 的地址压入栈.

2. fun1函数执行后: ret指令改变了eip, eip = dz, 转到main函数里面执行 printf("2222 ")

3. main函数执行ret后: 取出printf("1111 ")地址赋给了eip, 导致程序又跳到了printf("1111 ")处执行


2.把fun1函数改进下,使运行结果为:
2222

实现代码:

#include <stdio.h>
#include <Windows.h>
DWORD dz=0;
DWORD dz1=0;
void fun1()
{
    __asm
   {
   add esp,8 //前面默认执行了push eip, push ebp, 保存main ret的地址内存就在esp+8的位置
     mov eax, dz1
       push eax //把printf("1111
")的地址替换为 main 的'}'
       sub esp,4 //还原栈指针

  mov eax, dz
  push eax
  ret
  }
}
void main()
{
  HMODULE h = GetModuleHandle(NULL);
  dz1= dz =(DWORD)h;
  dz+=0x1077; //0x1062为 printf("2222
")相对于代码段基址的偏移
  dz1+=0x1085;//0x1085为 main函数的'}' 相对于代码段基址的偏移
  __asm
  {
    call fun1
  }
  printf("1111
");
  printf("2222
");
}

这样 main函数执行ret后: eip= '}' 地方的地址, 程序结束,运行结果为:
2222

原文地址:https://www.cnblogs.com/mayingkun/p/4645566.html