【问题标题】:Reverse Engineering a recursive function对递归函数进行逆向工程
【发布时间】:2017-02-15 05:48:15
【问题描述】:

我有一个家庭作业来反转一个函数

汇编输出是这样的:

0x00000000004010c4 <+0>:    sub    $0x18,%rsp
0x00000000004010c8 <+4>:    lea    0xc(%rsp),%rcx
0x00000000004010cd <+9>:    lea    0x8(%rsp),%rdx
0x00000000004010d2 <+14>:   mov    $0x402995,%esi
0x00000000004010d7 <+19>:   mov    $0x0,%eax
0x00000000004010dc <+24>:   callq  0x400cb0 <__isoc99_sscanf@plt>
0x00000000004010e1 <+29>:   cmp    $0x2,%eax
0x00000000004010e4 <+32>:   jne    0x4010ed <phase_4+41>
0x00000000004010e6 <+34>:   cmpl   $0xe,0x8(%rsp)
0x00000000004010eb <+39>:   jbe    0x4010f2 <phase_4+46>
0x00000000004010ed <+41>:   callq  0x401671 <explode_bomb>
0x00000000004010f2 <+46>:   mov    $0xe,%edx
0x00000000004010f7 <+51>:   mov    $0x0,%esi
0x00000000004010fc <+56>:   mov    0x8(%rsp),%edi
0x0000000000401100 <+60>:   callq  0x401086 <func4>
0x0000000000401105 <+65>:   cmp    $0x3,%eax
0x0000000000401108 <+68>:   jne    0x401111 <phase_4+77>
0x000000000040110a <+70>:   cmpl   $0x3,0xc(%rsp)
0x000000000040110f <+75>:   je     0x401116 <phase_4+82>
0x0000000000401111 <+77>:   callq  0x401671 <explode_bomb>
0x0000000000401116 <+82>:   add    $0x18,%rsp
0x000000000040111a <+86>:   retq   

我对此函数的解决方案如下所示: 我认为 func4 应该返回 3

int phase4(const char* read ) {
int var1, var2;
if ((sscanf(read, "%d %d", &var1, &var2) != 2) || (var1 < 0xe))
    explode_bomb();

if (func4(var1, 0, 0xe /*14*/) != 3)
    explode_bomb();

if (var2 != 3)
    explode_bomb();
return 3;
}

func4 看起来像这样:

0x0000000000401086 <+0>:    sub    $0x8,%rsp
0x000000000040108a <+4>:    mov    %edx,%eax
0x000000000040108c <+6>:    sub    %esi,%eax
0x000000000040108e <+8>:    mov    %eax,%ecx
0x0000000000401090 <+10>:   shr    $0x1f,%ecx
0x0000000000401093 <+13>:   add    %ecx,%eax
0x0000000000401095 <+15>:   sar    %eax
0x0000000000401097 <+17>:   lea    (%rax,%rsi,1),%ecx
0x000000000040109a <+20>:   cmp    %edi,%ecx
0x000000000040109c <+22>:   jle    0x4010aa <func4+36>
0x000000000040109e <+24>:   lea    -0x1(%rcx),%edx
0x00000000004010a1 <+27>:   callq  0x401086 <func4>
0x00000000004010a6 <+32>:   add    %eax,%eax
0x00000000004010a8 <+34>:   jmp    0x4010bf <func4+57>
0x00000000004010aa <+36>:   mov    $0x0,%eax
0x00000000004010af <+41>:   cmp    %edi,%ecx
0x00000000004010b1 <+43>:   jge    0x4010bf <func4+57>
0x00000000004010b3 <+45>:   lea    0x1(%rcx),%esi
0x00000000004010b6 <+48>:   callq  0x401086 <func4>
0x00000000004010bb <+53>:   lea    0x1(%rax,%rax,1),%eax
0x00000000004010bf <+57>:   add    $0x8,%rsp
0x00000000004010c3 <+61>:   retq   

我的 c 代码如下所示:

int func4(unsigned rsi, unsigned rdi, unsigned rdx) {
unsigned rax = rdx;
rax -= rsi;
unsigned rcx = rax;
rcx >>= (unsigned)0x1f;
rax += rcx;
rax >>= (signed)1;
rcx = rax + rsi;
if (rcx <= rdi) {
    rax = 0;
    if (rcx >= rdi)
        return rax;
    else {
        rax = func4(rdi, rsi + 1, rdx);
        rax = rax + rax + 1;
    }
} else {
    rdx = rcx - 1;
    rax = func4(rdi, rsi, rdx);
    rax = rax + rax;
}
return rax;
}

但是当我尝试从 -512 到 512 的值时,我永远不会得到 3;我做错了什么?

编辑:

我找到了如下所示的解决方案:

int func4(int32_t di, int32_t si, int32_t dx) {
int32_t ax = dx;
ax = ax - si;
int32_t cx = ax;
cx = (uint32_t)cx >> (uint32_t)0x1f;
ax = ax + cx;
ax = (int32_t)ax >> (int32_t)1;
cx = ax + si;

if (cx <= di)
    goto first;

dx = cx - 1;
ax = func4(di, si, dx);
ax = ax + ax;
goto fin;

first:
   ax = 0;
   if (cx >= di)
       goto fin;

si = cx + 1;
ax = func4(di, si, dx);
ax = ax + ax + 1;

fin:
    return ax;
}

【问题讨论】:

  • 在调试器中单步执行它们并找到它们的分歧点。

标签: c assembly reverse-engineering


【解决方案1】:

一目了然,问题可能出在此处:

rax >>= (signed)1;           // sar    %eax

这相当于:

rax = rax >> (signed)1;

无符号移位(因为移位运算符的符号由第一个操作数决定,而不是第二个)。所以你应该写:

rax = (unsigned)((signed)rax >> 1);

编辑:同样,您错误地翻译了jlejge。这些指令进行有符号比较,而您相应的 C 代码进行无符号比较。也解决这个问题:

if ((signed)rcx <= (signed)rdi) {
    rax = 0;
    if ((signed)rcx >= (signed)rdi)
...

【讨论】:

    【解决方案2】:

    如何从汇编中生成 C:

    写出程序集。然后用与寄存器相同的名称声明 C 变量,并通过汇编将每个算术或逻辑汇编指令替换为 C 指令,并将每个分支替换为 if goto 构造。当然,如果你有调用,你必须知道调用约定。

    一旦 C 可以正常工作,就逐渐让它更像人类,在每一点测试它针对程序集(如果你有的话)或类似程序集的 C(如果你不能组装程序集)的行为。

    【讨论】:

      猜你喜欢
      • 2018-08-26
      • 2016-09-28
      • 2017-07-11
      • 2016-04-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      相关资源
      最近更新 更多