解密x86汇编功能

Kev*_*vin 2 c x86 assembly att

我目前正致力于二元炸弹任务的第二阶段.我无法完全解密某个函数在调用时所执行的操作.我已经坚持了几天.

功能是:

0000000000400f2a <func2a>:
  400f2a:   85 ff                   test   %edi,%edi
  400f2c:   74 1d                   je     400f4b <func2a+0x21>
  400f2e:   b9 cd cc cc cc          mov    $0xcccccccd,%ecx
  400f33:   89 f8                   mov    %edi,%eax
  400f35:   f7 e1                   mul    %ecx
  400f37:   c1 ea 03                shr    $0x3,%edx
  400f3a:   8d 04 92                lea    (%rdx,%rdx,4),%eax
  400f3d:   01 c0                   add    %eax,%eax
  400f3f:   29 c7                   sub    %eax,%edi
  400f41:   83 04 be 01             addl   $0x1,(%rsi,%rdi,4)
  400f45:   89 d7                   mov    %edx,%edi
  400f47:   85 d2                   test   %edx,%edx
  400f49:   75 e8                   jne    400f33 <func2a+0x9>
  400f4b:   f3 c3                   repz retq 
Run Code Online (Sandbox Code Playgroud)

它在较大的函数"phase_2"中被调用:

0000000000400f4d <phase_2>: 
  400f4d:   53                      push   %rbx
  400f4e:   48 83 ec 60             sub    $0x60,%rsp
  400f52:   48 c7 44 24 30 00 00    movq   $0x0,0x30(%rsp)
  400f59:   00 00 
  400f5b:   48 c7 44 24 38 00 00    movq   $0x0,0x38(%rsp)
  400f62:   00 00 
  400f64:   48 c7 44 24 40 00 00    movq   $0x0,0x40(%rsp)
  400f6b:   00 00 
  400f6d:   48 c7 44 24 48 00 00    movq   $0x0,0x48(%rsp)
  400f74:   00 00 
  400f76:   48 c7 44 24 50 00 00    movq   $0x0,0x50(%rsp)
  400f7d:   00 00 
  400f7f:   48 c7 04 24 00 00 00    movq   $0x0,(%rsp)
  400f86:   00 
  400f87:   48 c7 44 24 08 00 00    movq   $0x0,0x8(%rsp)
  400f8e:   00 00 
  400f90:   48 c7 44 24 10 00 00    movq   $0x0,0x10(%rsp)
  400f97:   00 00 
  400f99:   48 c7 44 24 18 00 00    movq   $0x0,0x18(%rsp)
  400fa0:   00 00 
  400fa2:   48 c7 44 24 20 00 00    movq   $0x0,0x20(%rsp)
  400fa9:   00 00 
  400fab:   48 8d 4c 24 58          lea    0x58(%rsp),%rcx
  400fb0:   48 8d 54 24 5c          lea    0x5c(%rsp),%rdx
  400fb5:   be 9e 26 40 00          mov    $0x40269e,%esi
  400fba:   b8 00 00 00 00          mov    $0x0,%eax
  400fbf:   e8 6c fc ff ff          callq  400c30 <__isoc99_sscanf@plt>
  400fc4:   83 f8 02                cmp    $0x2,%eax
  400fc7:   74 05                   je     400fce <phase_2+0x81>
  400fc9:   e8 c1 06 00 00          callq  40168f <explode_bomb>
  400fce:   83 7c 24 5c 64          cmpl   $0x64,0x5c(%rsp)
  400fd3:   76 07                   jbe    400fdc <phase_2+0x8f>
  400fd5:   83 7c 24 58 64          cmpl   $0x64,0x58(%rsp)
  400fda:   77 05                   ja     400fe1 <phase_2+0x94>
  400fdc:   e8 ae 06 00 00          callq  40168f <explode_bomb>
  400fe1:   48 8d 74 24 30          lea    0x30(%rsp),%rsi
  400fe6:   8b 7c 24 5c             mov    0x5c(%rsp),%edi
  400fea:   e8 3b ff ff ff          callq  400f2a <func2a>
  400fef:   48 89 e6                mov    %rsp,%rsi
  400ff2:   8b 7c 24 58             mov    0x58(%rsp),%edi
  400ff6:   e8 2f ff ff ff          callq  400f2a <func2a>
  400ffb:   bb 00 00 00 00          mov    $0x0,%ebx
  401000:   8b 04 1c                mov    (%rsp,%rbx,1),%eax
  401003:   39 44 1c 30             cmp    %eax,0x30(%rsp,%rbx,1)
  401007:   74 05                   je     40100e <phase_2+0xc1>
  401009:   e8 81 06 00 00          callq  40168f <explode_bomb>
  40100e:   48 83 c3 04             add    $0x4,%rbx
  401012:   48 83 fb 28             cmp    $0x28,%rbx
  401016:   75 e8                   jne    401000 <phase_2+0xb3>
  401018:   48 83 c4 60             add    $0x60,%rsp
  40101c:   5b                      pop    %rbx
  40101d:   c3                      retq   
