MIPS 汇编到 C 代码

逆向工程 部件 反编译 C 反编译 米普
2021-06-30 13:49:47

我想我真的是脑残了,我不确定接下来要做什么,但我正在尝试将汇编代码手动转换为 C 程序。它并没有真正起作用,但我不确定出了什么问题。我很乐意提供任何帮助。该代码由两个.c文件和一个子程序的头文件组成在头文件中,我只声明了extern int b变量,所以我不在这里发布它。

program code


build/program-mips:     file format elf32-tradbigmips


Disassembly of section my_text:

00405060 <subroutine_fnc>:
  405060:   27bdfff8    addiu   sp,sp,-8
  405064:   afbe0004    sw  s8,4(sp)
  405068:   03a0f025    move    s8,sp
  40506c:   afc40008    sw  a0,8(s8)
  405070:   8fc20008    lw  v0,8(s8)
  405074:   00000000    nop
  405078:   2842005b    slti    v0,v0,91
  40507c:   10400006    beqz    v0,405098 <subroutine_fnc+0x38>
  405080:   00000000    nop
  405084:   8fc20008    lw  v0,8(s8)
  405088:   00000000    nop
  40508c:   28420041    slti    v0,v0,65
  405090:   10400004    beqz    v0,4050a4 <subroutine_fnc+0x44>
  405094:   00000000    nop
  405098:   8fc20008    lw  v0,8(s8)
  40509c:   1000000c    b   4050d0 <subroutine_fnc+0x70>
  4050a0:   00000000    nop
  4050a4:   3c020041    lui v0,0x41
  4050a8:   8c4260d0    lw  v0,24784(v0)
  4050ac:   00000000    nop
  4050b0:   24430001    addiu   v1,v0,1
  4050b4:   3c020041    lui v0,0x41
  4050b8:   ac4360d0    sw  v1,24784(v0)
  4050bc:   8fc20008    lw  v0,8(s8)
  4050c0:   00000000    nop
  4050c4:   24420020    addiu   v0,v0,32
  4050c8:   afc20008    sw  v0,8(s8)
  4050cc:   8fc20008    lw  v0,8(s8)
  4050d0:   03c0e825    move    sp,s8
  4050d4:   8fbe0004    lw  s8,4(sp)
  4050d8:   27bd0008    addiu   sp,sp,8
  4050dc:   03e00008    jr  ra
  4050e0:   00000000    nop

