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_keyto 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.