SCIST 2023 Final CTF Pwnable / Reverse 官方解答
前言⌗
這次幫 SCIST 設計了 3 題 Pwnable 與 1 題 Reverse,難度大概在簡單到中等。
Pwnable⌗
Way Back Home⌗
- 難度: 易
- 考點:
Ret2Text
漏洞發生在:
char buf[0x20];
gets(buf);
用到 gets
就是個裸的 BOF 然後有一個會直接 system('/bin/sh')
的 Function 可以跳。
Shellcode Without Shell⌗
- 難度: 易
- 考點:
Shellcode
可以直接送 shellcode 給題目跑,但有上 seccomp,只能 open
, read
, write
。
可以直接猜到要 open('/home/pwn/flag.txt')
然後 read()
到某個 buffer 再 write()
到 STDOUT。
Rand Oriented Programming⌗
- 難度: 中
- 考點:
ROP
,Format-string
存在 Format-String 的漏洞,可以任意 Leak Address
rand_region[used_region].space = AllocRandSpace();
printf("What's your name?");
scanf("%s", rand_region[used_region].name);
printf("Random Code Author Recorded:");
printf(rand_region[used_region].name);
used_region++;
ReadExecROP
會直接讀你的輸入並跳上去執行,直接堆 ROP Chain 就可以了:
if((read(0, stack+(LEN_STACK/2), LEN_STACK/2)) < 0) error("read");
asm volatile (
"mov %0, %%rsp\n"
"xor %%rax, %%rax\n"
"xor %%rbx, %%rbx\n"
"xor %%rcx, %%rcx\n"
"xor %%rdx, %%rdx\n"
"xor %%rdi, %%rdi\n"
"xor %%rsi, %%rsi\n"
"xor %%rbp, %%rbp\n"
"xor %%r8, %%r8\n"
"xor %%r9, %%r9\n"
"xor %%r10, %%r10\n"
"xor %%r11, %%r11\n"
"xor %%r12, %%r12\n"
"xor %%r13, %%r13\n"
"xor %%r14, %%r14\n"
"xor %%r15, %%r15\n"
"ret\n"
:
: "r" (stack+(LEN_STACK/2))
);
Reverse⌗
BinWalker Key Validator Service⌗
- 難度: 中
- 考點:
BST
其中最醜的結構其實是 Binary Search Tree,這支程式會把 Key 讀入並塞進去 BST 裡頭,做出 Pre-order Traversal 後將結果加上某個數字後跟某個 Array 做比對。Key 就是 Flag 的 ASCII。
solver.py
:
inorder = [18337, 16920, 16163, 10590, 8183, 5427, 3170, 793, 546, 1938, 2943, 3455, 3196, 4136, 6883, 6817, 6903, 8851, 8192, 8410, 11036, 10592, 12391, 14100, 13843, 12714, 17205, 18732, 18611, 19770, 19149, 19433, 19277, 20831, 19774, 31795, 22193, 21536, 21483, 23838, 22524, 22430, 22199, 22596, 23460, 30712, 27174, 24997, 23889, 23864, 25595, 25281, 26649, 26646, 28360, 30588, 28583, 31879]
target = [18418, 16987, 16234, 10509, 8099, 5448, 3099, 809, 599, 1997, 2868, 3345, 3148, 4191, 6844, 6851, 6814, 8957, 8289, 8360, 11109, 10559, 12308, 14119, 13938, 12760, 17270, 18756, 18668, 19790, 19135, 19418, 19326, 20736, 19722, 31837, 22229, 21631, 21378, 23920, 22476, 22508, 22227, 22561, 23510, 30631, 27218, 25047, 23909, 23886, 25502, 25267, 26730, 26658, 28324, 30557, 28634]
# flag = [0x53, 0x43, 0x49, 0x53, 0x54, 0x7b, 0x79, 0x30, 0x75, 0x5f, 0x4b, 0x6e, 0x30, 0x77, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x73, 0x33, 0x61, 0x72, 0x43, 0x68, 0x5f, 0x74, 0x72, 0x33, 0x33, 0x5f, 0x34, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x30, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x34, 0x76, 0x65, 0x72, 0x73, 0x34, 0x6c, 0x21, 0x7d]
flag = []
for i, t in zip(inorder, target):
for guess in range(0xffff):
if i ^ guess == t:
print(f'[+] Found {guess}')
flag.append(guess)
break
print(len(flag))
for f in flag:
print(chr(f), end='')
print(' ')
Read other posts