Phase 3 (75 pts)
This is a little more challenging but still nonetheless manageable.
Problem Statement
Reflections? Rotations? Translations? This is starting to sound like geometry...
Author: treap_treap
Solution
Sounds complex. Let's look at it using Ghidra.
Ghidra
- phase3
- func3_1
- func3_2
bool phase3(undefined8 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,
undefined4 param_5,undefined4 param_6,undefined4 param_7,undefined4 param_8,char *param_9
)
{
int strCmpRes;
char *__s1;
char *outputStr;
undefined8 in_R8;
undefined8 in_R9;
undefined4 extraout_XMM0_Da;
undefined in_stack_ffffffffffffffc8;
char *inputPtr;
puts("\nReflections? Rotations? Translations? This is starting to sound like geometry...");
__s1 = (char *)calloc(0x29,1);
getInput(extraout_XMM0_Da,param_2,param_3,param_4,param_5,param_6,param_7,param_8,3,param_9,
&DAT_001028d1,__s1,in_R8,in_R9,in_stack_ffffffffffffffc8);
inputPtr = __s1;
while (*inputPtr != '\0') {
outputStr = func3_1(inputPtr);
*inputPtr = *outputStr;
outputStr = func3_2(inputPtr);
*inputPtr = *outputStr;
inputPtr = inputPtr + 1;
}
strCmpRes = strcmp(__s1,"\"_9~Jb0!=A`G!06qfc8\'_20uf6`2%7");
free(__s1);
return strCmpRes == 0;
}
char * func3_1(char *character)
{
char cVar1;
if (('@' < *character) && (*character < '[')) {
*character = *character + -0xd;
if (*character < 'A') {
cVar1 = '\x1a';
}
else {
cVar1 = '\0';
}
*character = cVar1 + *character;
}
if (('`' < *character) && (*character < '{')) {
*character = *character + -0xd;
if (*character < 'a') {
cVar1 = '\x1a';
}
else {
cVar1 = '\0';
}
*character = cVar1 + *character;
}
return character;
}
char * func3_2(char *character)
{
char cVar1;
if ((' ' < *character) && (*character != '\x7f')) {
*character = *character + -0x2f;
if (*character < '!') {
cVar1 = '^';
}
else {
cVar1 = '\0';
}
*character = cVar1 + *character;
}
return character;
}
Understanding
Initially, I had spent a huge amount of time trying to reverse the functions by coding a Python script to attempt to go backwards from the given string back to the flag.
However, I realise that it might not be an onto function, where every output can easily be mapped back to the original flag.
Hence, I decided to replicate the 2 functions in Python and brute force the flag using the 127 different characters in ASCII.
Solve.py
target = "\"_9~Jb0!=A`G!06qfc8\'_20uf6`2%7"
flag = ""
for c in target:
for i in range(1, 128):
tmp = i
# Function3_1
if tmp > ord('@') and tmp < ord('['):
tmp -= 0xd
if tmp < ord('A'):
tmp += 0x1a
if tmp > ord('`') and tmp < ord('{'):
tmp -= 0xd
if tmp < ord('a'):
tmp += 0x1a
# Function3_2
if tmp > ord(' ') and tmp != 0x7f:
tmp -= 0x2f
if tmp < ord('!'):
tmp += ord('^')
if (chr(tmp) == c):
flag += chr(i)
break
print(flag)
Flag
DawgCTF{D0uBl3_Cyc1iC_rO74tI0n_S7r1nGs}