Hackvent 2019: Day 20

Hackvent 2019160

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 dataAt 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}

Leave a comment

(required)(will not be published)(required)

Comments

There are no comments yet. Be the first to add one!