004050e4 <toplevel_fnc>:
  4050e4:   27bdffc8    addiu   sp,sp,-56
  4050e8:   afbf0034    sw  ra,52(sp)
  4050ec:   afbe0030    sw  s8,48(sp)
  4050f0:   03a0f025    move    s8,sp
  4050f4:   1000001e    b   405170 <toplevel_fnc+0x8c>
  4050f8:   00000000    nop
  4050fc:   83c20028    lb  v0,40(s8)
  405100:   00000000    nop
  405104:   00402025    move    a0,v0
  405108:   0c101418    jal 405060 <subroutine_fnc>
  40510c:   00000000    nop
  405110:   00021600    sll v0,v0,0x18
  405114:   00021603    sra v0,v0,0x18
  405118:   a3c20028    sb  v0,40(s8)
  40511c:   24040001    li  a0,1
  405120:   27c20028    addiu   v0,s8,40
  405124:   00402825    move    a1,v0
  405128:   24060001    li  a2,1
  40512c:   24020fa4    li  v0,4004
  405130:   0000000c    syscall
  405134:   afc70018    sw  a3,24(s8)
  405138:   afc20024    sw  v0,36(s8)
  40513c:   8fc20018    lw  v0,24(s8)
  405140:   00000000    nop
  405144:   14400004    bnez    v0,405158 <toplevel_fnc+0x74>
  405148:   00000000    nop
  40514c:   8fc20024    lw  v0,36(s8)
  405150:   10000002    b   40515c <toplevel_fnc+0x78>
  405154:   00000000    nop
  405158:   2402ffff    li  v0,-1
  40515c:   afc20020    sw  v0,32(s8)
  405160:   8fc20020    lw  v0,32(s8)
  405164:   00000000    nop
  405168:   04400018    bltz    v0,4051cc <toplevel_fnc+0xe8>
  40516c:   00000000    nop
  405170:   00002025    move    a0,zero
  405174:   27c20028    addiu   v0,s8,40
  405178:   00402825    move    a1,v0
  40517c:   24060001    li  a2,1
  405180:   24020fa3    li  v0,4003
  405184:   0000000c    syscall
  405188:   afc70018    sw  a3,24(s8)
  40518c:   afc2001c    sw  v0,28(s8)
  405190:   8fc20018    lw  v0,24(s8)
  405194:   00000000    nop
  405198:   14400004    bnez    v0,4051ac <toplevel_fnc+0xc8>
  40519c:   00000000    nop
  4051a0:   8fc2001c    lw  v0,28(s8)
  4051a4:   10000002    b   4051b0 <toplevel_fnc+0xcc>
  4051a8:   00000000    nop
  4051ac:   2402ffff    li  v0,-1
  4051b0:   afc20020    sw  v0,32(s8)
  4051b4:   8fc30020    lw  v1,32(s8)
  4051b8:   24020001    li  v0,1
  4051bc:   1062ffcf    beq v1,v0,4050fc <toplevel_fnc+0x18>
  4051c0:   00000000    nop
  4051c4:   10000002    b   4051d0 <toplevel_fnc+0xec>
  4051c8:   00000000    nop
  4051cc:   00000000    nop
  4051d0:   3c020041    lui v0,0x41
  4051d4:   8c4260d0    lw  v0,24784(v0)
  4051d8:   03c0e825    move    sp,s8
  4051dc:   8fbf0034    lw  ra,52(sp)
  4051e0:   8fbe0030    lw  s8,48(sp)
  4051e4:   27bd0038    addiu   sp,sp,56
  4051e8:   03e00008    jr  ra
  4051ec:   00000000    nop

program data


build/program-mips:     file format elf32-tradbigmips

Contents of section my_data:
 4160d0 00000000                             ....      

这是我到目前为止检索到的代码:

顶层

#include <stdio.h>
#include "subroutine.h"


int b = 0;
int toplevel_fnc(void)
{
  char a = 0;
  while (b < 0)
  {
    read(0, a, 1);
    a = 3;
    if (a != 1)
    {
      (long)b;
      a = subroutine_fnc(b);
      write(1,a,1);
      b += 4;
    }
  }
  return b;
}

子程序

/* Implementation of the subroutine subroutine_fnc */

#include "subroutine.h"



int subroutine_fnc(int a)
{
  if (90 < a)
  {
    return a;
  }
  if (64 < a)
  {
    b += 1;
    a += 32;
    return a;
  }
}
3个回答

生成伪代码

您应该尝试使用专门的程序在 C 中生成伪代码。从原始 asm 中用 C 编写代码很痛苦,强烈不推荐这样做。

工具

  1. Ghidra(免费)
  2. IDA PRO(付费)

如果由于某些原因你真的需要手动编写它,我建议使用反汇编器,它会在漂亮的图形中显示 asm 什么应该真正帮助你。例如:

  1. 吉德拉
  2. 国际开发协会免费
  3. 刀具

它并没有真正起作用,但我不确定出了什么问题。

更多信息可以帮助提供更具体的答案,例如原始程序的行为究竟是什么以及编译后的代码产生什么行为?

您是否编译了程序并比较了输出程序集以查看其相似之处和不同之处?

我还建议您在第一次通过时不要尝试过多地重写逻辑,而是在重建肉之前一次遵循一个分支。例如你的subroutine_fnc

