/* sub_402A88 - HDCP TA (hdcp_full.bin), Navi31 PSP 13.0.0 * * Signature: sub_402A88(int ctx, char *msg, unsigned int len, int *out) * ctx = HDCP session slot (652 B, table @0x407000) * msg = attacker message (shm+0x29) * len = a3, attacker-chosen (5*N+25 on the reachable path) * out = status written back, surfaces at shm+0x1424 * * STACK FRAME (verified from encoded immediates, NOT from IDA's frame view): * v54 SP+0x100 268 bytes <- overflow destination (see note 1) * v56 SP+0x210 <- STACK CANARY = v54+272 * savedR4 <- v54+276 * savedLR <- v54+308 * * NOTE 1: IDA declares `_DWORD v54[58]` = 232 B. That is WRONG. The prologue * does sub_401188(v54, 0x10C) = memset 268 bytes. 268 is authoritative. * * NOTE 2: every bare `sub_401058();` below is a memcpy whose ARGUMENTS Hex-Rays * dropped. The important one is the third (see NOTE 3). */ int __fastcall sub_402A88(int a1, char *a2, unsigned int a3, int *a4) { int *v4; // r11 int result; // r0 int v10; // r8 int v11; // r10 int v12; // r9 unsigned int v13; // r0 bool v14; // zf int v15; // r0 unsigned int v16; // r0 int v17; // r1 int v18; // r8 int v19; // r7 __int64 v20; // r2 char *v21; // r0 int v22; // r1 unsigned int v23; // r8 int v24; // r7 unsigned int v25; // r1 int v26; // r0 int v27; // r1 int v28; // r2 int v29; // r1 char *v30; // r1 int v31; // r3 int v32; // r3 int v33; // r7 unsigned int i; // r7 unsigned __int8 *v35; // r1 int v36; // r0 int v37; // r2 int v38; // r3 int v39; // r1 int v40; // r0 int v41; // r0 char v42; // [sp+4h] [bp-210h] int v43; // [sp+8h] [bp-20Ch] int v44; // [sp+Ch] [bp-208h] int v45; // [sp+10h] [bp-204h] int v46; // [sp+14h] [bp-200h] int v47; // [sp+18h] [bp-1FCh] BYREF unsigned __int16 v48; // [sp+1Ch] [bp-1F8h] BYREF int v49; // [sp+20h] [bp-1F4h] BYREF unsigned __int8 v50; // [sp+24h] [bp-1F0h] _BYTE v51[3]; // [sp+25h] [bp-1EFh] BYREF _DWORD v52[8]; // [sp+C0h] [bp-154h] BYREF int v53[8]; // [sp+E0h] [bp-134h] BYREF _DWORD v54[58]; // [sp+100h] [bp-114h] BYREF _DWORD v55[10]; // [sp+1E8h] [bp-2Ch] BYREF int v56; // [sp+210h] [bp-4h] v4 = off_40394C; v56 = *off_40394C; v48 = 0; sub_401188(v54, 0x10Cu); result = 1; if ( a1 == 0 || a2 == nullptr || a4 == nullptr ) goto LABEL_33; *a4 = 100; if ( *(_BYTE *)(a1 + 589) != 0 ) { if ( sub_4045A0(*(_DWORD *)(a1 + 4)) != 0 ) { result = 20; goto LABEL_33; } *(_BYTE *)(a1 + 589) = 0; } if ( *(_DWORD *)(a1 + 16) != 6 ) { if ( a3 == 176 ) { v42 = *a2; v12 = (unsigned __int8)a2[1]; sub_40182C(a2, &v48, 2); v13 = v48; v10 = (v48 & 8) != 0; *(_DWORD *)(a1 + 52) = v10; *(_DWORD *)(a1 + 68) = (v13 & 2) != 0; *(_DWORD *)(a1 + 64) = v13 & 1; *(_DWORD *)(a1 + 60) = (v13 >> 9) & 7; *(_BYTE *)(a1 + 56) = (v13 >> 4) & 0x1F; v11 = (v13 & 4) != 0; *(_DWORD *)(a1 + 48) = v11; v44 = (unsigned __int8)a2[2]; v46 = (unsigned __int8)a2[3]; v45 = (unsigned __int8)a2[4]; v43 = 16; sub_401058(); sub_401058(); a3 = v12 << 8; goto LABEL_17; } goto LABEL_27; } if ( *(_DWORD *)(a1 + 36) != 20 ) { if ( a3 <= 1 ) goto LABEL_27; v10 = (unsigned __int8)a2[1]; *(_DWORD *)(a1 + 52) = v10; v11 = (unsigned __int8)*a2; *(_DWORD *)(a1 + 48) = v11; *(_BYTE *)(a1 + 56) = a2[2]; *(_DWORD *)(a1 + 60) = (unsigned __int8)a2[3]; *(_DWORD *)(a1 + 64) = (unsigned __int8)a2[5]; *(_DWORD *)(a1 + 68) = (unsigned __int8)a2[4]; if ( a2[1] != 0 || *a2 != 0 ) { LABEL_30: *(_DWORD *)(a1 + 24) = 7; v15 = 107; goto LABEL_31; } if ( 5 * (unsigned __int8)a2[2] + 25 == a3 ) { v44 = (unsigned __int8)a2[6]; v46 = (unsigned __int8)a2[7]; v45 = (unsigned __int8)a2[8]; v43 = 16; sub_401058(); sub_401058(); a3 = 0; v42 = 0; goto LABEL_17; } LABEL_27: *(_DWORD *)(a1 + 24) = 7; v15 = 109; goto LABEL_31; } if ( a3 <= 1 ) goto LABEL_27; v10 = (unsigned __int8)a2[1]; *(_DWORD *)(a1 + 52) = v10; v11 = (unsigned __int8)*a2; *(_DWORD *)(a1 + 48) = v11; *(_BYTE *)(a1 + 56) = a2[2]; *(_DWORD *)(a1 + 60) = (unsigned __int8)a2[3]; if ( a2[1] != 0 || *a2 != 0 ) goto LABEL_30; if ( 5 * (unsigned __int8)a2[2] + 36 != a3 ) goto LABEL_27; a3 = 0; v43 = 32; *(_DWORD *)(a1 + 72) = 0; sub_401058(); sub_401058(); v42 = 0; v44 = 0; v46 = 0; v45 = 0; LABEL_17: v14 = v10 == 0; if ( v10 == 0 ) v14 = v11 == 0; if ( !v14 ) goto LABEL_30; if ( *(_DWORD *)(a1 + 64) == 0 && *(_DWORD *)(a1 + 68) == 0 ) goto LABEL_35; if ( (unsigned int)(*(_DWORD *)(a1 + 28) - 1) > 1 ) goto LABEL_35; *(_DWORD *)(a1 + 32) = 0; if ( sub_404666(*(_DWORD *)(a1 + 4), 1) == 0 ) goto LABEL_35; LABEL_25: result = 17; LABEL_33: while ( *v4 != v56 ) { ((void (__fastcall *)(int, int))loc_404338)(result, *v4 - v56); LABEL_35: v16 = v44 | (v46 << 8) | (v45 << 16); v17 = *(_DWORD *)(a1 + 72); if ( v16 != 0 && v17 == 0 || v17 == 1 && v16 < *(_DWORD *)(a1 + 596) ) { *(_DWORD *)(a1 + 24) = 7; v15 = 108; LABEL_31: *a4 = v15; LABEL_32: result = 0; } else { v18 = *(unsigned __int8 *)(a1 + 56); *(_DWORD *)(a1 + 596) = v16; *(_DWORD *)(a1 + 72) = 1; v19 = 5 * v18; sub_401058(); if ( *(_DWORD *)(a1 + 16) == 6 ) { v20 = *(_QWORD *)(a1 + 48); *((_BYTE *)v54 + 5 * v18) = *(_DWORD *)(a1 + 60); v21 = (char *)v54 + v19; v22 = *(_DWORD *)(a1 + 36); v21[2] = BYTE4(v20); v21[1] = v18; v21[3] = v20; if ( v22 == 20 ) { v23 = v43; a3 = (unsigned int)v54; v24 = v19 + 4; goto LABEL_48; } v28 = *(_DWORD *)(a1 + 68); a3 = (unsigned int)v54; v21[5] = *(_QWORD *)(a1 + 64); v26 = 9; *((_BYTE *)&v54[1] + v19) = v28; v27 = 6; v23 = v43; } else { v23 = v43; v25 = a3 >> 8; *((_BYTE *)v54 + v19) = v42 | a3; a3 = (unsigned int)v54; *((_BYTE *)v54 + v19 + 1) = v25; v26 = 5; v27 = 2; } v29 = v27 + v19; v24 = v19 + v26; *((_BYTE *)v54 + v29) = v44; v30 = (char *)v54 + v29; v30[2] = v45; v30[1] = v46; LABEL_48: sub_401058(); v55[8] = v23; sub_4010E0(v55, v53, v23, v31); if ( ((int (__fastcall *)(_DWORD *, int, _DWORD *, int *, int))loc_403FF4)(v54, v24, v52, &v47, 32) != 0 ) { *(_DWORD *)(a1 + 24) = 7; *a4 = 106; sub_401188(v52, 0x20u); sub_401188(v54, 0x10Cu); goto LABEL_32; } if ( v47 == 32 ) { v32 = v52[5]; a3 = v52[6]; v33 = v52[7]; *(_DWORD *)(a1 + 600) = v52[4]; *(_DWORD *)(a1 + 604) = v32; *(_DWORD *)(a1 + 608) = a3; *(_DWORD *)(a1 + 612) = v33; } sub_401188(v52, 0x20u); sub_401188(v54, 0x10Cu); for ( i = 0; i < *(unsigned __int8 *)(a1 + 56); ++i ) { v35 = (unsigned __int8 *)(a1 + 85 + 5 * i); v36 = *v35; a3 = v35[3]; v37 = v35[1]; v38 = v35[2]; v50 = v35[4]; v49 = v36 | (v37 << 8) | ((v38 | (a3 << 8)) << 16); if ( sub_40471A(&v49) != 0 ) goto LABEL_60; } if ( sub_404646(a1 + 616) != 0 ) goto LABEL_25; sub_401144(v51, 155); v39 = *(unsigned __int8 *)(a1 + 79); v50 = *(_BYTE *)(a1 + 83); v40 = *(_DWORD *)(a1 + 4); v49 = v39 | (*(unsigned __int8 *)(a1 + 80) << 8) | ((*(unsigned __int8 *)(a1 + 81) | (*(unsigned __int8 *)(a1 + 82) << 8)) << 16); v41 = sub_404574(v40, &v49, 1, a1 + 616); if ( v41 != 0 || (a3 = *(unsigned __int8 *)(a1 + 56), sub_401058(), (v41 = sub_404574(*(_DWORD *)(a1 + 4), &v49, a3, a1 + 616)) != 0) ) { if ( v41 != 23 ) goto LABEL_25; LABEL_60: *(_DWORD *)(a1 + 24) = 7; *a4 = 112; goto LABEL_25; } result = 0; *a4 = 0; } } return result; }