[逆向]顺序结构:四则运算

简单的顺序结构逆向分析-->四则运算

使用工具:VS2013,Ollydbg

 

源代码:

#include <windows.h>

//定义全局变量
int nGlobal = 5; 
char cGlobal = 'a';

int main()
{
	//定义局部变量
	int nLocal_1 = 0;
	int nLocal_2 = 8;
	//变量之间进行运算
	nLocal_1 += nGlobal;
	nLocal_2 = nLocal_1 * 4;
	nLocal_1 += cGlobal;
	cGlobal += 2;
	nLocal_1 -= 5;
	nLocal_2 /= 2;

	return 0;
}
 

为了更好的锻炼读汇编的能力,在VS的debug或者release目录下,把pdb符号文件删除,否则加载到Ollydbg中会出现很多提示,导致分析难度大大降低

 

使用OllyDbg加载后,main()函数:

00121380    55              push ebp
00121381    8BEC            mov ebp,esp
00121383    81EC D8000000   sub esp,0xD8
00121389    53              push ebx
0012138A    56              push esi                             ; Reverse_.<ModuleEntryPoint>
0012138B    57              push edi
0012138C    8DBD 28FFFFFF   lea edi,dword ptr ss:[ebp-0xD8]
00121392    B9 36000000     mov ecx,0x36
00121397    B8 CCCCCCCC     mov eax,0xCCCCCCCC
0012139C    F3:AB           rep stos dword ptr es:[edi]
0012139E    C745 F8 0000000>mov dword ptr ss:[ebp-0x8],0x0       ; 局部变量1 int nLocal_1 = 0;
001213A5    C745 EC 0800000>mov dword ptr ss:[ebp-0x14],0x8      ; 局部变量2 int nLocal_2 = 8;
001213AC    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]       ; 局部变量1放到EAX中,为后面的加法做准备
001213AF    0305 00801200   add eax,dword ptr ds:[0x128000]      ; nLocal_1 = nLocal_1+nGlobal
001213B5    8945 F8         mov dword ptr ss:[ebp-0x8],eax       ; 把加完之后的值赋值给nLocal_1,相当于更新nLocal_1的值
001213B8    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]       ; 把新的nLocal_1的值放到EAX中,为后面的乘法做准备
001213BB    C1E0 02         shl eax,0x2                          ; 左移2,就相当于*4
001213BE    8945 EC         mov dword ptr ss:[ebp-0x14],eax      ; nLocal_2 = nLocal_1 * 
001213C1    0FBE05 04801200 movsx eax,byte ptr ds:[0x128004]     ; 把全局变量cGlobal放到EAX中,准备加法
001213C8    0345 F8         add eax,dword ptr ss:[ebp-0x8]       ; nLocal_1 = nLocal_1+cGlobal
001213CB    8945 F8         mov dword ptr ss:[ebp-0x8],eax       ; 更新nLocal_1的值
001213CE    0FBE05 04801200 movsx eax,byte ptr ds:[0x128004]
001213D5    83C0 02         add eax,0x2
001213D8    A2 04801200     mov byte ptr ds:[0x128004],al        ; cGlobal = cGlobal + 2;
001213DD    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]
001213E0    83E8 05         sub eax,0x5
001213E3    8945 F8         mov dword ptr ss:[ebp-0x8],eax       ; nLocal_1 = nLocal_1 - 5;
001213E6    8B45 EC         mov eax,dword ptr ss:[ebp-0x14]
001213E9    99              cdq                                  ; 下面会有介绍
001213EA    2BC2            sub eax,edx
001213EC    D1F8            sar eax,1                            ; 右移1位,相当于除以2
001213EE    8945 EC         mov dword ptr ss:[ebp-0x14],eax      ; nLocal_2 = nLocal_2 / 2;
001213F1    33C0            xor eax,eax                          ; 把EAX清零
001213F3    5F              pop edi                              ; 还原edi,保证edi的值和刚进入函数时的值相同
001213F4    5E              pop esi                              ; 还原esi
001213F5    5B              pop ebx                              ; 还原ebx
001213F6    8BE5            mov esp,ebp
001213F8    5D              pop ebp                              ; Reverse_.<ModuleEntryPoint>
001213F9    C3              retn

 

