Skip to content

Commit fb5bbb9

Browse files
committed
[writeup] add crypto & re (part)
1 parent 4496f6b commit fb5bbb9

File tree

34 files changed

+1272
-13
lines changed

34 files changed

+1272
-13
lines changed

README.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
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)
6+
- _HeroCTF V3_
7+
- [Kernel Module #3](heroctf-v3/kernel-module-3/writeup.md)
8+
- [Kernel Module #2](heroctf-v3/kernel-module-2/writeup.md)
9+
- [Kernel Module #1](heroctf-v3/kernel-module-1/writeup.md)
10+
- [Win But Twisted](heroctf-v3/win-but-twisted/writeup.md)
11+
- [H4XOR](heroctf-v3/h4XOR/writeup.md)
12+
- [JNI](heroctf-v3/JNI/writeup.md)
13+
- [sELF Control](heroctf-v3/self-control/writeup.md)
1414

1515
- _GLSC CTF 2021_
1616
- [Collisions](glsc-ctf-2021/collisions/writeup.md)
@@ -41,6 +41,8 @@
4141
- [Dialtone](google-ctf-2019/dialtone/writeup.md)
4242

4343
- _CTFLearn_
44+
- [Rotterdam](ctflearn/rotterdam/writeup.md)
45+
- [Jumper](ctflearn/jumper/writeup.md)
4446
- [Rangoon](ctflearn/rangoon/writeup.md)
4547
- [Ramada](ctflearn/ramada/writeup.md)
4648
- [Recklinghausen](ctflearn/recklinghausen/writeup.md)
@@ -75,11 +77,11 @@
7577

7678
### Web
7779

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)
80+
- _HeroCTF V3_
81+
- [You Should Die](heroctf-v3/you-should-die/writeup.md)
82+
- [Transfer](heroctf-v3/transfer/writeup.md)
83+
- [PwnQL #2](heroctf-v3/pwnQL-2/writeup.md)
84+
- [PwnQL #1](heroctf-v3/pwnQL-1/writeup.md)
8385

8486
- _GLSC CTF 2021_
8587
- [MR. Roboto](glsc-ctf-2021/mr.roboto/writeup.md)
@@ -114,6 +116,12 @@
114116

115117
### Crypto
116118

119+
- _CTFLearn_
120+
- [AlexCTF CR2 Many Time Secrets](ctflearn/alexctf-cr2-many-time-secrets/writeup.md)
121+
- [RSA Beginner](ctflearn/rsa-beginner/decrypt.py)
122+
- [RSA Noob](ctflearn/rsa-noob/decrypt.py)
123+
- [Substitution](ctflearn/substitution-cipher/substitution.py)
124+
117125
- _Google CTF 2019_
118126
- [Cryptoqkd](google-ctf-2019/cryptoqkd.web.ctfcompetition.com/post.py)
119127

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import string
2+
3+
msg = []
4+
5+
with open('msg', 'r') as fd:
6+
buf = fd.readlines()
7+
print('len of one line', len(buf[0].strip()))
8+
msg = ''.join([l.strip() for l in buf])
9+
10+
msg = [int(msg[i:i+2], 16) for i in range(0, len(msg), 2)]
11+
prefix = "ALEXCTF{"
12+
13+
plain = [chr(msg[i] ^ ord(prefix[i])) for i in range(len(prefix))]
14+
print(''.join(plain))
15+
16+
# Guess the plain starts with "Dear Friend"
17+
plain = ''.join(plain) + "end"
18+
print(plain)
19+
20+
prefix = ''.join(map(chr, [msg[i] ^ ord(plain[i]) for i in range(len(plain))]))
21+
print(prefix)
22+
23+
# Guess flag starts with "ALEXFLAG{HERE_"
24+
prefix += "E_"
25+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i]) for i in range(len(prefix))]))
26+
print(plain)
27+
28+
# Found some meaningful words in partially decoded message
29+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i%len(prefix)]) for i in range(len(msg))]))
30+
print(plain)
31+
32+
i = plain.find('nderstood')
33+
plain = plain[:i-1] + 'u' + plain[i:]
34+
i = plain.find('sed', i)
35+
plain = plain[:i-1] + 'u' + plain[i:]
36+
i = plain.find('time ', i)
37+
plain = plain[:i+5] + 'padding' + plain[i+5+7:]
38+
i = plain.find("kcz", i)
39+
plain = plain[:i] + 'key' + plain[i+3:]
40+
i = plain.find("gree", i)
41+
plain = plain[:i-1] + 'a' + plain[i:]
42+
i = plain.find("ncryption", i)
43+
plain = plain[:i-1] + 'e' + plain[i:]
44+
i = plain.find("schcne", i)
45+
plain = plain[:i] + 'scheme' + plain[i+6:]
46+
print(plain)
47+
48+
prefix = ''.join(map(chr, [msg[i] ^ ord(plain[i]) for i in range(len(plain))]))
49+
print("== with modified plain text")
50+
print(prefix)
51+
52+
# Now we know the flag starts with "ALEXCTF{HERE_GOES_"
53+
# and the plain text becomes "Dear Friend, This "
54+
prefix = "ALEXCTF{HERE_GOES_"
55+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i%len(prefix)]) for i in range(len(msg))]))
56+
print("== with prefix:", prefix)
57+
print(plain)
58+
59+
# Got more words by guessing "THE_FLAG", but still not completely right
60+
prefix = prefix + "THE_FLAG"
61+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i%len(prefix)]) for i in range(len(msg))]))
62+
print("== with prefix:", prefix)
63+
print(plain)
64+
65+
i = plain.find("-@8O")
66+
plain = plain[:i] + " I u" + plain[i+4:]
67+
i = plain.find("encry", i)
68+
plain = plain[:i+5] + "ption" + plain[i+5+5:]
69+
i = plain.find("-d}Nhod", i)
70+
plain = plain[:i] + " method" + plain[i+7:]
71+
i = plain.find("cracfl", i)
72+
plain = plain[:i+4] + "ked " + plain[i+4+4:]
73+
i = plain.find("kepy", i)
74+
plain = plain[:i+3] + "t secure" + plain[i+3+8:]
75+
i = plain.find("yb|8[", i)
76+
plain = plain[:i] + "you a" + plain[i+5:]
77+
i = plain.find("thdz8_n", i)
78+
plain = plain[:i] + "this e" + plain[i+6:]
79+
plain = plain[:-1] + "s"
80+
print(plain)
81+
82+
prefix = ''.join(map(chr, [msg[i] ^ ord(plain[i]) for i in range(len(plain))]))
83+
print("== with modified plain text")
84+
print(prefix)
85+
86+
# now we know the flag is "ALEXCTF{HERE_GOES_THE_KEY}", test again
87+
prefix = "ALEXCTF{HERE_GOES_THE_KEY}"
88+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i%len(prefix)]) for i in range(len(msg))]))
89+
print("== with prefix:", prefix)
90+
print(plain)
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
As the key is partially known, the prefix *"ALEXCTF{"*, we shall be able to get part of the plain text by xor it with the cipher text.
3+
4+
```python
5+
plain = [chr(msg[i] ^ ord(prefix[i])) for i in range(len(prefix))]
6+
print(''.join(plain))
7+
```
8+
9+
The decoded text is *"Dear Fri"*, guessed the plain text starts with *"Dear Friend"*. Decrypt key with it we got *"ALEXFLAG{HER"*.
10+
11+
```python
12+
prefix = ''.join(map(chr, [msg[i] ^ ord(plain[i]) for i in range(len(plain))]))
13+
```
14+
15+
Guessed the following characters are "E_", so the decrypted key became *"ALEXFLAG{HERE_"*. So the plain text starts with *"Dear Friend, "*. Tried to decrypt the whole plain text with it, we found some meaningful words in partially decoded plain text.
16+
17+
```python
18+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i%len(prefix)]) for i in range(len(msg))]))
19+
print(plain)
20+
```
21+
22+
```bash
23+
Dear Friend, Rkix<tgSr.^<Wnderstood my kjs}kkv`s<Wsed One time vbd+ynmLn~cuMn scheme, I hcbro<tf_c.~his the only eh`rrltgQy.zyVhod that is mgwhnqazWto{p[ proven to be&mo<c|_terxever if the kcz bo e[gz7oGcure, Let Me mmo|<ihnab<Cgree with me rl ~oe.Jgd<Gncryption schcne+}ly_n}9
24+
```
25+
26+
Tried to fix some understanable words and decode the key with it.
27+
28+
```python
29+
i = plain.find('nderstood')
30+
plain = plain[:i-1] + 'u' + plain[i:]
31+
i = plain.find('sed', i)
32+
plain = plain[:i-1] + 'u' + plain[i:]
33+
i = plain.find('time ', i)
34+
plain = plain[:i+5] + 'padding' + plain[i+5+7:]
35+
i = plain.find("kcz", i)
36+
plain = plain[:i] + 'key' + plain[i+3:]
37+
i = plain.find("gree", i)
38+
plain = plain[:i-1] + 'a' + plain[i:]
39+
i = plain.find("ncryption", i)
40+
plain = plain[:i-1] + 'e' + plain[i:]
41+
i = plain.find("schcne", i)
42+
plain = plain[:i] + 'scheme' + plain[i+6:]
43+
print(plain)
44+
45+
prefix = ''.join(map(chr, [msg[i] ^ ord(plain[i]) for i in range(len(plain))]))
46+
print(prefix)
47+
```
48+
49+
In the output, we can find the next word of key *"GOES"*, so now the decrypted key became *"ALEXCTF{HERE_GOES"*.
50+
51+
```bash
52+
Dear Friend, Rkix<tgSr.^<understood my kjs}kkv`s<used One time paddingLn~cuMn scheme, I hcbro<tf_c.~his the only eh`rrltgQy.zyVhod that is mgwhnqazWto{p[ proven to be&mo<c|_terxever if the key bo e[gz7oGcure, Let Me mmo|<ihnab<agree with me rl ~oe.Jgd<encryption scheme+}ly_n}9
53+
ALEXCTF{HERE_ALEXCTF{HERE}ALEXCTF{HERE_ALEXCTF{HERE}ALEXCTF{HERE_GOESTL{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE_GOEXCTF{HERE_ALEXCTF{HERE_ALEXCTF{HERE}ALEXCTF{HERE_ALEXCTF{HERE}ALEXCTF{HERE_GOEXCTF{HER
54+
```
55+
56+
We are looking for flag, so could it be *"HERE_GOES_THE_FLAG"*? The decoded text is different, still not done yet, but we can see some more meaningful words.
57+
58+
```bash
59+
Dear Friend, This time-@8Onderstood my mistake acm8Osed One time pad encry}}qUn scheme, I heard that-`lis the only encryption-d}Nhod that is mathematicletC proven to be not cracfl|ever if the key is kepy)k_cure, Let Me know if yb|8[gree with me to use thdz8_ncryption scheme alway~'
60+
```
61+
62+
Tried to fix some of them and decode the key.
63+
64+
```python
65+
i = plain.find("-@8O")
66+
plain = plain[:i] + " I u" + plain[i+4:]
67+
i = plain.find("encry", i)
68+
plain = plain[:i+5] + "ption" + plain[i+5+5:]
69+
i = plain.find("-d}Nhod", i)
70+
plain = plain[:i] + " method" + plain[i+7:]
71+
i = plain.find("cracfl", i)
72+
plain = plain[:i+4] + "ked " + plain[i+4+4:]
73+
i = plain.find("kepy", i)
74+
plain = plain[:i+3] + "t secure" + plain[i+3+8:]
75+
i = plain.find("yb|8[", i)
76+
plain = plain[:i] + "you a" + plain[i+5:]
77+
i = plain.find("thdz8_n", i)
78+
plain = plain[:i] + "this e" + plain[i+6:]
79+
plain = plain[:-1] + "s"
80+
print(plain)
81+
82+
prefix = ''.join(map(chr, [msg[i] ^ ord(plain[i]) for i in range(len(plain))]))
83+
print(prefix)
84+
```
85+
86+
Now we could identitfy the flag *"ALEXCTF{HERE_GOES_THE_KEY}"*.
87+
88+
```bash
89+
ALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_FLAGALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_FLAGALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_FLAGALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_THE_F
90+
```
91+
92+
Verified the key by decrypt the whold cipher text with it.
93+
94+
```python
95+
prefix = "ALEXCTF{HERE_GOES_THE_KEY}"
96+
plain = ''.join(map(chr, [msg[i] ^ ord(prefix[i%len(prefix)]) for i in range(len(msg))]))
97+
print(plain)
98+
```
99+
100+
Here is the plain text and the above is the right key, also the flag.
101+
102+
```bash
103+
Dear Friend, This time I understood my mistake and used One time pad encryption scheme, I heard that it is the only encryption method that is mathematically proven to be not cracked ever if the key is kept secure, Let Me know if you agree with me to use this encryption scheme always.
104+
```
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <stdio.h>
2+
3+
unsigned long vals1[30] = {0x00014c4c5e, 0x005130720c, 0x003e87df91, 0x00340ccb70, 0x00676fa321, \
4+
0x002aa1a2a0, 0x005165565c, 0x0005526445, 0x006a480682, 0x0033dfa545, \
5+
0x004c88ea19, 0x0073255b4e, 0x0074c67bfe, 0x0052f90324, 0x006f44e5df, \
6+
0x001435d143, 0x0066d75377, 0x0035b86969, 0x000448dc19, 0x000c13eaf7, \
7+
0x0015fedd23, 0x00422b655c, 0x0061ef012d, 0x000fd42ba5, 0x002ca8f2c9, \
8+
0x00054b8249, 0x006dc2f69d, 0x0076ba54d5, 0x0068e371c0, 0x001551247c
9+
};
10+
unsigned long vals2[30] = {0x0002f21618, 0x00577d3f68, 0x000c838fda, 0x0068e5cdc4, 0x006314b34d, \
11+
0x007a193245, 0x0009525af6, 0x0031a96ada, 0x0056957557, 0x0001610dfe, \
12+
0x002e59bcbf, 0x002051fae0, 0x0068b5e038, 0x0031f0fadb, 0x004160e7a4, \
13+
0x006e7ff823, 0x006130cd85, 0x0063a55548, 0x007a88b47f, 0x000938111f, \
14+
0x006b16ee35, 0x0078cb6446, 0x0016cab7a1, 0x001e9a7cd6, 0x0027f24b7f, \
15+
0x004a9f28e9, 0x00029c5bf9, 0x000ee5248e, 0x007e91a8b2, 0x006add9c6a
16+
};
17+
unsigned long vals3[30] = {0x0053d9c12d, 0x007e4f6f47, 0x0056084aad, 0x0053ce10aa, 0x00349ef85d, \
18+
0x007a19aaaa, 0x001e102afb, 0x005f71a2af, 0x005a6edb6c, 0x0021ca6074, \
19+
0x000de96e1d, 0x006def4121, 0x00626b818b, 0x0071f7f9f7, 0x0064c5dc07, \
20+
0x005c41e208, 0x003934170c, 0x0043ffab5b, 0x006aa9e600, 0x0070f44639, \
21+
0x0072f4fbbb, 0x0034b15564, 0x0055f40b0a, 0x00146e2173, 0x004c244136, \
22+
0x003d5f0e6a, 0x005b745413, 0x0074b3a37f, 0x0048669939, 0x0048659c9f
23+
};
24+
unsigned long vals4[30] = {0x0051095f4d, 0x000bd6fed3, 0x0021d06bec, 0x0068a2be66, 0x0065b4db28, \
25+
0x00523e80b2, 0x00151e2877, 0x007b25fbce, 0x001c3f1002, 0x005f3de306, \
26+
0x005190a5b8, 0x00141e6c1e, 0x0046f23ce0, 0x0002fd6107, 0x0005340b05, \
27+
0x0032e8d951, 0x0031aae0ef, 0x00721b2012, 0x0027b2da28, 0x0053c349bb, \
28+
0x002580f1e2, 0x001a0fb431, 0x00147d67e6, 0x0024ee0a0e, 0x003dd7b640, \
29+
0x0034f01b4d, 0x003d60a616, 0x007f05ad3c, 0x000b8b10dd, 0x007064f0ad
30+
};
31+
unsigned long flag [30] = {0x00a8f10265, 0x00e2b9dd5a, 0x003ed39108, 0x0137df46b0, 0x0163cf89f4, \
32+
0x0130e2005e, 0x0059c5c456, 0x00e4b06978, 0x00b6f2b73e, 0x0073c8b677, \
33+
0x00c89c6ede, 0x0112b6833f, 0x01060a173a, 0x00f81b68de, 0x00d9941c55, \
34+
0x0111dd04a2, 0x0122e71875, 0x014cbd3551, 0x003c2b50ed, 0x00b98307b9, \
35+
0x0119622208, 0x00a8575118, 0x0041cb19f0, 0x005eee93e0, 0x0056973551, \
36+
0x00a7a5c099, 0x00688bacfc, 0x017032876f, 0x00ba9e9447, 0x0138b04da1
37+
};
38+
39+
unsigned long step1(int i) {
40+
unsigned long a = vals4[i];
41+
unsigned long b = flag[i];
42+
return b - a;
43+
}
44+
45+
unsigned long step2(int i, unsigned long c) {
46+
unsigned long a = vals3[i];
47+
return a ^ c;
48+
}
49+
50+
unsigned long step3(int i, unsigned long c) {
51+
unsigned long a = vals2[i];
52+
return c - a;
53+
}
54+
55+
unsigned long step4(int i, unsigned long c) {
56+
unsigned long a = vals1[i];
57+
return c ^ a;
58+
}
59+
60+
int main() {
61+
unsigned long res;
62+
unsigned long flag[30] = {0};
63+
64+
for (int i = 0; i < 30; i++) {
65+
res = step1(i);
66+
res = step2(i, res);
67+
res = step3(i, res);
68+
res = step4(i, res);
69+
flag[i] = res % 256;
70+
printf("%c", flag[i]);
71+
}
72+
}

ctflearn/bruXOR/decrypt.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python
2+
3+
s = "q{vpln'bH_varHuebcrqxetrHOXEj"
4+
output = []
5+
6+
for c in range(256):
7+
output.append([])
8+
for i in range(len(s)):
9+
a = ord(s[i]) ^ c
10+
if (a >= ord('a') and a <= ord('z')) or\
11+
(a >= ord('A') and a <= ord('Z')) or\
12+
(a >= ord('0') and a <= ord('9')) or\
13+
a == ord('_') or a == ord('{') or a == ord('}') or a == ord('@'):
14+
output[-1].append(chr(a))
15+
if output[-1] and output[-1][-1] == '}':
16+
print(chr(c), ''.join(output[-1]))

ctflearn/jumper/writeup.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
We were asked to find out where does it jump to from *0x80484e2*. The destination is stored in register *eax*.
3+
4+
```asm
5+
80484df: 8b 45 f0 mov -0x10(%ebp),%eax
6+
80484e2: ff d0 call *%eax <--- What address does this jump to??
7+
```
8+
9+
Look back a few lines, there was a ``fgets`` call to get user input and the value is stored in *eax*. When user input is *jump*, ``fgets`` reads only 4 bytes, the last byte is set to *"\x00"* for end of string, therefore, in register *eax* the value is *006d756a* for string *"
10+
jum\x00"*.
11+
12+
```asm
13+
80484b4: 50 push %eax
14+
80484b5: 6a 04 push $0x4
15+
80484b7: 8d 45 f0 lea -0x10(%ebp),%eax
16+
80484ba: 50 push %eax
17+
80484bb: e8 80 fe ff ff call 8048340 <fgets@plt>
18+
```
19+
20+
The coming loop increaments value in *eax* by 5 for 8 times, so when it quit the loop, *eax* became *0x006d756a+40*, which is the flag *0x6d7592* without leading zeros.
21+
22+
```asm
23+
80484cc: 8b 45 f0 mov -0x10(%ebp),%eax
24+
80484cf: 83 c0 05 add $0x5,%eax
25+
80484d2: 89 45 f0 mov %eax,-0x10(%ebp)
26+
80484d5: 83 45 f4 01 addl $0x1,-0xc(%ebp)
27+
80484d9: 83 7d f4 07 cmpl $0x7,-0xc(%ebp)
28+
80484dd: 7e ed jle 80484cc <jump+0x3d>
29+
```

ctflearn/re-verse-dis/find_passwd.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env python3
2+
3+
def bytes_to_array(dat, sz):
4+
dat = dat.split()
5+
arr = []
6+
for i in range(0, len(dat), sz):
7+
arr.append(int(''.join(reversed(dat[i:i+sz])), 16))
8+
return arr
9+
10+
key = "IdontKnowWhatsGoingOn"
11+
s = "08 00 00 00 06 00 00 00 2c 00 00 00 3a 00 00 00 32 00 00 00 30 00 00 00 1c 00 00 00 5c 00 00 00 01 00 00 00 32 00 00 00 1a 00 00 00 12 00 00 00 45 00 00 00 1d 00 00 00 20 00 00 00 30 00 00 00 0d 00 00 00 1b 00 00 00 03 00 00 00 7c 00 00 00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
12+
s = bytes_to_array(s, 4)
13+
pw = []
14+
15+
for i in range(len(key)):
16+
pw.append(ord(key[i]) ^ s[i])
17+
print(''.join(map(chr, pw)))
18+

0 commit comments

Comments
 (0)