Decompiling an unknown "service" to understand it's purpose, find a flaw and a possible exploit

Hello, probably some of you may have heard of NSO Group, https://www.nsogroup.com
That company made a sophisticated and state of art zero click exploit for iOS, used it for while to spy and eavesdrop on several thousand subscribers all-over the world, including government members, journalist and top-level businessman.

A friend of mine applied for a job while they were hiring reverse engineers and hackers.
They gave him this test to solve, it’s kind of hack the box challenge. I could provide the binary file to anybody interested to see it.

Interview Challenge

Service to exploit for the /flag:

  • host: aaa.bbb.ccc.ddd
  • port: 6854

Testing the Service

$ nc aaa.bbb.ccc.ddd 6854
GET /api/hottie/
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 74

{
        "ishot": false,
        "ad": "Buy Hottie, the hottest new bath accessory!"
}
1 Like

//----- (0000000000400144) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
__int64 __fastcall unhex(unsigned __int8 a1)
{
if ( a1 > 0x2Fu && a1 <= 0x39u )
return (unsigned __int8)(a1 - 48);
if ( a1 > 0x60u && a1 <= 0x66u )
return (unsigned __int8)(a1 - 87);
if ( a1 <= 0x40u || a1 > 0x46u )
return 0LL;
return (unsigned __int8)(a1 - 55);
}
// 400148: positive sp value 10 has been found

//----- (00000000004001D0) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
__int64 __fastcall url_decode(__int64 a1, __int64 a2)
{
char v3; // w19
unsigned int v4; // w0
char v7; // [xsp-9h] [xbp-9h]
unsigned int i; // [xsp-8h] [xbp-8h]
int v9; // [xsp-4h] [xbp-4h]

v9 = 0;
for ( i = 0; ; ++i )
{
v7 = *(_BYTE )(a2 + v9);
if ( !v7 )
break;
if ( v7 == 37 )
{
v3 = 16 * unhex(
(_BYTE )(a2 + v9 + 1LL));
v7 = v3 | unhex(
(_BYTE *)(a2 + v9 + 2LL));
v9 += 3;
}
else
{
++v9;
}
v4 = i;
*(_BYTE *)(a1 + (int)v4) = v7;
}
return i;
}
// 4001D4: positive sp value 40 has been found

//----- (00000000004002C4) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
__int64 __fastcall response(int a1, _BYTE *a2)
{
if ( a1 == 200 )
{
puts(“HTTP/1.1 200 OK\r”);
}
else if ( a1 == 401 )
{
puts(“HTTP/1.1 401 Unauthorized\r”);
}
strlen(a2);
return printf((__int64)“Content-Type: application/json\r\nContent-Length: %ld\r\n\r\n%s”);
}
// 4002C8: positive sp value 20 has been found

//----- (0000000000400338) ----------------------------------------------------
// bad sp value at call has been detected, the output may be wrong!
// positive sp value has been detected, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 *v4; // [xsp-470h] [xbp-470h] BYREF
unsigned __int8 v5[1024]; // [xsp-468h] [xbp-468h] BYREF
_QWORD v6[2]; // [xsp-68h] [xbp-68h] BYREF
int v7; // [xsp-54h] [xbp-54h]
unsigned __int64 v8; // [xsp-50h] [xbp-50h]
__int64 v9; // [xsp-48h] [xbp-48h]
unsigned __int8 *v10; // [xsp-40h] [xbp-40h]
unsigned __int8 *v11; // [xsp-38h] [xbp-38h]
unsigned __int8 *v12; // [xsp-30h] [xbp-30h]
unsigned __int8 *v13; // [xsp-28h] [xbp-28h]
unsigned int v14; // [xsp-1Ch] [xbp-1Ch]
const char *v15; // [xsp-18h] [xbp-18h]
unsigned __int8 *v16; // [xsp-10h] [xbp-10h]
unsigned __int8 *v17; // [xsp-8h] [xbp-8h]

setvbuf((__int64)&_stdout_FILE, 0LL, 2, 0LL);
setvbuf((__int64)&_stderr_FILE, 0LL, 2, 0LL);
v16 = “GET /api/hottie/”;
v15 = “Buy Hottie, the hottest new bath accessory!”;
v6[0] = 0LL;
v6[1] = 0LL;
memset((int8x16_t *)v5, 0, sizeof(v5));
v17 = “public”;
v14 = read(0, v5, (void *)0x3FF);
if ( v14 <= 8 || (unsigned int)strncmp(v5, v16, 16LL) )
return 0;
v13 = strchr(v5, 0xAu);
if ( v13 )
{
*v13-- = 0;
if ( *v13 == 13 )
*v13 = 0;
}
v13 = strstr(v5, " HTTP/“);
if ( v13 )
*v13 = 0;
v12 = strchr(v5, 0x3Fu);
if ( v12 )
{
*v12++ = 0;
if ( !(unsigned int)strncmp(v12, “token=”, 6LL) )
v17 = v12 + 6;
}
v11 = &v5[16];
v10 = strchr(&v5[16], 0x2Fu);
if ( v10 )
*v10 = 0;
v9 = 0LL;
v8 = strlen(v11);
if ( !(unsigned int)strcmp(v17, “enterprise”) )
{
if ( v8 > 0xC )
{
response(401, “{\n\t"error": "contact us for unlimited support"\n}”);
return 0;
}
}
else if ( !(unsigned int)strcmp(v17, “premium”) )
{
if ( v8 > 9 )
{
response(401, “{\n\t"error": "sign up for enterprise to get big support"\n}”);
return 0;
}
}
else
{
v17 = “public”;
if ( v8 > 6 )
{
response(401, “{\n\t"error": "sign up for premium or enterprise to get huge support"\n}”);
return 0;
}
}
v8 = (int)url_decode((__int64)v6, (__int64)v11);
if ( LOBYTE(v6[0]) == 45 && !(unsigned int)strcmp(v17, “public”) )
{
response(401, “{\n\t"error": "sign up for premium or enterprise to get not-positive number support"\n}”);
return 0;
}
else
{
v7 = *((unsigned __int8 *)v6 + v8 - 1) - 48;
v4 = 0LL;
if ( !(unsigned int)strcmp(v17, “public”) )
asprintf(&v4, (__int64)”{\n\t"ishot": %s,\n\t"ad": "%s"\n}\n");
else
asprintf(&v4, (__int64)“{\n\t"ishot": %s\n}\n”);
response(200, v4);
return 0;
}
}