上面出现了几个不是很常见的指令,接下来单独介绍一下:

1、rep stos

rep是重复指令,stos表示把EAX中的值放到EDI指向的地址中,相当于是给堆栈初始化一片区域

EDI地址变化的方向由DF决定,DF = 1,EDI的值会往递减的方向变化;如果DF= 0,那么EDI的值就会往递增的方向变化

 

完整的指令:

mov ecx,0x36

mov eax,0xCCCCCCCC

rep stos dword ptr es:[edi]

上面的指令功能就是把edi中地址指向的值赋值成EAX中的值,赋值的次数为ECX中的值

 

可以在OD中观察一下指令执行之后堆栈中的变化

在指令执行之前,EDI的值是0xDDFB40

DF = 0

 

 

堆栈中情况是这样的:

 

接下来执行一下rep stos这条指令

可以看到从0xDDFB40这个地址开始,堆栈中的值都被赋值成了0xCCCCCCCC

 

因为 DF = 0,所以可以看到EDI的地址是往递增的方向变化的

循环次数ECX = 0x36,所以地址的变化是0x36 * 4 = 0xD8,也就是赋值一直到0xDDFB40 + 0xD8 = 0xDDFC18 为止

 

 

2、movsx

movsx eax,byte ptr ds:[0x128004]

带符号扩展,并把扩展之后的值给eax

如果最高位是1,那么扩展位就用1填充,如果最高位是0,那么扩展位就用0填充

比如说 

mov BL,0x80

movsx AX,BL

执行完movsx之后AX中的值就是0xFF80,因为0x80转换成二进制来看的话就是1000 0000,对于有符号的数来说,最高位为1就是表示负数,所以由一个字节扩展成两个字节,结果就是1111 1111 1000 0000,扩展位用1填充,转换成十六进制就是0xFF80

如果是

mov BL,0x50

movsx AX,BL

那就是0x50 = 0101 0000,最高位为0,扩展位也是用0填充,一个字节扩展成两字节就是 0000 0000 0101 0000,执行完movsx之后AX=0x0050

 

3、cdq

Convert Double to Quad,意思就是把双字(四字节,一个字 = 两字节)扩展为四字(八字节),因为扩展成了8字节,一个EAX放不到,所以把八字节的高四字节放到了EDX中。

这个指令常用于扩展 被除数 ,在以前指令集规定除数必须是被除数的一半长,目前还在用这个规定。

这个指令一般是在计算除法的时候出现

 

4、shl

逻辑左移,最低位补0

格式:

SHL DST,常量

或者

SHL DST,CL

左移的位数根据常量的值和CL的值来确定

比如说:

mov eax,0x12

shl eax,2

首先0x12 = 0001 0010

左移2位,结果变成 0100 1000=0x48

左移指令可以用在乘法计算中,左移1位表示乘以2,左移2位表示乘以4,以此类推

所以0x12左移2位就是0x12*4=0x48

 

5、sar

算术右移,最高位补什么值由符号位决定,如果最高位是0,那么补0;如果最高位是1,那么补1,也就是算术右移最高位保持不变

比如说

mov eax,0x80

sar eax,1

由于0x80最高位是符号位,所以右移的时候最高位补1

1000 0000 -> 1110 0000

如果是

mov eax,0x52

sar eax,2

那么结果就是 0101 0010 -> 0001 0100 

右移也相当于是除法,右移一位除以2,右移2位除以4

 

6、xor

用来计算两个数异或的结果,如果是异或两个相同的寄存器,那就是在执行寄存器置零操作

 

搜索关注公众号[逆向小生],不定期更新逆向工程师需要掌握的技能,包括Windows和Android方面的逆向,还有作为一个逆向工程师的思维模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值