簡體   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