登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 95|回复: 1

X86C++反汇编09.switch case语句

[复制链接]

94

主题

-6

回帖

126

积分

网站编辑

积分
126
发表于 2025-5-18 16:04:29 | 显示全部楼层 |阅读模式

case 分支不超过3个

当 case 分支少于3个,不会怎么优化,直接3个跳转,这种很像 if esle ,但是跟if esle 有区别,它跳转和跳转之间没有实质性代码,只有影响标志位代码

其次 它的代码结构分2部分

img

而且必须这么设计,因为break的原因

case种有break 就跳走,没有的话就顺着走,且不做判定,一旦把case 值: 插入 case jxx 那么一旦遇到break,就要做比较

int main(int argc, char* argv[])
{
   switch(argc)
   {
   case 0:
       printf("case 0");
   case 1:
       printf("case 1");
       break;
   case 2:
       printf("case 2");
   }
   return 0;
}

反汇编代码:
debug 版
     mov     eax, [ebp+argc]
     mov     [ebp+var_4], eax
     cmp     [ebp+var_4], 0
     jz      short loc_401042
     cmp     [ebp+var_4], 1
     jz      short loc_40104F
     cmp     [ebp+var_4], 2
     jz      short loc_40105E
     jmp     short loc_40106B
loc_401042:                          
     push    offset Format   ; "case 0"
     call    _printf
     add     esp, 4
loc_40104F:                         
     push    offset aCase1   ; "case 1"
     call    _printf
     add     esp, 4
     jmp     short loc_40106B
loc_40105E:                           
     push    offset aCase2   ; "case 2"
     call    _printf
     add     esp, 4
loc_40106B: 

分析:  遇到上面定式,就可以判断位 switch case ,还原时就可以无脑还原 ,jxx 比的是谁 case 就是 谁,而且需要看最后一个跳转,如果是  jne  或者  jnz 就是  default 或者 switch end , jne 或者 jnz后面的jmp 就是 case,否则如果是 jz 或者  je,后面的jmp 就是    default 或者 switch end 

release 版  有优化
     mov     eax, [esp+argc]
     sub     eax, 0
     jz      short loc_40101F     ;case 0
     dec     eax                            
     jz      short loc_40102C     ;case  1  
     dec     eax
     jnz     short loc_401039      ;case  2 ,因为前面已经减1,再减1就是 减2
     push    offset aCase2   ; "case 2"
     call    sub_401040
     add     esp, 4
     xor     eax, eax
     retn
loc_40101F:                           
     push    offset aCase0   ; "case 0"
     call    sub_401040
     add     esp, 4
loc_40102C:                           
     push    offset aCase1   ; "case 1"
     call    sub_401040
     add     esp, 4
loc_401039:  

分析: 有无default 的的区别 看把 break;   break 肯定不执行 default  的代码,  break肯定跳到 switch  end
看判断 跟 jnz 跳出的是不是同一个点,是的话就没有 default ,否则就是有
int main(int argc, char* argv[])
{
   switch(argc)
   {
   default: 
         printf("default:");
         break;
   case 0:
       printf("case 0");
   case 1:
       printf("case 1");
       break;
   case 2:
       printf("case 2");
   }
   return 0;
}
反汇编代码;
     mov     eax, [esp+argc]
     sub     eax, 0
     jz      short loc_40102F      ; -0 = 0 CASE 0
     dec     eax
     jz      short loc_40103C      ; -1= 0 CASE 1
     dec     eax
     jz      short loc_40101F       ; -1-1= 0 CASE 2
        ;default  
     push    offset aDefault ;   "default:"
     call    sub_401050
     add     esp, 4
     xor     eax, eax
     retn
loc_40101F:                           
     push    offset aCase2   ; "case 2"
     call    sub_401050
     add     esp, 4
     xor     eax, eax
     retn
loc_40102F:                          
     push    offset aCase0   ; "case 0"
     call    sub_401050
     add     esp, 4
loc_40103C:                          
     push    offset aCase1   ; "case 1"
     call    sub_401050