40506c:   afc40008    sw  a0,8(s8)
405070:   8fc20008    lw  v0,8(s8)
405074:   00000000    nop
405078:   2842005b    slti    v0,v0,91
40507c:   10400006    beqz    v0,405098 <subroutine_fnc+0x38>
...
405098:   8fc20008    lw  v0,8(s8)
40509c:   1000000c    b   4050d0 <subroutine_fnc+0x70>
...
4050d0:   03c0e825    move    sp,s8
4050d4:   8fbe0004    lw  s8,4(sp)
4050d8:   27bd0008    addiu   sp,sp,8
4050dc:   03e00008    jr  ra

我们取 a0(通常是第一个参数)并将其保存到 8(s8)。然后将 8(s8) 加载到 v0 中。slti v0, v0, 91相当于if(v0<91) v0=1 else v0=0然后beqz v0, 405098是“如果 v0 等于 0 ,则转到 405098”。405098 将 8(s8) 加载回 v0,然后无条件地分支(跳转)到 4050d0。从这里我们有后同步;恢复 s8 的值,恢复堆栈指针,并返回调用我们的东西。请记住,通常 v0 是 MIPS 用来从中返回值的寄存器,因此我们现在假设这就是正在发生的事情(通过查看紧跟在 subroutine_fnc 的原始调用之后的指令,它利用了 v0在 405110)。

所以在 C 中,一个分支类似于:

int subroutine_fnc(int a) {
   if (a < 91) {
      ...
   }
405098:
   return a;
}

继续在第一个分支的另一个方向:

405080:   00000000    nop
405084:   8fc20008    lw  v0,8(s8)
405088:   00000000    nop
40508c:   28420041    slti    v0,v0,65
405090:   10400004    beqz    v0,4050a4 <subroutine_fnc+0x44>
405094:   00000000    nop

将 8(s8) 重新加载到 v0,if(v0<65) v0=1 else v0=0“如果 v0 等于 0,则转到 4050a4”。如果我们不选择这个分支,我们会在 405098 处着陆,我们已经覆盖了它,这样我们就会得到类似的结果:

int subroutine_fnc(int a) {
   if (a < 91) {
      if ( a < 65 ) {
          goto 405098:
      }
      4050a4:   3c020041    lui v0,0x41
      4050a8:   8c4260d0    lw  v0,24784(v0)
      4050ac:   00000000    nop
      4050b0:   24430001    addiu   v1,v0,1
      4050b4:   3c020041    lui v0,0x41
      4050b8:   ac4360d0    sw  v1,24784(v0)
      4050bc:   8fc20008    lw  v0,8(s8)
      4050c0:   00000000    nop
      4050c4:   24420020    addiu   v0,v0,32
      4050c8:   afc20008    sw  v0,8(s8)
      4050cc:   8fc20008    lw  v0,8(s8)
   }
405098:
   return a;
}

现在我们已经覆盖了分支并且非常简单,我们可以清理逻辑以摆脱那个 goto。

int subroutine_fnc(int a) {
   if (a < 91) {
      if ( a >= 65 ) {
          4050a4:   3c020041    lui v0,0x41
          4050a8:   8c4260d0    lw  v0,24784(v0)
          4050ac:   00000000    nop
          4050b0:   24430001    addiu   v1,v0,1
          4050b4:   3c020041    lui v0,0x41
          4050b8:   ac4360d0    sw  v1,24784(v0)
          4050bc:   8fc20008    lw  v0,8(s8)
          4050c0:   00000000    nop
          4050c4:   24420020    addiu   v0,v0,32
          4050c8:   afc20008    sw  v0,8(s8)
          4050cc:   8fc20008    lw  v0,8(s8)
      }
   }
   return a;
}

如果你真的想要你可以通过制作它进一步清理它 if ( a < 91 && a >= 65 ) {

但是,此时您甚至可以在确认实际计算是什么之前就看到分支逻辑是错误的。subroutine_fnc跳出我的原因是如果a大于 90 ,你的代码会发生什么

披露,我不太记得 MIPS。我使用了这个指令参考这个寄存器参考

最好的选择是像上面提到的那样,特别为 mips 伪 c 使用 ghidra 并将该伪代码编辑为更易于操作和编译的内容。你这样做只是为了自我知识和学习应用吗?