首页
社区
课程
招聘
[旧帖] 每次遇到这种CALL 就迷糊了,lea 如何转化成mov? 0.00雪花
发表于: 2015-2-10 15:22 1975

[旧帖] 每次遇到这种CALL 就迷糊了,lea 如何转化成mov? 0.00雪花

2015-2-10 15:22
1975
每次遇到这种CALL 就迷糊了,lea 如何转化成mov?
004F4429  |.  8D55 E8       lea     edx, dword ptr [ebp-18]                     ;  100690
004F442C  |.  8D45 F0       lea     eax, dword ptr [ebp-10]                      ;  0
004F442F  |.  E8 400EFBFF   call    004A5274            ;  TfrmMain_FormKeyDown

call    004A5274 内部:

004A5274  /$  55            push    ebp
004A5275  |.  8BEC          mov     ebp, esp
004A5277  |.  50            push    eax
004A5278  |.  B8 0A000000   mov     eax, 0A
004A527D  |>  81C4 04F0FFFF /add     esp, -0FFC
004A5283  |.  50            |push    eax
004A5284  |.  48            |dec     eax
004A5285  |.^ 75 F6         \jnz     short 004A527D
004A5287  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
004A528A  |.  83C4 F8       add     esp, -8
004A528D  |.  53            push    ebx
004A528E  |.  56            push    esi                                                 ;
004A528F  |.  57            push    edi
004A5290  |.  8BF0          mov     esi, eax                                            ;
004A5292  |.  8D7D F4       lea     edi, dword ptr [ebp-C]
004A5295  |.  A5            movs    dword ptr es:[edi], dword ptr [esi]
004A5296  |.  A5            movs    dword ptr es:[edi], dword ptr [esi]
004A5297  |.  A5            movs    dword ptr es:[edi], dword ptr [esi]
004A5298  |.  8BDA          mov     ebx, edx                                            ;  
004A529A  |.  8D95 F45FFFFF lea     edx, dword ptr [ebp+FFFF5FF4]
004A52A0  |.  8D45 F4       lea     eax, dword ptr [ebp-C]
004A52A3  |.  B9 0C000000   mov     ecx, 0C
004A52A8  |.  E8 A7DEF5FF   call    00403154
004A52D5  |.  5F            pop     edi
004A52D6  |.  5E            pop     esi
004A52D7  |.  5B            pop     ebx
004A52D8  |.  8BE5          mov     esp, ebp
004A52DA  |.  5D            pop     ebp
004A52DB  \.  C3            retn

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
2
004F4429  |.  8D55 E8       lea     edx, dword ptr [ebp-18]                     ;  100690
004F442C  |.  8D45 F0       lea     eax, dword ptr [ebp-10]                      ;  0
004F442F  |.  E8 400EFBFF   call    004A5274            ;  TfrmMain_FormKeyDown

lea 虽然是加载有效地址的汇编指令助记符,但多数情况用于算术运算,不过在上面的主调函数中,应该确实是
加载有效地址。
例如,将 [ebp-18]的地址加载到edx中,将 [ebp-10]的地址加载到eax中,这是为调用地址 004A5274 处的函数前,做好传递参数的准备,两个参数的地址现在位于edx与eax中,照理讲,还需要将2个参数压栈,即
push [edx]
push [eax]
这样,被调函数才能正确接收到参数,但是在楼主的输出信息中没有看到上面两条指令,可能是编译器出于性能优化的原因而省略了,
注意上面的 push [edx] ,这种格式为“存储器引用”,因为lea的关系,现在edx中保存的是注释中100690的地址,要取得该地址处的值,即100690,就需要存储器引用才能取值(如果你确定被调函数接收的参数确实是类似100690的值)
上面的汇编指令如果用 mov 来改写,应该如下:

mov     edx, dword ptr [ebp-18]                     ;  100690
push edx                                                                                              ; 第二个参数先压栈
mov     eax, dword ptr [ebp-10]                      ;  0
push eax                                                                                             ;第一个参数压栈
call    004A5274                                                                    ;TfrmMain_FormKeyDown

当然,由于新增了2条push 指令,call指令的地址不会是 004A5274 ,具体取决2条push指令的对应机器码字节长度。
2015-2-10 15:46
0
雪    币: 195
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
非常感谢,我先慢慢消化下~
2015-2-10 15:52
0
雪    币: 398
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
根据楼主的反汇编代码,可以初步看出是DELPHI编写的程序,根据DELPHI程序函数的调用约定,参数如果少于三个的话,是采用EAX,EDX,ECX来传递参数的,所以
004F4429  |.  8D55 E8       lea     edx, dword ptr [ebp-18]                     ;  100690
004F442C  |.  8D45 F0       lea     eax, dword ptr [ebp-10]                      ;  0
004F442F  |.  E8 400EFBFF   call    004A5274            ;  TfrmMain_FormKeyDown

