Hackvent 2019: Day 20
Challenge
HV19.20 i want to play a game
Introduction
Santa was spying you on Discord and saw that you want something weird and obscure to reverse?
your wish is my command.
Resource mirror: HV19-Day20-game.zip
Solution
We are given a binary and told it is something obscure we have to reverse. We download the binary and open it in IDA. After some digging around we realise the file has something to do with the PS4 and this is consistent with the hint in the zip file name too.
We dig around in IDA where we find a single main()
method. We see that we seem to read in a file called /mnt/usb0/PS4UPDATE.PUP
and then take the MD5 hash of this file and compare it to f86d4f9d2c049547bd61f942151ffb55
. After googling this hash we find the file in question is the PS4 5.05 firmware.
We decide to decompile the code to C and are presented with the following:
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rcx
__int64 v4; // rcx
__int64 v5; // r13
unsigned int v6; // eax
__int64 v7; // rcx
__int16 *v8; // r15
__int64 v9; // rcx
__int64 v10; // r12
__int64 v11; // rdx
__int64 i; // rax
__int64 v13; // r13
__int64 v14; // rcx
__int64 v15; // r12
__int64 j; // rax
__int64 v17; // rcx
__int64 v18; // rcx
__int64 v20; // [rsp+8h] [rbp-520h]
void (*v21)(void); // [rsp+10h] [rbp-518h]
void (*v22)(void); // [rsp+18h] [rbp-510h]
__int64 v23; // [rsp+27h] [rbp-501h]
char v24; // [rsp+30h] [rbp-4F8h]
__int16 v25; // [rsp+40h] [rbp-4E8h]
__int16 v26; // [rsp+42h] [rbp-4E6h]
int v27; // [rsp+44h] [rbp-4E4h]
char v28[32]; // [rsp+50h] [rbp-4D8h]
char v29[32]; // [rsp+70h] [rbp-4B8h]
refptr_initKernel(argc, argv, envp);
refptr_initLibc();
refptr_initNetwork();
(*(void (__fastcall **)(_QWORD, _QWORD, _QWORD, _QWORD))refptr_sceKernelLoadStartModule)(0i64, 0i64, 0i64, 0i64);
refptr_sceKernelDlsym(v3, &v21);
refptr_sceKernelDlsym(v4, &v22);
(*(void (**)(void))refptr_malloc)();
(*(void (**)(void))refptr_malloc)();
v21();
v22();
v5 = (*(__int64 (**)(void))refptr_fopen)();
(*(void (**)(void))refptr_malloc)();
refptr_MD5Init();
while ( 1 )
{
v6 = (*(__int64 (__fastcall **)(__int64, __int64))refptr_fread)(v5, 1024i64);
if ( !v6 )
break;
refptr_MD5Update(v7, v6);
}
v8 = (__int16 *)&v24;
refptr_MD5Final();
(*(void (**)(void))refptr_fclose)();
v10 = v20;
do
{
v11 = *(unsigned __int8 *)v8;
v8 = (__int16 *)((char *)v8 + 1);
v10 += 2i64;
(*(void (__fastcall **)(__int64, __int64))refptr_sprintf)(v9, v11);
}
while ( &v25 != v8 );
if ( !(*(unsigned int (**)(void))refptr_strcmp)() )
{
for ( i = 0i64; i != 26; ++i )
v28[i] = byte_300[i];
v13 = 4919i64;
v15 = (*(__int64 (__fastcall **)(_BYTE *))refptr_fopen)(byte_300);
do
{
(*(void (__fastcall **)(__int64, _QWORD))refptr_fseek)(v14, 0i64);
(*(void (__fastcall **)(__int64, __int64))refptr_fread)(v15, 1i64);
for ( j = 0i64; j != 26; ++j )
v28[j] ^= v29[j];
v13 += 4919i64;
}
while ( v13 != 24201480 );
(*(void (**)(void))refptr_fclose)();
strcpy((char *)&v23, "sendflag");
v25 = 528;
v27 = 16777343;
v26 = (*(__int64 (**)(void))refptr_sceNetHtons)();
(*(void (__fastcall **)(__int64, __int64))refptr_memset)(v17, 6i64);
(*(__int64 (__fastcall **)(_QWORD, __int64))refptr_sceNetSocket)(0i64, 1i64);
(*(void (__fastcall **)(__int64, __int64))refptr_sceNetConnect)(v18, 16i64);
(*(void (__fastcall **)(_QWORD, __int64))refptr_sceNetSend)(0i64, 26i64);
(*(void (**)(void))refptr_sceNetSocketClose)();
}
return 0;
}
The above decompilation is not perfect but we see the general structure of the program. First we initialise an array of 32 bytes with some data from byte_300 and store this as our flag data. Next we open our /mnt/usb0/PS4UPDATE.PUP
file. We initialise our file pointer value to 0x1337
and start looping, adding 0x1337
to our seek pointer each iteration. Finally, we read 26 bytes from the file and XOR this with the current flag data. At the end, we should our flag in our array.
We translate this to python code and get the following:
# Hackvent 2019 - Day 20
# Mo Beigi (https://mobeigi.com)
flag = bytearray(b'\xCE\x55\x95\x4E\x38\xC5\x89\xA5\x1B\x6F\x5E\x25\xD2\x1D\x2A\x2B\x5E\x7B\x39\x14\x8E\xD0\xF0\xF8\xF8\xA5\x00')
# Read PS4 firmware with MD5 f86d4f9d2c049547bd61f942151ffb55
f = open("PS4UPDATE.PUP", "rb")
offset = 0x1337
while offset != 0x1714908:
# Absolute seek to offset
f.seek(offset, 0)
read_bytes = f.read(26)
# xor flag with read bytes
for j in range(0, 26):
flag[j] ^= read_bytes[j]
offset += 0x1337
# Print flag
print(''.join(chr(i) for i in flag))
Running this gives us our flag!
Flag:
HV19{C0nsole_H0mebr3w_FTW}