• 逆向分析练习二(回文数判断)


    逆向分析练习二(回文数判断)

    今天依旧是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          
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    分析

    这里只做简略的描述,具体的分析在汇编代码的注释中

    1. 首先按流程看下来看到0076359C这里发现这是个比较跳转可以初步判定7635B9h这里应该是一个块的结束
    2. 在这块代码中间有一个新接触到的指令cdq下面简单介绍一下这个指令
      1. 这个指令把 EAX 的第 31 bit 复制到 EDX 的每一个 bit 上。 它大多出现在除法运算之前。它实际的作用只是把EDX的所有位都设成EAX最高位的值。也就是说,当EAX <80000000, EDX 为00000000;当EAX >= 80000000, EDX 则为FFFFFFFF。
    3. 看到cdq就应该知道下面应该是一个除法操作,继续往下看,会发现确实如此,在对x除10
    4. 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;
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    源代码

    
    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;
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    Android学习笔记 42. RxJava基本使用
    从零用VitePress搭建博客教程(5) - 如何自定义页面模板、给页面添加独有的className和使页面标题变成侧边目录?
    Java异常、继承结构、自定义异常、SpringBoot中捕获处理异常
    【多线程】线程安全(重点)
    超声波清洗机好用吗?哪家超声波清洗机好?不错超声波清洗机推荐
    HJ107 求解立方根
    单数据改多数据导致,LinkedHashMap读取视图数据出错
    Mysql数据库管理-Innodb 内存优化分析
    centos7安装tomcat9过程
    Lua的resty-request库写的一个爬虫
  • 原文地址:https://blog.csdn.net/qq_43147121/article/details/128037669