case 分支大于3 且较为连续

会做表

int main(int argc, char* argv[])
{
   switch(argc)
   {
   default: 
         printf("default:");
         break;
   case 0:
       printf("case 0");
   case 1:
       printf("case 1");
       break;
   case 2:
       printf("case 2");
   case 3:
       printf("case 3");
   case 5:
       printf("case 5");
   case 6:
       printf("case 6");
   }
   printf("hello");
   printf("hello");
   return 0;
}
反汇编代码:
     mov     eax, [ebp+argc]
     mov     [ebp+var_4], eax
     cmp     [ebp+var_4], 6              ;跟 case值的区间比较
     ja      short def_40D747           ;这里就是 switch end 或者default,至于是否有 default 需要后面验证
     mov     ecx, [ebp+var_4]
     jmp     ds:jpt_40D747[ecx*4]      ; 寻址  数组首地址40D747
def_40D747:                                                                              
     push    offset Format   ; jumptable 0040D747 default case, case 4
     call    _printf
     add     esp, 4
     jmp     short loc_40D7AD
loc_40D75D:                          
     push    offset aCase0   ; jumptable 0040D747 case 0
     call    _printf
     add     esp, 4
loc_40D76A:                             ;
     push    offset aCase1   ; jumptable 0040D747 case 1
     call    _printf
     add     esp, 4
     jmp     short loc_40D7AD
loc_40D779:                           
     push    offset aCase2   ; jumptable 0040D747 case 2
     call    _printf
     add     esp, 4
loc_40D786:                          
     push    offset aCase3   ; jumptable 0040D747 case 3
     call    _printf
     add     esp, 4
loc_40D793:  
     push    offset aCase5   ; jumptable 0040D747 case 5
     call    _printf
     add     esp, 4
loc_40D7A0:  
     push    offset aCase6   ; jumptable 0040D747 case 6
     call    _printf
     add     esp, 4
loc_40D7AD:                          
     push    offset aHello   ; "hello"
     call    _printf
     add     esp, 4
     push    offset aHello   ; "hello"
     call    _printf

分析:

先观察 eax 的取值范围(0-6),在跳转到调表 ,分别命名为 0 - 6,接着看每个case,看谁有 break,找到有break 的地方直接命名为 default ,接着论证 default 分时是否存在, 当把代码外提,内联都搞清楚以后如果 default 和 switch end 重合,说明没有 default 分支

跳表的数组

img

img

当如果 case 不是从 0 - 6 而是 100 -106 , 那么就会 先减去最小 case 值

int main(int argc, char* argv[])
{
    switch (argc)
    {
    default:
        printf("default:");
        break;
    case 100:
        printf("case 0");
    case 101:
        printf("case 1");
        break;
    case 102:
        printf("case 2");
    case 103:
        printf("case 3");
    case 105:
        printf("case 5");
    case 106:
        printf("case 6");
    }
    printf("hello");
    printf("hello");
    return 0;
}
反汇编代码:

image.png

case分支大于3且不连续

case 的 值区间超过12 ,就会换方案

再按上面坐标 ,需要很多四字节来放地址 ,大部分都是 default ,所以不划算

int main(int argc, char* argv[])
{
    switch (argc)
    {
    default:
        printf("default:");
        break;
    case 100:
        printf("case 0");
    case 111:
        printf("case 1");
        break;
    case 122:
        printf("case 2");
    case 133:
        printf("case 3");
    case 145:
        printf("case 5");
    case 156:
        printf("case 6");
    }
    printf("hello");
    printf("hello");
    return 0;
}

反汇编代码:
     push    ebp
     mov     ebp, esp
     mov     eax, [ebp+argc]
     add     eax, 0FFFFFF9Ch ; switch 57 cases
     cmp     eax, 38h
     ja      short $LN4   
     movzx   eax, ds:byte_4010E0[eax]     ;第一次寻址
     jmp     ds:jpt_401055[eax*4]                ;  ;第二次寻址

$LN5:                                 
     push    offset _Format  ; jumptable 00401055 case 100
     call    _printf
     add     esp, 4
