I haven’t solved this during the contest, but I want to share my solution.
The zip file contained a binary file named brcmfmac43430-sdio.bin; which is a Broadcom 43430 SDIO firmware.
After some time poking around using ghidra I found a base64 encoded string Um9zZXMgYXJlIHJlZCwgVmlvbGV0cyBhcmUgYmx1ZSwgRHJTY2hvdHRreSBsb3ZlcyBob29raW5nIGlvY3Rscywgd2h5IHNob3VsZG4ndCB5b3U/
which decodes to Roses are red, Violets are blue, DrSchottky loves hooking ioctls, why shouldn't you?
.
Searching for references to this string shows that it is only referenced in one function.
undefined4 FUN_00058dd8(undefined4 param_1,int param_2,undefined4 param_3,undefined4 param_4,undefined4 param_5 ) { undefined4 uVar1; byte *pbVar2; byte *pbVar3; byte bStack57; undefined4 local_38; undefined4 uStack52; undefined4 uStack48; undefined4 uStack44; undefined4 local_28; undefined4 auStack36 [2]; FUN_00058d9c(param_3,param_4); local_38 = *(undefined4 *)PTR_DAT_00058e84; uStack52 = *(undefined4 *)(PTR_DAT_00058e84 + 4); uStack48 = *(undefined4 *)(PTR_DAT_00058e84 + 8); uStack44 = *(undefined4 *)(PTR_DAT_00058e84 + 0xc); local_28 = *(undefined4 *)(PTR_DAT_00058e84 + 0x10); auStack36[0] = *(undefined4 *)(PTR_DAT_00058e84 + 0x14); if (param_2 == 0xcafe) { FUN_00803cd4(param_3,PTR_s_Um9zZXMgYXJlIHJlZCwgVmlvbGV0cyBh_00058e90,param_4); return 0; } if (param_2 != 0xd00d) { if (param_2 != 0x1337) { uVar1 = FUN_0081a2d4(param_1,param_2,param_3,param_4,param_5); return uVar1; } pbVar3 = &bStack57; pbVar2 = DAT_00058e88; do { pbVar3 = pbVar3 + 1; pbVar2 = pbVar2 + 1; *pbVar3 = *pbVar2 ^ *pbVar3; } while (pbVar3 != (byte *)((int)auStack36 + 2)); FUN_00803cd4(param_3,&local_38,param_4); return 0; } FUN_00002390(PTR_DAT_00058e8c,0x800000,0x17); return 0; }
This function seemed like the right place because it contains a basic xor cipher. The question is: what data is being xored? This took me far too long to find out.
One part is directly mentioned: pbVar3 = &bStack57;
Which references 0x09, 0xbc, 0x31, 0x3a, 0x68, 0x1a, 0xab, 0x72, 0x47, 0x86, 0x7e, 0xe6, 0x4a, 0x1d, 0x6f, 0x04, 0x2e, 0x74, 0x50, 0x0d, 0x78, 0x06, 0x3e
.
The other part is not in the binary itself, but in the rom of the firmware. The call at the end FUN_00002390(PTR_DAT_00058e8c,0x800000,0x17);
copies 0x17 byte of data into a local variable from address 0x800000 – which is where the rom is hooked. The rom file can be found on github. Loading the file into ghidra got me the other part: 0x41, 0xEA, 0x00, 0x03, 0x13, 0x43, 0x9B, 0x07, 0x30, 0xB5, 0x10, 0xD1, 0x0C, 0x68, 0x03, 0x68, 0x63, 0x40, 0x13, 0x60, 0x4C, 0x68, 0x43
. I wrote the following small python script to do the xoring and extracted the flag:
flag = [0x09, 0xbc, 0x31, 0x3a, 0x68, 0x1a, 0xab, 0x72, 0x47, 0x86, 0x7e, 0xe6, 0x4a, 0x1d, 0x6f, 0x04, 0x2e, 0x74, 0x50, 0x0d, 0x78, 0x06, 0x3e] key = [0x41, 0xEA, 0x00, 0x03, 0x13, 0x43, 0x9B, 0x07, 0x30, 0xB5, 0x10, 0xD1, 0x0C, 0x68, 0x03, 0x68, 0x63, 0x40, 0x13, 0x60, 0x4C, 0x68, 0x43] for i in range(len(key)): x = key[i] ^ flag[i] print(chr(x), end = "")
The flag is HV19{Y0uw3n7FullM4Cm4n}.