Run Code Online (Sandbox Code Playgroud)

我完全理解phase_2正在做什么,我只是不明白func2a正在做什么以及它如何影响0x30(%rsp)的值等等.因此,我总是到达0x401003的比较语句,炸弹最终在那里爆炸.

我的问题是我不明白输入(相位解决方案)如何通过func2a影响0x30(%rsp)的值.

Mat*_*lia 11

  400f2a:   85 ff                   test   %edi,%edi
  400f2c:   74 1d                   je     400f4b <func2a+0x21>
Run Code Online (Sandbox Code Playgroud)

这只是edi0 时的早期退出(je与之相同jz).

  400f2e:   b9 cd cc cc cc          mov    $0xcccccccd,%ecx
  400f33:   89 f8                   mov    %edi,%eax
  400f35:   f7 e1                   mul    %ecx
  400f37:   c1 ea 03                shr    $0x3,%edx
Run Code Online (Sandbox Code Playgroud)

这是一个经典的优化技巧; 它是除以乘以倒数的整数算术等价物(详见此处); 在实践中,这与说法相同edx = edi / 10;

  400f3a:   8d 04 92                lea    (%rdx,%rdx,4),%eax
  400f3d:   01 c0                   add    %eax,%eax
Run Code Online (Sandbox Code Playgroud)

在这里,它正在利用lea算术运算(在英特尔语法中更清晰,它是lea eax,[rdx+rdx*4]=> eax = edx*5),然后将结果与自身相加.这一切归结为eax = edx*10.

  400f3f:   29 c7                   sub    %eax,%edi
Run Code Online (Sandbox Code Playgroud)

然后,将其减去edi.


所以,总而言之,这是计算最后一个十进制数字的一种复杂(但快速)的方法edi; 到目前为止我们所拥有的是:

void func2a(unsigned edi) {
    if(edi==0) return;
label1:
    edx=edi/10;
    edi%=10;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

(之后label1:是因为400f33跳跃目标)


继续:

  400f41:   83 04 be 01             addl   $0x1,(%rsi,%rdi,4)
Run Code Online (Sandbox Code Playgroud)

同样,在英特尔语法中,这对我来说更清晰 - add dword [rsi+rdi*4],byte +0x1.它是一个32位数组的常规增量int(rdi乘以4); 所以,我们可以想象rsi指向一个整数数组,用刚刚计算的最后一位数字索引edi.

void func2a(unsigned edi, int rsi[]) {
    if(edi==0) return;
label1:
    edx=edi/10;
    edi%=10;
    rsi[edi]++;
}
Run Code Online (Sandbox Code Playgroud)

然后:

  400f45:   89 d7                   mov    %edx,%edi
  400f47:   85 d2                   test   %edx,%edx
  400f49:   75 e8                   jne    400f33 <func2a+0x9>
Run Code Online (Sandbox Code Playgroud)

将上面计算的除法结果移动到edi,并且如果它与零不同则循环.

  400f4b:   f3 c3                   repz retq 
Run Code Online (Sandbox Code Playgroud)

返回(使用对某些AMD处理器最佳的指令的异常编码).


所以,通过while循环重写跳转并给出一些有意义的名字......

// number is edi, digits_count is rsi, as per regular
// x64 SystemV calling convention
void count_digits(unsigned number, int digits_count[]) {
    while(number) {
        digits_count[number%10]++;
        number/=10;
    }
}
Run Code Online (Sandbox Code Playgroud)

即,这是一个函数,给定一个整数,通过递增digits_count数组中相应的桶来计算单个十进制数的出现次数.


有趣的事实:如果我们给出上面的C代码gcc(几乎任何最近的版本-O1),我们会准确地获得你提供的程序集.

  • "如果我们将上面的C代码提供给gcc,我们会准确地获得你提供的程序集." - >完美的逆向工程.很棒的答案! (3认同)