Child Rev
Run strings
on childrev
, it shows an interesting message.
UPX is an open source executable packer, unpack it with upx
, now we can get on the real job.
Decompile the program in ghidra
, it takes user input and the four characters as parameters of XOR
function, if XOR return non-zero result, the input is correct.
undefined8 main(void)
{
undefined local_38 [40];
int local_10;
char local_c;
char local_b;
char local_a;
char local_9;
printf("ENTER THE FLAG : ");
__isoc99_scanf(&DAT_0049e182,local_38);
local_9 = 'G';
local_a = 'L';
local_b = 'U';
local_c = 'G';
local_10 = XOR(local_38,0x47,0x4c,0x55,0x47);
if (local_10 == 0) {
puts("USE GHIDRA CUTTER OR IDA , THEN IT WILL BE EASY\n");
}
else {
printf("YAY U MADE IT \n%c%c%c%c{%s}\n",(ulong)(uint)(int)local_9,(ulong)(uint)(int)local_a,
(ulong)(uint)(int)local_b,(ulong)(uint)(int)local_c,local_38);
}
return 0;
}
Take a look into XOR
function, it calls gen_key
to generate a key from the last four parameters, then xor
the key with the first parameter byte by byte, finally it check whether the result match array DAT_0049e060
.
ulong XOR(long param_1,char param_2,char param_3,char param_4,char param_5)
{
ulong key;
long j;
ulong *puVar1;
ulong *puVar2;
byte bVar3;
ulong local_248 [34];
ulong auStack312 [36];
int k;
uint ret;
int i;
bVar3 = 0;
key = gen_key((ulong)(uint)(int)param_2,(ulong)(uint)(int)param_3,(ulong)(uint)(int)param_4,
(ulong)(uint)(int)param_5);
i = 0;
while (i < 0x22) {
auStack312[i] = (long)*(char *)(param_1 + i) ^ key;
i = i + 1;
}
j = 0x22;
puVar1 = &DAT_0049e060;
puVar2 = local_248;
while (j != 0) {
j = j + -1;
*puVar2 = *puVar1;
puVar1 = puVar1 + (ulong)bVar3 * 0x1ffffffffffffffe + 1;
puVar2 = puVar2 + (ulong)bVar3 * 0x1ffffffffffffffe + 1;
}
ret = 0;
k = 0;
do {
if (0x21 < k) {
LAB_00401e3c:
return (ulong)ret;
}
if (auStack312[k] != local_248[k]) {
ret = 0;
goto LAB_00401e3c;
}
ret = 1;
k = k + 1;
} while( true );
}
The key is generated from “G”, “L”, “U”, “G”, so it’s constant, by debugging it with r2
we can find out the key is 0x00012f00
.
...
0x00401d70 0fbe8da8fdff. movsx ecx, byte [rbp - 0x258]
0x00401d77 0fbe95acfdff. movsx edx, byte [rbp - 0x254]
0x00401d7e 0fbeb5b0fdff. movsx esi, byte [rbp - 0x250]
0x00401d85 0fbe85b4fdff. movsx eax, byte [rbp - 0x24c]
0x00401d8c 89c7 mov edi, eax
0x00401d8e e81affffff call sym.gen_key
0x00401d93 488945e8 mov qword [rbp - 0x18], rax
...
Dump DAT_0049e060
block into dat
, convert it to int array.
dat = dat.split()
arr = []
for i in range(0, len(dat), 8):
arr.append(int(''.join(reversed(dat[i:i+8])), 16))
So we can xor
the arr
and key
to find out correct input.
key = 0x00012f00
flag = [0]*0x22
for i in range(len(flag)):
flag[i] = arr[i] ^ key
print(''.join(map(chr, flag)))
Enter the correct flag string, we get the actual flag in the output.