这段代码的意思就是 call    004A5274(eax,edx);
如果要写成MOV的意思,就是:
mov edx,ebp-18           
mov eax,ebp-10
call 004a5274
2015-2-12 20:01
0
雪    币: 195
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
[QUOTE=zbig;1353383]根据楼主的反汇编代码,可以初步看出是DELPHI编写的程序,根据DELPHI程序函数的调用约定,参数如果少于三个的话,是采用EAX,EDX,ECX来传递参数的,所以
004F4429  |.  8D55 E8       lea     edx, dword ptr [ebp-18]        ...[/QUOTE]
谢谢
这样写 mov edx,ebp-18 调试不通过
ebp-18 应该是个局部变量吧
是不是先计算出 ebp-18的值然后 mov 给eax
2015-2-13 08:50
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
6
根据ebp的负偏移来访问的栈地址,应该是局部变量没错.
这是个双字(4字节的局部变量) .即 dowrd ptr
[ebp-18]是一种叫做"存储器寻址"的操作数模式,
用于取得"栈底指针指向的地址处,偏移18h字节地址处的值",然后将该值复制到eax中
2015-2-13 09:47
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
保持队型
2015-2-13 11:17
0
雪    币: 195
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
[QUOTE=shayi;1353457]根据ebp的负偏移来访问的栈地址,应该是局部变量没错.
这是个双字(4字节的局部变量) .即 dowrd ptr
[ebp-18]是一种叫做"存储器寻址"的操作数模式,
用于取得"栈底指针指向的地址处,偏移18h字节地址处的值",然后将该值复制到eax...[/QUOTE]
如何自己定义2个变量,然后传给他
例如:
Var
S1,S2:STRING;
BEGIN
  ASM
  PUSHAD
  lea     edx, S1         
  lea     eax, S2         
  call    004A5274        
  POPAD
  END;
END;
不会弄~~
2015-2-13 15:14
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢解答,受益非浅
2015-2-13 19:33
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
10
假设变量s1,s2在main函数栈中分配,各为指向16字节长度字符串的起始字符地址的指针,main函数使用ebp寻址栈变量,两个字符串中的每个字符都占1字节,则有如下汇编代码(Intel & NASM风格)

******************
main函数序言部分
******************

push   ebp
mov   esp,     ebp
sub     esp,    24        ;由于下面要分配2个字符串,共32字节(等于16进制的20h字节)的空间,因
                                 ;此这里将esp,即栈顶,向内存低址方向,扩展24h字节,
                                ;多余的4字节为索引

*****************
main函数主体
******************

mov    ecx,     [ebp-24]   ;[ebp-24]处的4字节存储单元,作为索引寻址每个字符串中的字符,现
                                         ;在ecx作为索引

mov     eax,       [ebp-20]   ;取得变量s1
mov     ecx,   0     ;第一个字符索引为0
mov     [eax+ecx*1],    0x61      ;将s1指向的字符串的第一个字符設为 'a',索引乘以字符大小1,即为偏移量,偏移量加上作为起始地址的eax,即能找到目标字符

mov     edx,      [ebp-10]    ;取得变量s2
add      ecx,   1                   ;第二个字符索引为1
mov     [edx+ecx*1],      0x62     ;将s2指向的字符串的第二个字符設为 'b'

mov   eax,     [ebp-10]
push   eax         ;s2,作为第2个参数先压栈
mov    edx,     [ebp-20]
push   edx         ;s1作为第1个参数后压栈
call     004A5274
add     8          ;由主调函数清除压栈参数

************
main函数尾声
************
xor    eax,   eax
add    esp,     24    ;清除3个main的局部变量
leave
retn
2015-2-13 20:21
0
雪    币: 195
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
太热心了,非常感谢! 估计我得消化一阵子!
我是在delphi里面调用这个call
等我移植到delphi试试
十分谢谢
2015-2-13 21:22
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
12
其实我这个例子是用2个16字节的局部"字符数组"来代替字符串,模拟的汇编代码,可能与真实的编译器生成的代码有所差异

你应该用高级语言编写操作字符串的例程,然后用delphi编译器编译成汇编文件,查看汇编文件中的内容,
这样就可以理解处理器是如何读写字符串的,后者说白了就是连续的相同大小的内存区域(每个ASCII字符占1字节,每个unicode字符占2字节),这块区域又叫缓冲区,通常,为了安全起见,假设程序员在编程时指定16字节空间,编译器实际分配的空间要大一些,通常是可以被4字节整除的缓冲区大小,如果读写这块缓冲区的函数没有检查用户输入的数据长度是否存在"数组越界",那么就给缓冲区溢出攻击创造了条件,例如strcpy()

如果delphi编译器不支持生成中间的汇编文件,那么用IDA PRO 加载并反汇编最终的可执行文件,查看汇编代码即可.
2015-2-13 22:21
0
雪    币: 195
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢,谢谢,谢谢
测试完美通过!
自己总结一下:
lea     edx, dword ptr [ebp-C0]
把一个变量的地址给edx
那么可以自己先定义一个变量
之后取这个变量的地址
在给edx
至于这个变量里面是什么内容,可以跟踪到,直接赋值即可
例如:delphi 里面 简单的写下,方便后面的人
var
s:STRING;
ADD:^INTEGER;
BEGIN
S:='1';
ADD:=@S
END

多谢指点,以后在遇到类似的,就可以应付了
非常感谢!
2015-2-15 20:01
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
14
[QUOTE=sunyesy;1353987]谢谢,谢谢,谢谢
测试完美通过!
自己总结一下:
lea     edx, dword ptr [ebp-C0]
把一个变量的地址给edx
那么可以自己先定义一个变量
之后取这个变量的地址
在给edx
至于这个变量里面是什么内容,可以跟踪到,直接赋值即可
例如:delphi 里面 简单的写下,方便...[/QUOTE]

您太客气了,交流本来就是一个相互提高自身技术水平的过程.
像我就不懂delphi汇编语法,以后 遇到还得向你请教
2015-2-15 20:34
0
雪    币: 195
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
我喜欢这里的氛围,尤其是你的指导方式,循循善诱,
在你的一点一点的提示下,终于弄通了,感觉非常棒!
而且每次回答的都能到点上
我按照您的提示,一点一点摸索,终于搞懂了~
新年快乐~
2015-2-15 21:04
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
16
happy new year
2015-2-15 21:29
0
游客
登录 | 注册 方可回帖
返回
//