簡體   English   中英

更改內存中的“通話”地址?

[英]Change a 'call' address in memory?

這是用於64位x86 Intel處理器的。

在GDB中,我可以看到:

0x400500 <main+50>: call 0x400100 <somefunc>

但是,當我檢查0x400500處的內存時,看不到任何對“ 0x400100”的引用,附近的寄存器中也沒有任何明顯的內容。

如何“知道”在哪里打電話。 看起來很簡單,但我一直找不到答案。

我試圖用例如上述功能的參數調用系統,但只有有限的內存訪問權限。 請注意,這只是出於娛樂目的,是挑戰練習的一部分。

如何“知道”在哪里打電話。

調用地址是調用指令的偏移量。

例:

int foo() { return 42; }
int main() { return foo(); }

gcc -g t.c
gdb -q ./a.out

(gdb) disas/r main
Dump of assembler code for function main:
   0x00000000004004f8 <+0>: 55  push   %rbp
   0x00000000004004f9 <+1>: 48 89 e5    mov    %rsp,%rbp
   0x00000000004004fc <+4>: b8 00 00 00 00  mov    $0x0,%eax
   0x0000000000400501 <+9>: e8 e7 ff ff ff  callq  0x4004ed <foo>
   0x0000000000400506 <+14>:    5d  pop    %rbp
   0x0000000000400507 <+15>:    c3  retq
End of assembler dump.

(gdb) p &foo
$1 = (int (*)()) 0x4004ed <foo>

(gdb) p/x 0x4004ed - 0x0000000000400506
$2 = 0xffffffe7

注意callqe7 ff ff ff個字節。 這就是偏移量,用little-endian拼寫。

正常的調用指令被編碼為call rel32 ,具有相對位移而不是絕對位移。 與往常一樣,檢查指令集參考手冊條目以了解指令的編碼方式。

要獲取GDB的內置反匯編以包括原始機器代碼字節,請使用disas /r (不知道如何在layout asm / layout reg獲取asm窗口的行為。) objdump默認包含機器代碼(十六進制)。 我在.bashrc中使用alias disas='objdump -drwC -Mintel'


在GDB中 ,您不需要修改在機器指令中編碼的相對位移:您可以僅stepicall並且它們使用jump *0x1234567 GDB命令在其他地方繼續執行。 set $pc = 0x1234567來更改EIP / RIP而不執行“ continue”

請參見是否可以在GDB調試器中“跳轉” /“跳過”?

因此,您可以讓調用指令推送一個返回地址並跳轉,然后再跳轉到其他地方以假裝,就像您剛跳到那里一樣。 僅當可訪問原始call目標時,這才可能起作用。 我不知道x86是否會因為將RIP設置為不可執行的內存而出錯,還是不會在嘗試運行第一條指令之前出錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM