2016-03-31 56 views
1

This SO上的問題/答案顯示瞭如何使用GDB更改內存中的值,但在給出的示例中,它選擇了一個地址來設置先前未使用的值選擇地址以更改內存中的值

例如,返回值更改爲22,筆者確實

set {unsigned char}0x00000000004004b9 = 22 

然而,爲什麼會這個地址0x00000000004004b9是地址改變?如果你查看disas/r的輸出,地址0x00000000004004b9沒有被使用,那麼爲什麼使用這個設置爲22?我試圖瞭解如何知道哪個地址需要更改爲(在本例中)更改返回值,如果disas/r的輸出沒有顯示它。

代碼

$ cat t.c 
int main() 
{ 
    return 42; 
} 

$ gcc t.c && ./a.out; echo $? 
42 

$ gdb --write -q ./a.out 
(gdb) disas/r main 
Dump of assembler code for function main: 
    0x00000000004004b4 <+0>:  55  push %rbp 
    0x00000000004004b5 <+1>:  48 89 e5  mov %rsp,%rbp 
    0x00000000004004b8 <+4>:  b8 2a 00 00 00 mov $0x2a,%eax 
    0x00000000004004bd <+9>:  5d  pop %rbp 
    0x00000000004004be <+10>: c3  retq 
End of assembler dump. 
(gdb) set {unsigned char}0x00000000004004b9 = 22 
(gdb) disas/r main 
Dump of assembler code for function main: 
    0x00000000004004b4 <+0>:  55  push %rbp 
    0x00000000004004b5 <+1>:  48 89 e5  mov %rsp,%rbp 
    0x00000000004004b8 <+4>:  b8 16 00 00 00 mov $0x16,%eax <<< ---changed 
    0x00000000004004bd <+9>:  5d  pop %rbp 
    0x00000000004004be <+10>: c3  retq 
End of assembler dump. 
(gdb) q 

$ ./a.out; echo $? 
22 <<<--- Just as desired 

回答

1

我想了解如何知道需要改變(在這個例子中)改變返回值,如果disas輸出/ R沒有哪個地址展示下。

要理解這一點,您需要了解instruction encoding。這裏的指令是「立即移動32位常量來註冊」。常數是指令的部分(這就是「直接」意味着什麼)。這可能有助於編譯此相反:

int foo() { return 0x41424344; } 
int bar() { return 0x45464748; } 
int main() { return foo() + bar(); } 

當你編譯它,你應該會看到類似的東西:

(gdb) disas/r foo 
Dump of assembler code for function foo: 
    0x00000000004004ed <+0>:  55  push %rbp 
    0x00000000004004ee <+1>:  48 89 e5  mov %rsp,%rbp 
    0x00000000004004f1 <+4>:  b8 44 43 42 41 mov $0x41424344,%eax 
    0x00000000004004f6 <+9>:  5d  pop %rbp 
    0x00000000004004f7 <+10>: c3  retq 
End of assembler dump. 
(gdb) disas/r bar 
Dump of assembler code for function bar: 
    0x00000000004004f8 <+0>:  55  push %rbp 
    0x00000000004004f9 <+1>:  48 89 e5  mov %rsp,%rbp 
    0x00000000004004fc <+4>:  b8 48 47 46 45 mov $0x45464748,%eax 
    0x0000000000400501 <+9>:  5d  pop %rbp 
    0x0000000000400502 <+10>: c3  retq 
End of assembler dump. 

現在,你可以清楚地看到那裏的指令流中的每個字節立即常量駐留(並且x86也使用小端編碼)。

關於x86指令編碼的標準參考是Intel instruction set reference。您可以在第3-528頁找到0xB8說明。