2011-09-05 60 views
1

我需要你的幫助。這是我的程序的源代碼。我需要了解分數1,分數2,分數3和分數4函數的操作。需要幫助拆卸

1  #include <stdio.h> 
    2  #include <string.h> 
    3  #include <stdlib.h> 
    4  #include <sys/types.h> 
    5  #include <sys/stat.h> 
    6  #include <pwd.h> 
    7  #include <unistd.h> 
    8 
    9  #include "score.h" 
    10 
    (gdb) 
    11  int main(int argc, char *argv[]) 
    12  { 
    13  int i, j, k, l, s; 
    14  struct passwd *pw; 
    15  char cmd[1024]; 
    16 
    17  /* Make sure that we have exactly 5 arguments: the name of the executable, and 4 numbers */ 
    18  if (argc != 5) { 
    19   printf("Usage: %s i j k l\n where i,j,k,l are integers.\n Try to get as high a score as you can.\n", argv[0]); 
    20   exit(8); 
    (gdb) 
    21  } 
    22 
    23  initialize(); 
    24 
    25  /* Convert the inputs to ints */ 
    26  i = atoi(argv[1]); 
    27  j = atoi(argv[2]); 
    28  k = atoi(argv[3]); 
    29  l = atoi(argv[4]); 
    30 
    (gdb) 
    31  printf("You entered the integers %d, %d, %d, and %d.\n", i, j, k, l); 
    32  s = score1(i) + score2(j) + score3(k) + score4(l); 
    33 
    34  printf("Your score is %d.\n", s); 
    35  if (s > 0) { 
    36   pw = getpwuid(getuid()); 
    37   
    38   printf("Thank you!\n"); 
    40   system(cmd); 

我已經開始拆解類似下面的代碼:

(gdb) disas score1 
Dump of assembler code for function score1: 
0x080488b0 <score1+0>: push %ebp 
0x080488b1 <score1+1>: mov %esp,%ebp 
0x080488b3 <score1+3>: cmpl $0xe1e4,0x8(%ebp) 
0x080488ba <score1+10>: setne %al 
0x080488bd <score1+13>: movzbl %al,%eax 
0x080488c0 <score1+16>: sub $0x1,%eax 
0x080488c3 <score1+19>: and $0xa,%eax 
0x080488c6 <score1+22>: pop %ebp 
0x080488c7 <score1+23>: ret 

(gdb) disas score2 
Dump of assembler code for function score2: 
0x080488c8 <score2+0>: push %ebp 
0x080488c9 <score2+1>: mov %esp,%ebp 
0x080488cb <score2+3>: mov 0x8049f88,%eax 
0x080488d0 <score2+8>: sub $0x2,%eax 
0x080488d3 <score2+11>: mov %eax,0x8049f88 
0x080488d8 <score2+16>: cmp 0x8(%ebp),%eax 
0x080488db <score2+19>: setne %al 
0x080488de <score2+22>: movzbl %al,%eax 
0x080488e1 <score2+25>: sub $0x1,%eax 
0x080488e4 <score2+28>: and $0xa,%eax 
0x080488e7 <score2+31>: pop %ebp 
0x080488e8 <score2+32>: ret 

(gdb) disas score3 
    Dump of assembler code for function score3: 
    0x080488e9 <score3+0>: push %ebp 
    0x080488ea <score3+1>: mov %esp,%ebp 
    0x080488ec <score3+3>: mov 0x8(%ebp),%eax 
    0x080488ef <score3+6>: and $0xf,%eax 
    0x080488f2 <score3+9>: mov 0x8048e00(,%eax,4),%eax 
    0x080488f9 <score3+16>: pop %ebp 
    0x080488fa <score3+17>: ret 

(gdb) disas score4 
Dump of assembler code for function score4: 
0x080488fb <score4+0>: push %ebp 
0x080488fc <score4+1>: mov %esp,%ebp 
0x080488fe <score4+3>: push %ebx 
0x080488ff <score4+4>: mov 0x8(%ebp),%eax 
0x08048902 <score4+7>: movzwl %ax,%edx 
0x08048905 <score4+10>: mov %eax,%ecx 
0x08048907 <score4+12>: shr $0x10,%ecx 
0x0804890a <score4+15>: lea 0x0(,%edx,8),%eax 
0x08048911 <score4+22>: sub %edx,%eax 
0x08048913 <score4+24>: cmp %ecx,%eax 
0x08048915 <score4+26>: jne 0x8048920 <score4+37> 
0x08048917 <score4+28>: mov $0x8000ffff,%ebx 
0x0804891c <score4+33>: test %edx,%ecx 
0x0804891e <score4+35>: jne 0x8048940 <score4+69> 
0x08048920 <score4+37>: mov %ecx,%eax 
0x08048922 <score4+39>: xor %edx,%eax 
0x08048924 <score4+41>: cmp $0xf00f,%eax 
0x08048929 <score4+46>: jne 0x804893b <score4+64> 
0x0804892b <score4+48>: mov %ecx,%eax 
0x0804892d <score4+50>: or  %edx,%eax 
0x0804892f <score4+52>: mov $0xa,%ebx 
0x08048934 <score4+57>: cmp $0xf42f,%eax 
---Type <return> to continue, or q <return> to quit--- 
0x08048939 <score4+62>: je  0x8048940 <score4+69> 
0x0804893b <score4+64>: mov $0x0,%ebx 
0x08048940 <score4+69>: mov %ebx,%eax 
0x08048942 <score4+71>: pop %ebx 
0x08048943 <score4+72>: pop %ebp 
0x08048944 <score4+73>: ret 

我已經開始檢查score2。 我所做的是:

gdb) x 0x8049f88 
0x8049f88 <secret>:  "Чй" 
(gdb) disas 0x8049f88 
Dump of assembler code for function secret: 
0x08049f88 <secret+0>: dec %dl 
0x08049f8a <secret+2>: add %al,(%eax) 
End of assembler dump. 

而且我在這裏失去了

這是我認爲到目前爲止情況(見註釋):

(gdb) disas score2 
Dump of assembler code for function score2: 
0x080488c8 <score2+0>: push %ebp 
0x080488c9 <score2+1>: mov %esp,%ebp   'Copy %esp into %ebp 
0x080488cb <score2+3>: mov 0x8049f88,%eax  'executing: decrement and add 
0x080488d0 <score2+8>: sub $0x2,%eax   ' subtract $0x2 from %eax (How can I figure out what $0x2 
0x080488d3 <score2+11>: mov %eax,0x8049f88 'Have no idea what this does 
0x080488d8 <score2+16>: cmp 0x8(%ebp),%eax compare of %ebp to %eax (why %ebp has 0x8 preceding it?) 
0x080488db <score2+19>: setne %al 'I have no idea what this does 
0x080488de <score2+22>: movzbl %al,%eax 
0x080488e1 <score2+25>: sub $0x1,%eax 
0x080488e4 <score2+28>: and $0xa,%eax 
0x080488e7 <score2+31>: pop %ebp 
0x080488e8 <score2+32>: ret 

如果你可以幫助我理解score2對一個整數執行什麼類型的轉換,以及我可以在gdb中運行哪些命令來幫助我,我真的很感激它,並會嘗試重新計算我自己也是(得分1-3)。我只是迷失在這裏。

+1

您似乎沒有發佈這些函數的源代碼......另外,如果您對'score2'感興趣,爲什麼還要發佈其他所有函數的反彙編程序? –

+2

如果您想查看編譯器將生成的內容,請使用'-S'開關運行gcc,以使用'-O0'生成彙編代碼以禁用優化。以此作爲指導(或作爲替代)。 –

+0

[示例代碼](http://sscce.org/)應該是完整的,簡潔和可編輯的。樣本不完整,gdb輸出的文物(行號和提示)阻止了它的編譯。請通過編輯您的問題來清理示例代碼。另外,請選擇[有意義的名稱](http://tinyurl.com/so-hints)。 – outis

回答

2

爲了理解反彙編,你只需要知道兩件事。您需要知道的第一件事是CPU支持的所有指令和尋址模式以及它們的工作方式。第二件事是彙編/反彙編程序使用的語法。如果不熟悉這些事情,你將無處可尋。

對於「你會一事無成」的一個例子,這裏的score2:

0x080488c8 <score2+0>: push %ebp    ;Save EBP 
0x080488c9 <score2+1>: mov %esp,%ebp   ;EBP = address of stack frame 
0x080488cb <score2+3>: mov 0x8049f88,%eax ;EAX = the data at address 0x8049f88 
0x080488d0 <score2+8>: sub $0x2,%eax   ;EAX = EAX - 2 
0x080488d3 <score2+11>: mov %eax,0x8049f88 ;The value at address 0x8049f88 = eax 
0x080488d8 <score2+16>: cmp 0x8(%ebp),%eax ;Compare the int at offset 8 in the stack frame with EAX 
0x080488db <score2+19>: setne %al    ;If the int at offset 8 in the stack frame wasn't equal to EAX, set AL to 0, otherwise set AL to 1 
0x080488de <score2+22>: movzbl %al,%eax   ;Zero-extend AL to EAX (so EAX = 0 or 1) 
0x080488e1 <score2+25>: sub $0x1,%eax   ;Decrease EAX (so EAX = -1 or 0) 
0x080488e4 <score2+28>: and $0xa,%eax   ;EAX = EAX AND 0x0A (so EAX = 0xA or 0) 
0x080488e7 <score2+31>: pop %ebp    ;Restore previous EBP 
0x080488e8 <score2+32>: ret      ;Return 

轉換回C,這可能看起來像:

int score2(int something) { 
    some_global_int -= 2; 
    if(some_global_int == something) return 0; 
    else return 0x0A; 
} 

當然,我只打了這一起在5分鐘內,並沒有再檢查任何東西或測試任何東西,所以它可能是錯的。

閱讀上述「score2」代碼後,您是否更接近理解其他功能的反彙編?

根據您最初嘗試評論score2的方式,您應該要求某人爲您完成所有工作(並且什麼也不學,並且無法知道該人是對還是錯),或要求最好學習80x86彙編(以及AT & T語法)。

1

我假設你給了某種帶有分數函數的編譯庫,並且你試圖將它作爲某種作業項目進行逆向工程。在這種情況下,我建議你開始熟悉標準C調用約定cdecl

基本上,esp指向堆棧,函數的參數在被調用之前被壓入到堆棧中,因此C函數首先將esp移入ebp,然後它可以通過從ebp中減去值並取消引用來訪問參數地址。它使用ebp來達到這個目的,所以它仍然可以修改esp,以便在堆棧中添加更多的局部變量,而不會丟失對參數存儲位置的跟蹤。

總之,這裏是你開始score2以幫助概述:

(gdb) disas score2 
Dump of assembler code for function score2: 
0x080488c8 <score2+0>: push %ebp 
0x080488c9 <score2+1>: mov %esp,%ebp ; This just saves a copy of the top of our stack to read arguments with 
0x080488cb <score2+3>: mov 0x8049f88,%eax ; Load a value from a memory location (the number is a memory address, probably to a global variable) 
0x080488d0 <score2+8>: sub $0x2,%eax  ; Subtract 2 
0x080488d3 <score2+11>: mov %eax,0x8049f88 ; Store the new value into the same memory location 
0x080488d8 <score2+16>: cmp 0x8(%ebp),%eax ; Compare the first argument of the function to that value 
0x080488db <score2+19>: setne %al    ; Sets the lower byte of eax to 1 if they don't match 
0x080488de <score2+22>: movzbl %al,%eax  ; Sets al to eax, zeroing the upper bytes so eax is just 1 or 0 now 
0x080488e1 <score2+25>: sub $0x1,%eax  ; Subtract 1 from eax 
0x080488e4 <score2+28>: and $0xa,%eax  ; eax = eax & 0xa 
0x080488e7 <score2+31>: pop %ebp   
0x080488e8 <score2+32>: ret     ; Return eax 

因此,這意味着有某種全局變量保存在0x8049f88 (姑且稱之爲x)和score2字面翻譯成:

int score2(int n) { 
    x -= 2; 
    if (n == x) 
    n = 1; 
    else 
    n = 0; 
    n--; 
    n = n & 0xa; 
    return n; 
} 

編輯:布倫丹的例子是一樣的,但可能看起來更像是原來的代碼。仔細查看幾次,並將其與裝配輸出進行比較。

下一步現在看看0x8049f88處的變量是什麼。嘗試在gdb中運行awatch *0x8049f88以使其在每次訪問時都停止,並且還要print *0x8049f88以查看存儲在那裏的內容。如果您對彙編語言不太熟悉,則還應該運行set disassembly-flavor intel。該語法將匹配您更可能在Internet上找到的示例。

0

我認爲你不能訪問函數的源代碼,並且你應該嘗試找到數字來獲得大分數。你可能應該編輯你的問題來顯示score.h的內容,或者只是相關的部分,如果它很長。另外請注意,在0x8049f88反彙編沒有意義。而是使用gdb的x命令來顯示該位置,並進行相應的編輯。

雖然您可以通過反彙編來攻擊問題(如上所述),但您也可以嘗試使用不同的主程序,該程序會報告個別分數?()調用的結果,並通過一系列值對於大的價值。使用score2(),main()內的循環將不起作用,因爲score2()從內存中的單詞中減去2。所以,如果你想嘗試大量的輸入,你需要在shell代碼循環中用不同的參數調用程序。例如,如果你使用bash:

for i in {1..1000}; do testScore2 $i; done 

其中testScore2是隻運行score2主程序()及其參數,並將結果報告。當然,因爲score2()只能產生兩個不同的結果,正如前面兩個答案中詳細解釋的那樣,使用兩個以上的參數值測試score2()並不會有意義。我上面展示了shell代碼,因爲您可能想要將這種技術與其他一些評分函數結合使用。