逆向分析练习二(回文数判断)
今天依旧是debug版本的反汇编代码逆向分析,等能够熟练的分析debug版本的汇编代码后再看o1和o2优化下的代码会更简单。
这次分析的代码包含了大量的除法和取余数运算,如果没有对这方面指令使用经验的话也算是比较难了
能够帮助大家快速了解到除法运算这方面的逆向实现
题目描述
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121
是回文,而123
不是。
debug版汇编代码
00763580 push ebp //依旧是保存并提升栈
00763581 mov ebp,esp
00763583 sub esp,0D8h
00763589 push ebx
0076358A push esi
0076358B push edi
0076358C lea edi,[ebp-0D8h]
00763592 mov ecx,36h
00763597 mov eax,0CCCCCCCCh
0076359C rep stos dword ptr es:[edi] //从这里开始下面则是业务代码
0076359E cmp dword ptr [x],0 //这里应该是判断x>=0
007635A2 jl isPalindrome+39h (7635B9h) //这里如果<0就跳到7635B9h
007635A4 mov eax,dword ptr [x] //这里eax=x
007635A7 cdq //执行cdq根据eax是否大于 8000 0000来设置edx
007635A8 mov ecx,0Ah //ecx = 10
007635AD idiv eax,ecx //eax = eax/10
007635AF test edx,edx //判断edx是否为0
007635B1 jne isPalindrome+3Dh (7635BDh) //这么看来这里应该是对x除法后的余数判空
007635B3 cmp dword ptr [x],0 //如果小于10了就结束
007635B7 je isPalindrome+3Dh (7635BDh)
007635B9 xor al,al //所以说这里应该是一个块的结束
007635BB jmp isPalindrome+95h (763615h) //这里似乎直接跳转到结束了
007635BD mov dword ptr [flag],0 //又一个块的开始,flag=0
007635C4 mov eax,dword ptr [x] //eax = x
007635C7 mov dword ptr [t],eax //t=x
007635CA cmp dword ptr [x],0 //x>0 //从下面看回来会发现这是一个循环的开始
007635CE jle isPalindrome+76h (7635F6h) //一个块的开始
007635D0 mov ecx,dword ptr [flag] //ecx = flag
007635D3 imul ecx,ecx,0Ah //flag*10
007635D6 mov eax,dword ptr [x] //eax = x
007635D9 cdq //这是又要做除法了
007635DA mov esi,0Ah
007635DF idiv eax,esi
007635E1 add ecx,edx //这上面应该是一个除10之后对余数做加法到ecx
007635E3 mov dword ptr [flag],ecx //flag = ecx
007635E6 mov eax,dword ptr [x] //eax = x
007635E9 cdq
007635EA mov ecx,0Ah
007635EF idiv eax,ecx
007635F1 mov dword ptr [x],eax //这次只做除法然后写回x
007635F4 jmp isPalindrome+4Ah (7635CAh) //跳回循环的头部
007635F6 mov eax,dword ptr [t] //跳出
007635F9 cmp eax,dword ptr [flag]
007635FC je isPalindrome+8Dh (76360Dh)
007635FE mov eax,dword ptr [t]
00763601 cdq
00763602 mov ecx,0Ah
00763607 idiv eax,ecx
00763609 test eax,eax
0076360B jne isPalindrome+93h (763613h)
0076360D mov al,1 //这里是返回1
0076360F jmp isPalindrome+95h (763615h)
00763611 jmp isPalindrome+95h (763615h)
00763613 xor al,al //这里是返回0
00763615 pop edi
00763616 pop esi
00763617 pop ebx
00763618 mov esp,ebp
0076361A pop ebp
0076361B ret
分析
这里只做简略的描述,具体的分析在汇编代码的注释中
- 首先按流程看下来看到0076359C这里发现这是个比较跳转可以初步判定7635B9h这里应该是一个块的结束
- 在这块代码中间有一个新接触到的指令cdq下面简单介绍一下这个指令
- 这个指令把 EAX 的第 31 bit 复制到 EDX 的每一个 bit 上。 它大多出现在除法运算之前。它实际的作用只是把EDX的所有位都设成EAX最高位的值。也就是说,当EAX <80000000, EDX 为00000000;当EAX >= 80000000, EDX 则为FFFFFFFF。
- 看到cdq就应该知道下面应该是一个除法操作,继续往下看,会发现确实如此,在对x除10
- test指令:对两个操作数做and运算,并改变标记位
int func (x){
if(x < 0 || (x%10==0 && x != 0)) return 0;
int flag = 0,t=x;
while(x>=0){
flag = flag*10 + x%10;
x=x/10;
}
if(t != flag){
if(x/10==0)
return 1;
}
return 0;
}
源代码
bool isPalindrome(long int x){
if(x<0||(x%10==0&&x!=0)){
return false;}
long int flag=0;long int t=x;
while(x>0){
flag=flag*10+x%10;
x/=10;
}
if(t==flag||t/10==0){
return true;}
else {
return false;
}
}