$LN6:                                
     mov     eax, offset aCase1 ; jumptable 00401055 case 111
     jmp     short loc_4010A3
$LN7:                             
     push    offset aCase2   ; jumptable 00401055 case 122
     call    _printf
     add     esp, 4

$LN8:                              
     push    offset aCase3   ; jumptable 00401055 case 133
     call    _printf
     add     esp, 4
$LN9:                                 
     push    offset aCase5   ; jumptable 00401055 case 145
     call    _printf
     add     esp, 4
$LN10:                               
     mov     eax, offset aCase6 ; jumptable 00401055 case 156
     jmp     short loc_4010A3
$LN4:       
     mov     eax, offset aDefault ; 
loc_4010A3:                       
     push    eax             ; _Format
     call    _printf
     push    offset aHello   ; "hello"
     call    _printf
     push    offset aHello   ; "hello"
     call    _printf

分析: 采用二次寻址来方式 来获取跳转地址

先用 一个 int 数组 保存 case 的 跳转坐标 ,在用一个char 数组 保存 每个 case 区间值 跳转 的 坐标 在坐标数组的索引, 访问时 现根据 索引数组 拿索引,在 把索引转 整形 到 坐标数组拿对应 坐标,再跳转

img

说明 case 的区间是 100 - 156

对应的下标索引表

img

因为大部分 是 default ,所以 6对应的 derault 跳转的地址 , 然后 其他 非 6 值 表示 case的的值

例如 0 表示 100 +0 = 100 => case 100 表示 坐标表索引为0的坐标就是 case100 跳转的坐标 , 1=> 100 +11 = 111 => case 111 表示 坐标表索引为1的坐标就是 case111 跳转的坐标 , 2 => 100 + 22 => case 122 表示 坐标表索引为2的坐标就是 case122 跳转的坐标, 100表示 case 最小值 , 后面加的值表示在数组中的索引

对应的地址表:

img

img

带位图的位图保存方式 CreateCompatibleBitmap

img

先用一个数组保存 颜色种类 (调色板),在用另一个 char 数组 保存每个 坐标 对应的 颜色在 颜色数组的下标,这样就只需要一个 char 数组就可以了,这样就不需要用 int 数组 , 因此可以节省大量空间 ,但缺点就是需要2次 数组寻址,需要先在坐标数组 取出 对应颜色的下标 转成 整形 ,在根据下标在 颜色数组取出对应的颜色 ,而且 颜色种类不能超过 256种

混合方案

switch 是一个多分支的机器优化方案,优化的时候视为各个分支节点命中率均等,且必须是整形 或 类整形.不能是区间和浮点,

int main(int argc, char* argv[])
{
    switch (argc)
    {
    default:
        printf("default:");
        break;
case 100:
        printf("case 0");
case 200:
        printf("case 0");
case 300:
        printf("case 0");
case 400:
        printf("case 0");
case 500:
        printf("case 0");
case 1100:
        printf("case 0");
case 2111:
        printf("case 1");
        break;
 case 3122:
        printf("case 2");
case 4133:
        printf("case 3");
case 5545:
        printf("case 5");
case 6656:
        printf("case 6");
    }
    printf("hello");
    printf("hello");
    return 0;
}

编译器优化时,  使用 平衡比较数  来优化   会先对  csae 的值进行排序

100      200      300     400     500     1100    2111     3122     4133    5545     6656

然后先比 中间值    1100  
如果 等于 直接走   
如果  小于    在 跟左边 比较  ,跟左边比较 是也会 先跟中间值比较
如果   大于    在 跟到边 比较  ,跟右边比较 是也会 先跟中间值比较
一直递归比较值回到 一边值 满足上面 3种情况之一 ,就采用上面 的 对应的  优化方案 
                                                                1100
                                   <                             =                                  >
                                  300                                                              4133  
     <                            =                        >             <                            =                          >  
=100, =200                              =400,=500   =2111, =3122                                    =5545  ,=6656 

