2015-11-19 68 views
-1

有人請給我提供幫助,分解下面的shell代碼(在註釋部分),並向我解釋最後一行代碼的作用?逆向工程彙編代碼到C

# 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,但我不知道如何在這種情況下使用它。

P.S:我在一臺x86-32 Ubuntu Linux機器上。

+5

最後一行是在'BUF []'一個函數調用的代碼。如果堆棧內存段的NX位被設置爲安全性,它可能不起作用。 –

+1

最後一行是函數調用:http://cdecl.org/?q=%28+void+%28%2a%29%28+%29%29+buf+。 – kay

+1

@伊恩是對的。 '(void(*)())'是指向一個沒有參數的函數指針的'buf'類型。你可以使用'gdb'。只需使用'ni'和'si'命令即可進入指令級別。 –

回答

1

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 

如果這段代碼是爲了某種邪惡的目的而設計的,這並不會讓我感到意外。 這是一種將一些未知代碼引入程序並讓計算機執行的方法。

+0

謝謝你的隊友,你的詳細解釋:) – sasuke

2

您已經擁有內嵌代碼的反彙編代碼,它在註釋中。所以這部分有點混亂。

最終陳述將buf轉換爲函數指針並調用代碼。這是漏洞的實際使用。它也是(據我所知)未定義的行爲,並且不能在防止執行隨機區域內存的環境中工作。

+1

這可能是第一個問題實際上是在標題。如果我的理解是正確的,OP要反編譯的機器代碼爲C. – 2015-11-19 17:51:20

+0

@unwind是:)不過我很想了解如何將在意見彙編代碼看起來像在C語言或者至少是對的? – sasuke

1

程序集所做的是構建一個參數列表,以傳遞給操作系統調用來執行二進制文件(/bin/sh)。

這兩行將/bin/sh推到堆棧上。

pushl $0x68732f2f 
pushl $0x6e69622f 

這些行根據calling convention放置指針/bin/sh在參數寄存器。

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

該行將系統調用號碼11置於寄存器中作爲中斷的參數。

movb $0x0b, %al 

最後一行調用操作系統。

int $0x80 

C代碼中的這行只是將緩衝區轉換爲函數指針,然後調用該函數。

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

注意,這裏曾經是利用軟件,然而類似的方法可以用來JIT編譯代碼的常用方法。

+0

非常感謝你 – sasuke

1

我首先想到的第3行和第4行是設置/ bin/sh,但是第二個想法可能是sh/bin/X對於某些X我不太明白。實際上// sh部分看起來幾乎就像一個評論?

我的預感是系統調用第11行是exec系統調用,並且前面的行爲exec調用設置了參數。

要爲V小心運行此代碼,我會大膽地猜測;)

您可能要調查六角射線反彙編器,它可以(的排序)轉換成機器代碼/彙編(二是等價的)轉換成C.

3

該代碼是最有可能在進行呼叫到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寄存器爲零,將使用d爲 空字符串終止
  2. 線2,3和4所使用的堆棧作爲臨時緩衝器來存儲空終止ASCII字符串「/ bin/sh的」;由於堆棧按遞減順序增長,所以字符相反,這就是爲什麼首先推送終結符的原因。
  3. 第5行被加載 到EBX堆棧指針,它在這一刻指向我們形成在前面的步驟的字符串的第一個字符的地址的當前值。 Ebx是sys_execve()期望字符串與要運行的文件的寄存器。
  4. 線6,和7被再次使用堆棧作爲 臨時緩衝器來保存一個空終止ASCII字符串
  5. 管道8加載到ECX這個空字符串的其中sys_execve()期望命令行中的地址參數
  6. 9號線,沒有它的目的
  7. 10號線的想法,負載十進制值11 AL註冊,指定的 sys_execve()功能是我們要調用
  8. 11個線觸發interrput 0x80的一個 - 它的處理器是會採取行動的代碼ually執行sys_execve()調用爲我們