Skip to content

Commit e3dce6b

Browse files
committed
[writeup] add heroctf 2021 (part)
1 parent fe437a4 commit e3dce6b

File tree

27 files changed

+996
-6
lines changed

27 files changed

+996
-6
lines changed

README.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33

44
### Reverse Engineering
55

6+
- _HeroCTF 2021_
7+
- [Kernel Module #3](heroctf-2021/kernel-module-3/writeup.md)
8+
- [Kernel Module #2](heroctf-2021/kernel-module-2/writeup.md)
9+
- [Kernel Module #1](heroctf-2021/kernel-module-1/writeup.md)
10+
- [Win But Twisted](heroctf-2021/win-but-twisted/writeup.md)
11+
- [H4XOR](heroctf-2021/h4XOR/writeup.md)
12+
- [JNI](heroctf-2021/JNI/writeup.md)
13+
- [sELF Control](heroctf-2021/self-control/writeup.md)
14+
615
- _GLSC CTF 2021_
716
- [Collisions](glsc-ctf-2021/collisions/writeup.md)
817
- [Scr1pt1ng](glsc-ctf-2021/scr1pt1ng/writeup.md)
@@ -55,7 +64,7 @@
5564
- [Slippery Shellcode](picoctf-2019/slippery-shellcode/writeup.md)
5665
- [Messy Malloc](picoctf-2019/messy-malloc/writeup.md)
5766
- [Leap Frog](picoctf-2019/leap-frog/writeup.md)
58-
- [GoT](picoctf-2019/GoT/writeup.md)
67+
- [GoT](picoctf-2019/got/writeup.md)
5968
- [Pointy](picoctf-2019/pointy/writeup.md)
6069
- [ROP64](picoctf-2019/rop64/shellcode.py)
6170
- [AfterLife](picoctf-2019/AfterLife/shellcode.py)
@@ -66,6 +75,12 @@
6675

6776
### Web
6877

78+
- _HeroCTF 2021_
79+
- [You Should Die](heroctf-2021/you-should-die/writeup.md)
80+
- [Transfer](heroctf-2021/transfer/writeup.md)
81+
- [PwnQL #2](heroctf-2021/pwnQL-2/writeup.md)
82+
- [PwnQL #1](heroctf-2021/pwnQL-1/writeup.md)
83+
6984
- _GLSC CTF 2021_
7085
- [MR. Roboto](glsc-ctf-2021/mr.roboto/writeup.md)
7186

@@ -80,7 +95,7 @@
8095
- [Cereal Hacker 1](picoctf-2019/cereal-hacker1/writeup.md)
8196
- [Cereal Hacker 2](picoctf-2019/cereal-hacker2/writeup.md)
8297
- [Irish-Name-Repo 1](picoctf-2019/Irish-Name-Repo-1/writeup.md)
83-
- [Empire 1](picoctf-2019/Empire1/writeup.md)
98+
- [Empire 1](picoctf-2019/empire1/writeup.md)
8499

85100
- _CTFLearn_
86101
- [Don't Bump Your Head(er)](ctflearn/Don'tBumpYourHeader/writeup.md)
@@ -104,10 +119,10 @@
104119

105120
- _PicoCTF 2019_
106121
- [WhitePages](picoctf-2019/WhitePages/decode.py)
107-
- [Mr. WorldWide](picoctf-2019/Mr-WorldWide/writeup.md)
122+
- [Mr. WorldWide](picoctf-2019/mr-worldWide/writeup.md)
108123
- [Caesar](picoctf-2019/caesar/decode.py)
109124
- [ROT13](picoctf-2019/rot13/writeup.md)
110-
- [The Numbers](picoctf-2019/the_numbers/writeup.md)
125+
- [The Numbers](picoctf-2019/the-numbers/writeup.md)
111126

112127
- _Hacker101 CTF_
113128
- [Model E1337 Rolling Code Lock](hacker101-ctf/model-e1337-rolling-code-lock/writeup.md)
@@ -119,5 +134,3 @@
119134
- [Shark on Wire1](picoctf-2019/shark-on-wire1/writeup.md)
120135
- [ASM2](picoctf-2019/asm2/writeup.md)
121136
- [Like1000](picoctf-2019/like1000/writeup.md)
122-
123-

ctflearn/5x5/decode.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python
2+
3+
4+
def init_key():
5+
key = [[]]
6+
i = ord('A')
7+
j = 0
8+
9+
while i < ord('Z')+1:
10+
if len(key[-1]) == 5:
11+
key.append([])
12+
13+
key[-1].append(chr(i))
14+
print(chr(i), end=' ')
15+
j += 1
16+
if j % 5 == 0:
17+
print()
18+
i+=1
19+
if i == ord('K'):
20+
i+=1
21+
return key
22+
23+
def decode(key, enc):
24+
parts = enc.split(',')
25+
flag = ['?']*len(parts)
26+
27+
for i in range(len(parts)):
28+
flag[i] = parts[i]
29+
if not parts[i][0].isdigit():
30+
continue
31+
r = 0
32+
c = 0
33+
for a in parts[i]:
34+
if a.isdigit():
35+
if r == 0:
36+
r = int(a)
37+
else:
38+
c = int(a)
39+
f = key[int(r)-1][int(c)-1]
40+
flag[i] = f
41+
42+
return flag
43+
44+
enc = "1-3,4-4,2-1,{,4-4,2-3,4-5,3-2,1-2,4-3,_,4-5,3-5,}"
45+
key = init_key()
46+
flag = decode(key, enc)
47+
print(''.join(flag))

heroctf-2021/JNI/writeup.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
Decompile *JNI.apk* with *apktool*, go direct to *fr.heroctf.jni.MainActivity* class as indicated in *AndroidManifest.xml*.
3+
4+
```xml
5+
...
6+
<activity android:name="fr.heroctf.jni.MainActivity">
7+
<intent-filter>
8+
<action android:name="android.intent.action.MAIN"/>
9+
<category android:name="android.intent.category.LAUNCHER"/>
10+
</intent-filter>
11+
</activity>
12+
...
13+
```
14+
15+
*fr.heroctf.jni.MainActivity* is defined in *smali/fr/heroctf/jni/MainActivity.smali*. *checkFlag* function quickly grabbed eyeballs. As it's a native function, we need to look for the lower-level implementation, which is in ``lib``.
16+
17+
```java
18+
...
19+
invoke-virtual {p0, v0}, Lfr/heroctf/jni/MainActivity;->checkFlag(Ljava/lang/String;)Z
20+
...
21+
# virtual methods
22+
.method public native checkFlag(Ljava/lang/String;)Z
23+
.end method
24+
```
25+
26+
There are 4 *so* for 4 architectures respectively.
27+
28+
```bash
29+
lib/
30+
lib/x86
31+
lib/x86/libnative-lib.so
32+
lib/arm64-v8a
33+
lib/arm64-v8a/libnative-lib.so
34+
lib/armeabi-v7a
35+
lib/armeabi-v7a/libnative-lib.so
36+
lib/x86_64
37+
lib/x86_64/libnative-lib.so
38+
```
39+
40+
I decompiled the one for *x86_64*, *lib/x86_64/libnative-lib.so*.
41+
42+
```c
43+
ulong Java_fr_heroctf_jni_MainActivity_checkFlag
44+
(_JNIEnv *param_1,undefined8 param_2,_jstring *param_3)
45+
{
46+
char *input;
47+
size_t len;
48+
long in_FS_OFFSET;
49+
byte ret;
50+
uchar is_copy;
51+
long canary;
52+
53+
canary = *(long *)(in_FS_OFFSET + 0x28);
54+
input = (char *)GetStringUTFChars(param_1,param_3,&is_copy);
55+
if ((((is_copy == '\x01') && (len = strlen(input), len == 3)) && (*input == '6')) &&
56+
((input[1] == '6' && (input[2] == '6')))) {
57+
ret = 1;
58+
}
59+
else {
60+
ret = 0;
61+
}
62+
if (*(long *)(in_FS_OFFSET + 0x28) == canary) {
63+
return (ulong)ret;
64+
}
65+
/* WARNING: Subroutine does not return */
66+
__stack_chk_fail();
67+
}
68+
```
69+
70+
According to the way it check flag, it's easy to point out what the kernel is, by adding the flag prefix and suffix, the flag is ``Hero{666}``.
71+

heroctf-2021/h4XOR/decrypt.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env python3
2+
from pwn import xor
3+
from random import randint
4+
from os import urandom
5+
6+
7+
output_img = open("flag.png", "wb")
8+
input_img = open("flag.png.enc", "rb").read()
9+
10+
header = b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00"
11+
key = [0]*9
12+
for i in range(9):
13+
key[i] = int(input_img[i]) ^ int(header[i])
14+
output_img.write(xor(input_img, key))

heroctf-2021/h4XOR/writeup.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
From ``xor.py`` we know it generate a random key and xor it with the image to generate a encrypted one.
3+
4+
```python
5+
#!/usr/bin/env python3
6+
from os import urandom
7+
from random import randint
8+
from pwn import xor
9+
10+
input_img = open("flag.png", "rb").read()
11+
output_img = open("flag.png.enc", "wb")
12+
13+
key = urandom(8) + bytes([randint(0, 9)])
14+
output_img.write(xor(input_img, key))
15+
```
16+
17+
Since the origin image is *png* format, the header is widely known. If we xor the header with the first 9 bytes of encrypted image, we are able to get the key.
18+
19+
```python
20+
key = header ^ flag.png.enc[:9]
21+
```
22+
23+
```python
24+
output_img = open("flag.png", "wb")
25+
input_img = open("flag.png.enc", "rb").read()
26+
27+
header = b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00"
28+
key = [0]*9
29+
for i in range(9):
30+
key[i] = int(input_img[i]) ^ int(header[i])
31+
output_img.write(xor(input_img, key))
32+
```
33+
34+
```bash
35+
$ file flag.png
36+
flag.png: PNG image data, 300 x 300, 8-bit/color RGBA, non-interlaced
37+
```
38+
39+
Open the decrypted image *flag.png* with ``ristretto``, the flag is at the bottom left, ``Hero{123_xor_321}``.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
The *cat* command on server is malfunctioning, *which* command said *cat* command is using */bin/cat*. To correct it, we remove */bin/cat*, the whole vm is built upon *busybox*, so soft link */bin/busybox* to */bin/cat*.
3+
4+
```bash
5+
rm -f /bin/cat
6+
ln -s /bin/busybox /bin/cat
7+
```
8+
9+
*cat /dev/safe* to get the flag.
10+
11+
```bash
12+
cat /dev/safe
13+
Hero{s0_yOu_C4n_r34d_Fr0m_cHrD3v}
14+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python
2+
import string
3+
4+
expected = "OpenSesame"
5+
buf = ['?']*len(expected)
6+
7+
for i in range(len(buf)):
8+
for c in string.printable:
9+
buf[i] = c
10+
11+
if ord(buf[i]) + 0xbf < 0x1a:
12+
a = ord(buf[i]) - 0xd
13+
if ord(buf[i]) + ord('\r') < ord('['):
14+
a = ord(buf[i]) + ord('\r')
15+
buf[i] = chr(a)
16+
else:
17+
a = -0xd
18+
if ord(buf[i]) + 0xd < 0x7b:
19+
a = ord('\r')
20+
buf[i] = chr(ord(buf[i]) + a)
21+
22+
if buf[i] == expected[i]:
23+
buf[i] = c
24+
print(buf, end='\r')
25+
break
26+
buf[i] = '?'
27+
28+
print()
29+
print(''.join(buf))

0 commit comments

Comments
 (0)