这种方案还原 直接找等于 就行了 ,大于小于 都是引导  ,等于的值 就是 case值
比较大于,小于,等于 2个跳转就够了,因此上式的特征就是很多 2跳在一起 ,其中 je 肯定有, 另一个 jg 或 jl 之一

周末作业

  1. GreenVPN 对配置文件进行了加密 分析,解析出解密算法,并用高级语言还原出源码,并解密出远程服务器信息相关的密文。

思路: 既然是对配置文件信息解密,那么肯定会先读取配置文件,再对配置文件的内容 进行 解密

步骤:

先通过OD 打开 可执行文件,在 careteFile api上设置断点

img

获取缓冲区大小

img

对缓冲区字符进行转义

img

因此可以推测这块就是解密算法

img

直接跑完这段断码.可以发现 配置文件已经解密了

img

所以解密算法是

00407704  |> /8A11          /mov     dl, byte ptr [ecx]
00407706  |. |80F2 BD       |xor     dl, 0BD
00407709  |. |80C2 69       |add     dl, 69
0040770C  |. |8811          |mov     byte ptr [ecx], dl
0040770E  |. |41            |inc     ecx
0040770F  |. |48            |dec     eax
00407710  |.^\75 F2         \jnz     short 00407704
  1. 解密编译器求幻数

C2.DLL

这个dll 是通过 loadlibrary 加载的

调试方法: 用 OD 打开 CL.EXE

img

img

然后在 loadlibrary api上下断点

第二次断下来的时候就是 C2.DLL

img

解决不认识 stdio.h ,配置环境变量

img

解决字符问题: 用 vc6.0 写程序,不要用vs2019

img

样本中关键算法(文件偏移5FACE处)。

img

img

1075EACE    83EC 08         sub     esp, 8
1075EAD1    83F9 03         cmp     ecx, 3
1075EAD4    894C24 04       mov     dword ptr [esp+4], ecx
1075EAD8    7C 10           jl      short 1075EAEA
1075EADA    83F9 0D         cmp     ecx, 0D
1075EADD    73 0B           jnb     short 1075EAEA
1075EADF    8D04CD D8E07A10 lea     eax, dword ptr [ecx*8+107AE0D8]
1075EAE6    83C4 08         add     esp, 8
1075EAE9    C3              retn
//算法开始
1075EAEA    8BC1            mov     eax, ecx
1075EAEC    53              push    ebx
1075EAED    55              push    ebp
1075EAEE    56              push    esi
1075EAEF    99              cdq
1075EAF0    57              push    edi
1075EAF1    8BF1            mov     esi, ecx
1075EAF3    8BF8            mov     edi, eax
1075EAF5    BB 00000080     mov     ebx, 80000000
1075EAFA    C1EE 1F         shr     esi, 1F
1075EAFD    33FA            xor     edi, edx
1075EAFF    81EE 00000080   sub     esi, 80000000
1075EB05    2BFA            sub     edi, edx
1075EB07    8BC6            mov     eax, esi
1075EB09    33D2            xor     edx, edx
1075EB0B    C74424 10 1F000>mov     dword ptr [esp+10], 1F
1075EB13    F7F7            div     edi
1075EB15    B8 00000080     mov     eax, 80000000
1075EB1A    2BF2            sub     esi, edx
1075EB1C    33D2            xor     edx, edx
1075EB1E    4E              dec     esi
1075EB1F    F7F6            div     esi
1075EB21    33D2            xor     edx, edx
1075EB23    8BE8            mov     ebp, eax
1075EB25    0FAFC6          imul    eax, esi
1075EB28    2BD8            sub     ebx, eax
1075EB2A    B8 00000080     mov     eax, 80000000
1075EB2F    F7F7            div     edi
1075EB31    BA 00000080     mov     edx, 80000000
1075EB36    8BC8            mov     ecx, eax
1075EB38    0FAFC7          imul    eax, edi
1075EB3B    2BD0            sub     edx, eax
1075EB3D    EB 08           jmp     short 1075EB47
1075EB3F    8BC7            mov     eax, edi
1075EB41    2BC2            sub     eax, edx
1075EB43    3BE8            cmp     ebp, eax
1075EB45    73 22           jnb     short 1075EB69
1075EB47    8B4424 10       mov     eax, dword ptr [esp+10]
1075EB4B    03DB            add     ebx, ebx
1075EB4D    40              inc     eax
1075EB4E    03ED            add     ebp, ebp
1075EB50    3BDE            cmp     ebx, esi
1075EB52    894424 10       mov     dword ptr [esp+10], eax
1075EB56    0F83 AB080300   jnb     1078F407
1075EB5C    03D2            add     edx, edx
1075EB5E    03C9            add     ecx, ecx
1075EB60    3BD7            cmp     edx, edi
1075EB62  ^ 72 DB           jb      short 1075EB3F
1075EB64    41              inc     ecx
1075EB65    2BD7            sub     edx, edi
1075EB67  ^ EB D6           jmp     short 1075EB3F
1075EB69    0F84 A0080300   je      1078F40F
1075EB6F    8D41 01         lea     eax, dword ptr [ecx+1]
//算法结束
1075EB72    8B4C24 14       mov     ecx, dword ptr [esp+14]
1075EB76    5F              pop     edi
1075EB77    5E              pop     esi
1075EB78    5D              pop     ebp
1075EB79    A3 90F07910     mov     dword ptr [1079F090], eax
1075EB7E    85C9            test    ecx, ecx
1075EB80    5B              pop     ebx
1075EB81    0F8C 95080300   jl      1078F41C
1075EB87    8B4C24 00       mov     ecx, dword ptr [esp]
1075EB8B    B8 90F07910     mov     eax, 1079F090
1075EB90    83C1 E0         add     ecx, -20
1075EB93    890D 94F07910   mov     dword ptr [1079F094], ecx
1075EB99    83C4 08         add     esp, 8
1075EB9C    C3              retn

