Chinaunix首页 | 论坛 | 博客
  • 博客访问: 97508
  • 博文数量: 29
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 476
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-07 15:10
文章分类

全部博文(29)

文章存档

2011年(1)

2008年(28)

我的朋友

分类: C/C++

2008-09-24 11:40:53

   VC6下的几行简单的代码:

 

#include <stdio.h>

int main(void)
{
    int a;
    a = 5;
    return 0;
}

   对应的汇编代码:

1:
2: #include <stdio.h>
3:
4: int main(void)
5: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,44h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-44h]
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
6: int a;
7: a = 5;
00401028 mov dword ptr [ebp-4],5
8: return 0;
0040102F xor eax,eax
9: }
00401031 pop edi
00401032 pop esi
00401033 pop ebx
00401034 mov esp,ebp
00401036 pop ebp
00401037 ret

1.

EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:
  
  push ebp     ;保存当前ebp
  mov ebp,esp  ;EBP设为当前堆栈指针
  sub esp, xxx ;预留xxx字节给函数临时变量.减小stack的指针(注意,stack是从内存的高端向低端生长的),为局部变量保留一些空间,这里的44h不是固定的,由编译器计算得来
  ...

这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作:

   mov esp,ebp
   pop ebp
   ret

即可.恢复esp,ebp,这时函数的返回地址就在栈顶,调用ret就可以返回了。

2.

   00401016 push ebx
   00401017 push esi
   00401018 push edi

  EBX是"基地址"(base)寄存器, 在内存寻址时存放基地址.ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

3.

  00401019 lea edi,[ebp-44h]
  0040101C mov ecx,11h
  00401021 mov eax,0CCCCCCCCh
  00401026 rep stos dword ptr [edi]


用0xCC填充局部变量空间。这是Debug模式特有的,如果是字符串,你就看到被初始化成"烫烫烫烫烫烫"

4.

   00401028   mov         dword ptr [ebp-4],5

   [ebp-4]就是第一个局部变量a了

5.

   0040102F   xor eax,eax

  函数的结果都是放在eax中(ps:你可以在vc的watch窗口输入@EAX,就可以直接看到函数返回值了)

阅读(1026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~