自己找 算法的方法:

img

// CLProject.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <stdio.h>
#include <stdlib.h>

int g_nExp = 0; //指数
int g_nMagicNumber = 0; //幻数

int Test(int Divisor) {

//.text:1075EACE                 sub     esp, 8
    int ecx = Divisor;
//.text:1075EAD1                 cmp     ecx, 3
//.text:1075EAD4                 mov     [esp+8+var_4], ecx
//.text:1075EAD8                 jl      short loc_1075EAEA
//.text:1075EADA                 cmp     ecx, 13
//.text:1075EADD                 jnb     short loc_1075EAEA
    if (ecx >= 3 && ecx < 13) {
    //.text:1075EADF                 lea     eax, dword_107AE0D8[ecx*8]
    //.text:1075EAE6                 add     esp, 8
    //.text:1075EAE9                 retn

        printf("需要查表\r\n");
        return 0;
    }
//.text:1075EAEA loc_1075EAEA:                       
//.text:1075EAEA                                     
//.text:1075EAEA                 mov     eax, ecx
//.text:1075EAEC                 push    ebx
//.text:1075EAED                 push    ebp
//.text:1075EAEE                 push    esi
//.text:1075EAEF                 cdq                ;流水线优化的代码,可以后提            
//.text:1075EAF0                 push    edi
//.text:1075EAF1                 mov     esi, ecx
//.text:1075EAF3                 mov     edi, eax
//.text:1075EAF5                 mov     ebx, 80000000h
    int eax = ecx;
    unsigned int esi = ecx;
    int edi = eax;
    unsigned int ebx = 0x80000000;
//.text:1075EAFA                 shr     esi, 1Fh
    esi = esi >> 31; //能这么移说明它是无符号的
//                               cdq                        ;流水线优化的代码可以提到这里
//.text:1075EAFD                 xor     edi, edx
//.text:1075EB05                 sub     edi, edx           ;流水线优化的代码
    edi = abs(eax); //绝对值
//.text:1075EAFF                 sub     esi, 80000000h     ;流水线优化的代码
    esi = esi - 0x80000000;

//.text:1075EB0B                 mov     [esp+18h+nExp], 1Fh
    int nExp = 31;

//.text:1075EB07                 mov     eax, esi ;两处流水线优化,调整到这里
//.text:1075EB09                 xor     edx, edx
//.text:1075EB13                 div     edi
//.text:1075EB1A                 sub     esi, edx
//.text:1075EB1E                 dec     esi
    esi = esi - esi % edi - 1;

//.text:1075EB15                 mov     eax, 80000000h
//.text:1075EB1F                 div     esi
//.text:1075EB21                 xor     edx, edx
//.text:1075EB23                 mov     ebp, eax
    unsigned int ebp = 0x80000000 / esi;
//.text:1075EB25                 imul    eax, esi
//.text:1075EB28                 sub     ebx, eax
    ebx = ebx - ebp * esi  ;
//.text:1075EB2A                 mov     eax, 80000000h
//.text:1075EB1C                 xor     edx, edx
//.text:1075EB2F                 div     edi
//.text:1075EB36                 mov     ecx, eax
    ecx = 0x80000000 / edi;
//.text:1075EB38                 imul    eax, edi
//.text:1075EB31                 mov     edx, 80000000h
//.text:1075EB3B                 sub     edx, eax
    int edx = 0x80000000 - ecx * edi;
//.text:1075EB3D                 jmp     short LOOP_BEGIN2 ;直接跳到循环体内了
//.text:1075EB3F ; ---------------------------------------------------------------------------
//.text:1075EB3F
//.text:1075EB3F LOOP_BEGIN://;这里相当于第一次不执行,后续循环再执行,将EB3F的代码挪到调用的地方,这块就不存在了
//.text:1075EB3F                 mov     eax, edi
//.text:1075EB41                 sub     eax, edx
//.text:1075EB43                 cmp     ebp, eax
//.text:1075EB45                 jnb     short loc_1075EB69 

//.text:1075EB3F            
    do {

        //.text:1075EB47
        //.text:1075EB47 LOOP_BEGIN2:                       
        //.text:1075EB47                                     
        //.text:1075EB47                 mov     eax, [esp+18h+nExp]
        //.text:1075EB4D                 inc     eax
        eax = nExp + 1;
        //.text:1075EB4B                 add     ebx, ebx
        ebx = ebx * 2;
        //.text:1075EB4E                 add     ebp, ebp
        ebp = ebp * 2;

        //.text:1075EB52                 mov     [esp+18h+nExp], eax ;这句可以提到上面,就相当于nExp++;
        nExp = eax;
        //.text:1075EB50                 cmp     ebx, esi
        //.text:1075EB56                 //jnb     loc_1078F407  改为 jb loc_1075EB5C

        //;这里是跳到外部游离代码处,把游离代码贴回来后就要修改条件,jnb 跳到游离代码,就要改为jb 跳到下面的地方 loc_1075EB5C
        // 之前是不小于则跳到游离代码,现在改为小于则跳到原先下面的代码,也就是不小于的话不跳,照常执行游离代码

        if(ebx >= esi){
            //.text:1078F407 loc_1078F407 :                     ;把游离代码贴回来
            //.text : 1078F407                 inc     ebp
            ebp++;
            //.text : 1078F408                 sub     ebx, esi
            ebx = ebx - esi;
            //.text : 1078F40A                 jmp     loc_1075EB5C ;这一句就没用了

        }

        //.text:1075EB5C loc_1075EB5C:                       
        //.text:1075EB5C                 add     edx, edx
        edx = edx * 2;
        //.text:1075EB5E                 add     ecx, ecx
        ecx = ecx * 2;
        //.text:1075EB60                 cmp     edx, edi
        //.text:1075EB62                 jb      short LOOP_BEGIN ?
        if(edx < edi ){
            //可以把EB3F的代码搬到这里来,jb 还原为if ,成立就跳到这里
            //.text:1075EB3F                 mov     eax, edi
            //.text:1075EB41                 sub     eax, edx
            eax = edi - edx;
            //.text:1075EB43                 cmp     ebp, eax
            //.text:1075EB45                 jnb     short loc_1075EB69  ;不小于还原为等于,但由于EB69出还有个jnz所以只能是大于了
            if (ebp > eax) {
                break;
            }
            continue;
        }


        //.text:1075EB64                 inc     ecx
        ecx++;
        //.text:1075EB65                 sub     edx, edi
        edx = edx - edi;
        //EB3F的代码
        //.text:1075EB3F                 mov     eax, edi
        eax = edi;
        //.text:1075EB41                 sub     eax, edx
        eax = eax - edx; //?
        //.text:1075EB43                 cmp     ebp, eax
        //.text:1075EB45                 jnb     short loc_1075EB69 
        if (ebp < eax) {
            //.text:1075EB67                 jmp     short LOOP_BEGIN   ;
               //可以把EB3F的代码搬到这里来,jb 还原为if ,成立就跳到这里
            //.text:1075EB3F                 mov     eax, edi
            //.text:1075EB41                 sub     eax, edx
            eax = edi - edx;
            //.text:1075EB43                 cmp     ebp, eax
            //.text:1075EB45                 jnb     short loc_1075EB69  ;不小于还原为等于,但由于EB69出还有个jnz所以只能是大于了
            if (ebp > eax) {
                break;
            }
            continue;
        }

//.text:1075EB69 loc_1075EB69:                      
//.text:1075EB69                 jnz      LOOPEND;  jz      loc_1078F40F 满足条件则执行,改为不满足条件跳下面的代码
        if(ebp>eax){
            break;
        }
        //外提代码贴回来
        //.text:1078F40F loc_1078F40F:                      
        //.text:1078F40F                 test    ebx, ebx
        //.text:1078F411                 jz      LOOP_BEGIN2
        if (ebx != 0) { //避免每次continue检查ebx,所以直接写为死循环,然后判断ebx
            break;
        }
    } while (1);


//.text:1075EB6F
//.text:1075EB6F LOOPEND:                       
//.text:1075EB6F                 lea     eax, [ecx+1]
    eax = ecx + 1;
//.text:1075EB72                 mov     ecx, [esp+18h+var_4]
    ecx = Divisor;
//.text:1075EB76                 pop     edi
//.text:1075EB77                 pop     esi
//.text:1075EB78                 pop     ebp
//.text:1075EB79                 mov     ds:dword_1079F090, eax
    g_nMagicNumber = eax;
//.text:1075EB7E                 test    ecx, ecx
//.text:1075EB80                 pop     ebx
//.text:1075EB81                 jnl      loc_1075EB87 ;同样修改一下,满足条件跳下面的代码,不满足则执行游离代码
    if(ecx < 0){
    //游离代码
    // .text:1078F41C loc_1078F41C:                       
    //.text:1078F41C                 neg     eax
    //.text:1078F41E                 mov     ds:dword_1079F090, eax
        g_nMagicNumber = -eax;
    //.text:1078F423                 jmp     loc_1075EB87
    }
//.text:1075EB87
//.text:1075EB87 loc_1075EB87:                      
//.text:1075EB87                 mov     ecx, [esp+8+nExp] ;局部指数变量
//.text:1075EB8B                 mov     eax, offset dword_1079F090
//.text:1075EB90                 add     ecx, -32  ;指数 ,因为指数起步加32,所以要减去32,把剩下的返回出去
//.text:1075EB93                 mov     ds:dword_1079F094, ecx ;
    g_nExp = nExp - 32;
//.text:1075EB99                 add     esp, 8
//.text:1075EB9C                 retn
//.text:1075EB9C sub_1075EACE    endp
    return g_nMagicNumber;
}


int main(int argc)
{

    Test(-54321);
    printf("%08x ,Exp:%d", g_nMagicNumber,g_nExp);

    return 0;
}

0

主题

104

回帖

179

积分

注册会员

积分
179
发表于 2025-5-19 21:42:18 | 显示全部楼层
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-6-1 06:44 , Processed in 0.113436 second(s), 25 queries , Yac On.

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表