Skip to main content
added 171 characters in body
Source Link
user7290573
  • 362
  • 2
  • 14

Update 2: I've created a GitHub repository with my progress so far, for anyone who's willing to take a look.

Update 1: After digging around, I've managed to find a copy of the firmware with the symbols included (available here: https://www.mediafire.com/file/a0u7k2m87aj1jp6/Files.zip/file) and I'm pretty sure I've located the correct function for decompressing the files: cpr_tclDecompressAlgorithm::bDecompressData.

Update: After digging around, I've managed to find a copy of the firmware with the symbols included (available here: https://www.mediafire.com/file/a0u7k2m87aj1jp6/Files.zip/file) and I'm pretty sure I've located the correct function for decompressing the files: cpr_tclDecompressAlgorithm::bDecompressData.

Update 2: I've created a GitHub repository with my progress so far, for anyone who's willing to take a look.

Update 1: After digging around, I've managed to find a copy of the firmware with the symbols included (available here: https://www.mediafire.com/file/a0u7k2m87aj1jp6/Files.zip/file) and I'm pretty sure I've located the correct function for decompressing the files: cpr_tclDecompressAlgorithm::bDecompressData.

added 8245 characters in body
Source Link
user7290573
  • 362
  • 2
  • 14

As you can see, several standard PNG chunk names are present (sRGB, bKGD, IDAT, etc.) however the data between them appears to be scrambledcompressed/encrypted.

Some otherMy observations so far:

  • bytes 0x14-17 seem to be a DWORD indicating the custom header size (0x1C or 28 bytes)
  • bytes 0x1C-1D seem to be a WORD indicating the size ofof the data between themselves and where the actual PNG header begins (0x4B00 or 75 bytes, including the 2 size bytes) - this unknown data could wellmight be the chunkcompressed data table/dictionary
  • files are aligned to 4 byte blocks with 0x00
  • of the 2,196 compressed PNG files, exactly half have the same IHDR data: F0 E0 08 02 B2 E1 7C 5E 00 01; the other half have 01 90 88 08 02 E0 58 21 6D
  • similarly, half of the files' compressed data/dictionaries begin with the same 22 bytes: FC 06 31 46 85 53 68 85 84 F9 95 6E 40 80 55 E8 C5 18 19 DE 4A F8; the other half begin with FC 06 35 54 38 25 56 C8 1F 50 E9 06 04 58 85 5E 8C 91 E1 AD 84 - note how every file begins with FC 03 3x xx

Update: After digging around, I've managed to find a copy of the firmware with the symbols included (available here: https://www.mediafire.com/file/a0u7k2m87aj1jp6/Files.zip/file) and I'm pretty sure I've located the correct function for decompressing the files: cpr_tclDecompressAlgorithm::bDecompressData.

Unfortunately, I'm not able to make a great deal of sense of it, but what I can see from the symbols is that:

  • a couple of custom structs are used in the decompression method, cpr_tclCodeTable and cpr_tclCodeTableEntry
  • the structs are then used with methods called cpr_tclCodeTable::iu32SearchIndexOfCode and cpr_tclCodeTable::corfoGetCodeEntry
  • decompression begins by calling cpr_tclDecompressAlgorithm::u32GetNextBits to read 32 bits / 4 bytes
  • the return value from u32GetNextBits is used with & 3 and right shifted 2 bits, which indicates the first two bits are used as some scrambled formkind of flag

HasI will post IDA's pseudocode of the function below, but I'm not expecting anyone encountered this kindto spend a great deal of PNG before?time on this - I just wondered if anyone can recognise what's happening here, e.g. Huffman, LZSS, etc.

int __fastcall cpr_tclDecompressAlgorithm::bDecompressData(int a1, int a2, int a3, size_t a4, unsigned int a5, int a6) { int v7; // r8 unsigned int v10; // r5 int v11; // r9 void *v12; // r0 unsigned int v13; // r8 unsigned int v14; // r0 const cpr_tclCodeTable *CodeTable; // r11 unsigned int v16; // r6 unsigned int v17; // r7 unsigned int v18; // r0 int v19; // r0 int v20; // r2 int v21; // r3 int v22; // r5 int v23; // r0 int v24; // r7 unsigned int v25; // r1 int v26; // r3 _BYTE *v27; // r0 size_t v28; // r6 __int16 v29; // r12 int v30; // r2 int v31; // r5 int v32; // r0 unsigned int v33; // r10 int v34; // r3 _BYTE *v35; // r1 int v36; // r0 unsigned int v37; // r12 int v38; // r3 void *v39; // r0 size_t v40; // r5 int v41; // r2 int result; // r0 int v43; // r3 int v44; // r2 _BYTE *v45; // r2 int v46; // r0 int v47; // r3 _BOOL4 v48; // r3 int v49; // r0 *(_DWORD *)(a1 + 16) = a4; v7 = a2 & 3; *(_DWORD *)(a1 + 12) = a3; *(_DWORD *)(a1 + 4) = a2; *(_DWORD *)(a1 + 8) = a2; if ( (a2 & 3) != 0 ) { v49 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr_decompression.cpp"); trc_tclGlobalTrace::vTraceLevel1(21504, 332, v49, "CPR read access to unaligned adress 0x%x", a2); return 0; } cpr_tclDecompressAlgorithm::vInterpreteHeader((cpr_tclDecompressAlgorithm *)a1, a5); v10 = a5 - *(_DWORD *)(a1 + 48); if ( a4 < a5 ) { if ( a4 <= v10 ) { *(_DWORD *)(a1 + 48) = v7; v10 = a4; v11 = 1; goto LABEL_7; } *(_DWORD *)(a1 + 48) = a4 - v10; } v11 = v7; LABEL_7: v12 = *(void **)(a1 + 12); v13 = (unsigned int)v12 + v10; if ( !v10 ) goto LABEL_34; if ( a6 == 3 ) { v14 = cpr_tclDecompressAlgorithm::u32GetNextBits((cpr_tclDecompressAlgorithm *)a1, 0x20u); CodeTable = (const cpr_tclCodeTable *)(*(_DWORD *)a1 + 44 * (v14 & 3)); v16 = v14 >> 2; v17 = 2; cpr_tclDecompressAlgorithm::vInit((cpr_tclDecompressAlgorithm *)a1, CodeTable); while ( 1 ) { while ( 1 ) { if ( *(_DWORD *)(a1 + 12) >= v13 ) goto LABEL_34; v18 = cpr_tclCodeTable::iu32SearchIndexOfCode(CodeTable, v16); v19 = cpr_tclCodeTable::corfoGetCodeEntry(CodeTable, v18); v20 = *(_DWORD *)(v19 + 12); v21 = *(unsigned __int8 *)(v19 + 16); v22 = v19; v17 += v21; v16 >>= v21; if ( v20 != 3 ) break; v23 = cpr_tclDecompressAlgorithm::u32GetNextBits((cpr_tclDecompressAlgorithm *)a1, v17); v24 = *(unsigned __int8 *)(v22 + 17); v25 = v23 | v16; v26 = (v23 | v16) & ~(-1 << v24); v27 = *(_BYTE **)(a1 + 12); v28 = (unsigned __int16)(v26 + *(_WORD *)(v22 + 2)); v29 = *(_WORD *)(v22 + 6); v30 = *(_DWORD *)(a1 + 44); v31 = *(unsigned __int8 *)(v22 + 18); if ( v13 < (unsigned int)&v27[v28] ) { if ( v11 != 1 ) { v32 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr" "_decompression.cpp"); trc_tclGlobalTrace::vTraceLevel1( 21504, 253, v32, "CPR Overwrite Copy n=%d wpos=0x%x epos=0x%x", v28, *(_DWORD *)(a1 + 12), v13); LABEL_24: result = 0; goto LABEL_35; } v28 = (unsigned __int16)(v13 - (_WORD)v27); } v33 = v25 >> v24; v34 = -(unsigned __int16)(v29 + (((v25 >> v24) & ~(-1 << v31)) << v30)); v35 = &v27[-(unsigned __int16)(v29 + (((v25 >> v24) & ~(-1 << v31)) << v30))]; if ( v28 == 2 ) { *v27 = v27[v34]; *(_BYTE *)(*(_DWORD *)(a1 + 12) + 1) = v35[1]; } else { memcpy(v27, v35, v28); } v17 = v31 + v24; *(_DWORD *)(a1 + 12) += v28; v16 = v33 >> v31; } if ( v20 == 2 ) { v36 = cpr_tclDecompressAlgorithm::u32GetNextBits((cpr_tclDecompressAlgorithm *)a1, v17); v17 = *(unsigned __int8 *)(v22 + 17); v37 = v36 | v16; v38 = (v36 | v16) & ~(-1 << v17); v39 = *(void **)(a1 + 12); v40 = (unsigned __int16)(v38 + *(_WORD *)(v22 + 2)); if ( v13 < (unsigned int)v39 + v40 ) { if ( v11 != 1 ) { v41 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr" "_decompression.cpp"); trc_tclGlobalTrace::vTraceLevel1( 21504, 291, v41, "CPR Overwrite Lit n=%d wpos=0x%x epos=0x%x", v40, *(_DWORD *)(a1 + 12), v13); goto LABEL_24; } v40 = (unsigned __int16)(v13 - (_WORD)v39); } v16 = v37 >> v17; memcpy(v39, *(const void **)(a1 + 8), v40); v43 = *(_DWORD *)(a1 + 12) + v40; v44 = *(_DWORD *)(a1 + 8) + v40; } else { v45 = *(_BYTE **)(a1 + 12); if ( (_BYTE *)v13 == v45 ) { v46 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr_d" "ecompression.cpp"); trc_tclGlobalTrace::vTraceLevel1( 21504, 306, v46, "CPR Overwrite Lit1 n=1 wpos=0x%x epos=0x%x", *(_DWORD *)(a1 + 12), v13); goto LABEL_24; } *v45 = **(_BYTE **)(a1 + 8); v43 = *(_DWORD *)(a1 + 12) + 1; v44 = *(_DWORD *)(a1 + 8) + 1; } *(_DWORD *)(a1 + 12) = v43; *(_DWORD *)(a1 + 8) = v44; } } if ( a6 == 1 ) { memcpy(v12, *(const void **)(a1 + 4), v10); result = 1; *(_DWORD *)(a1 + 12) += v10; } else { LABEL_34: result = 1; } LABEL_35: v47 = *(_DWORD *)(a1 + 48); v48 = v47 != 0; if ( result != 1 ) v48 = 0; if ( v48 ) { memset(*(void **)(a1 + 12), 0, *(_DWORD *)(a1 + 48)); result = 1; } return result; } 

As you can see, several standard PNG chunk names are present (sRGB, bKGD, IDAT, etc.) however the data between them appears to be scrambled.

Some other observations:

  • bytes 0x14-17 seem to be a DWORD indicating the custom header size (0x1C or 28 bytes)
  • bytes 0x1C-1D seem to be a WORD indicating the size of the data between themselves and where the actual PNG header begins (0x4B00 or 75 bytes, including the 2 size bytes) - this unknown data could well be the chunk data in some scrambled form

Has anyone encountered this kind of PNG before?

As you can see, several standard PNG chunk names are present (sRGB, bKGD, IDAT, etc.) however the data between them appears to be compressed/encrypted.

My observations so far:

  • bytes 0x14-17 seem to be a DWORD indicating the custom header size (0x1C or 28 bytes)
  • bytes 0x1C-1D seem to be a WORD indicating the size of the data between themselves and where the actual PNG header begins (0x4B00 or 75 bytes, including the 2 size bytes) - this might be the compressed data table/dictionary
  • files are aligned to 4 byte blocks with 0x00
  • of the 2,196 compressed PNG files, exactly half have the same IHDR data: F0 E0 08 02 B2 E1 7C 5E 00 01; the other half have 01 90 88 08 02 E0 58 21 6D
  • similarly, half of the files' compressed data/dictionaries begin with the same 22 bytes: FC 06 31 46 85 53 68 85 84 F9 95 6E 40 80 55 E8 C5 18 19 DE 4A F8; the other half begin with FC 06 35 54 38 25 56 C8 1F 50 E9 06 04 58 85 5E 8C 91 E1 AD 84 - note how every file begins with FC 03 3x xx

Update: After digging around, I've managed to find a copy of the firmware with the symbols included (available here: https://www.mediafire.com/file/a0u7k2m87aj1jp6/Files.zip/file) and I'm pretty sure I've located the correct function for decompressing the files: cpr_tclDecompressAlgorithm::bDecompressData.

Unfortunately, I'm not able to make a great deal of sense of it, but what I can see from the symbols is that:

  • a couple of custom structs are used in the decompression method, cpr_tclCodeTable and cpr_tclCodeTableEntry
  • the structs are then used with methods called cpr_tclCodeTable::iu32SearchIndexOfCode and cpr_tclCodeTable::corfoGetCodeEntry
  • decompression begins by calling cpr_tclDecompressAlgorithm::u32GetNextBits to read 32 bits / 4 bytes
  • the return value from u32GetNextBits is used with & 3 and right shifted 2 bits, which indicates the first two bits are used as some kind of flag

I will post IDA's pseudocode of the function below, but I'm not expecting anyone to spend a great deal of time on this - I just wondered if anyone can recognise what's happening here, e.g. Huffman, LZSS, etc.

int __fastcall cpr_tclDecompressAlgorithm::bDecompressData(int a1, int a2, int a3, size_t a4, unsigned int a5, int a6) { int v7; // r8 unsigned int v10; // r5 int v11; // r9 void *v12; // r0 unsigned int v13; // r8 unsigned int v14; // r0 const cpr_tclCodeTable *CodeTable; // r11 unsigned int v16; // r6 unsigned int v17; // r7 unsigned int v18; // r0 int v19; // r0 int v20; // r2 int v21; // r3 int v22; // r5 int v23; // r0 int v24; // r7 unsigned int v25; // r1 int v26; // r3 _BYTE *v27; // r0 size_t v28; // r6 __int16 v29; // r12 int v30; // r2 int v31; // r5 int v32; // r0 unsigned int v33; // r10 int v34; // r3 _BYTE *v35; // r1 int v36; // r0 unsigned int v37; // r12 int v38; // r3 void *v39; // r0 size_t v40; // r5 int v41; // r2 int result; // r0 int v43; // r3 int v44; // r2 _BYTE *v45; // r2 int v46; // r0 int v47; // r3 _BOOL4 v48; // r3 int v49; // r0 *(_DWORD *)(a1 + 16) = a4; v7 = a2 & 3; *(_DWORD *)(a1 + 12) = a3; *(_DWORD *)(a1 + 4) = a2; *(_DWORD *)(a1 + 8) = a2; if ( (a2 & 3) != 0 ) { v49 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr_decompression.cpp"); trc_tclGlobalTrace::vTraceLevel1(21504, 332, v49, "CPR read access to unaligned adress 0x%x", a2); return 0; } cpr_tclDecompressAlgorithm::vInterpreteHeader((cpr_tclDecompressAlgorithm *)a1, a5); v10 = a5 - *(_DWORD *)(a1 + 48); if ( a4 < a5 ) { if ( a4 <= v10 ) { *(_DWORD *)(a1 + 48) = v7; v10 = a4; v11 = 1; goto LABEL_7; } *(_DWORD *)(a1 + 48) = a4 - v10; } v11 = v7; LABEL_7: v12 = *(void **)(a1 + 12); v13 = (unsigned int)v12 + v10; if ( !v10 ) goto LABEL_34; if ( a6 == 3 ) { v14 = cpr_tclDecompressAlgorithm::u32GetNextBits((cpr_tclDecompressAlgorithm *)a1, 0x20u); CodeTable = (const cpr_tclCodeTable *)(*(_DWORD *)a1 + 44 * (v14 & 3)); v16 = v14 >> 2; v17 = 2; cpr_tclDecompressAlgorithm::vInit((cpr_tclDecompressAlgorithm *)a1, CodeTable); while ( 1 ) { while ( 1 ) { if ( *(_DWORD *)(a1 + 12) >= v13 ) goto LABEL_34; v18 = cpr_tclCodeTable::iu32SearchIndexOfCode(CodeTable, v16); v19 = cpr_tclCodeTable::corfoGetCodeEntry(CodeTable, v18); v20 = *(_DWORD *)(v19 + 12); v21 = *(unsigned __int8 *)(v19 + 16); v22 = v19; v17 += v21; v16 >>= v21; if ( v20 != 3 ) break; v23 = cpr_tclDecompressAlgorithm::u32GetNextBits((cpr_tclDecompressAlgorithm *)a1, v17); v24 = *(unsigned __int8 *)(v22 + 17); v25 = v23 | v16; v26 = (v23 | v16) & ~(-1 << v24); v27 = *(_BYTE **)(a1 + 12); v28 = (unsigned __int16)(v26 + *(_WORD *)(v22 + 2)); v29 = *(_WORD *)(v22 + 6); v30 = *(_DWORD *)(a1 + 44); v31 = *(unsigned __int8 *)(v22 + 18); if ( v13 < (unsigned int)&v27[v28] ) { if ( v11 != 1 ) { v32 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr" "_decompression.cpp"); trc_tclGlobalTrace::vTraceLevel1( 21504, 253, v32, "CPR Overwrite Copy n=%d wpos=0x%x epos=0x%x", v28, *(_DWORD *)(a1 + 12), v13); LABEL_24: result = 0; goto LABEL_35; } v28 = (unsigned __int16)(v13 - (_WORD)v27); } v33 = v25 >> v24; v34 = -(unsigned __int16)(v29 + (((v25 >> v24) & ~(-1 << v31)) << v30)); v35 = &v27[-(unsigned __int16)(v29 + (((v25 >> v24) & ~(-1 << v31)) << v30))]; if ( v28 == 2 ) { *v27 = v27[v34]; *(_BYTE *)(*(_DWORD *)(a1 + 12) + 1) = v35[1]; } else { memcpy(v27, v35, v28); } v17 = v31 + v24; *(_DWORD *)(a1 + 12) += v28; v16 = v33 >> v31; } if ( v20 == 2 ) { v36 = cpr_tclDecompressAlgorithm::u32GetNextBits((cpr_tclDecompressAlgorithm *)a1, v17); v17 = *(unsigned __int8 *)(v22 + 17); v37 = v36 | v16; v38 = (v36 | v16) & ~(-1 << v17); v39 = *(void **)(a1 + 12); v40 = (unsigned __int16)(v38 + *(_WORD *)(v22 + 2)); if ( v13 < (unsigned int)v39 + v40 ) { if ( v11 != 1 ) { v41 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr" "_decompression.cpp"); trc_tclGlobalTrace::vTraceLevel1( 21504, 291, v41, "CPR Overwrite Lit n=%d wpos=0x%x epos=0x%x", v40, *(_DWORD *)(a1 + 12), v13); goto LABEL_24; } v40 = (unsigned __int16)(v13 - (_WORD)v39); } v16 = v37 >> v17; memcpy(v39, *(const void **)(a1 + 8), v40); v43 = *(_DWORD *)(a1 + 12) + v40; v44 = *(_DWORD *)(a1 + 8) + v40; } else { v45 = *(_BYTE **)(a1 + 12); if ( (_BYTE *)v13 == v45 ) { v46 = trc_szGetFileName( "/opt/bosch/DI_SWNAVI_13.2C5P10/di_swnavi/components/dapi/devicemanager/devicehandler/compression/cpr_d" "ecompression.cpp"); trc_tclGlobalTrace::vTraceLevel1( 21504, 306, v46, "CPR Overwrite Lit1 n=1 wpos=0x%x epos=0x%x", *(_DWORD *)(a1 + 12), v13); goto LABEL_24; } *v45 = **(_BYTE **)(a1 + 8); v43 = *(_DWORD *)(a1 + 12) + 1; v44 = *(_DWORD *)(a1 + 8) + 1; } *(_DWORD *)(a1 + 12) = v43; *(_DWORD *)(a1 + 8) = v44; } } if ( a6 == 1 ) { memcpy(v12, *(const void **)(a1 + 4), v10); result = 1; *(_DWORD *)(a1 + 12) += v10; } else { LABEL_34: result = 1; } LABEL_35: v47 = *(_DWORD *)(a1 + 48); v48 = v47 != 0; if ( result != 1 ) v48 = 0; if ( v48 ) { memset(*(void **)(a1 + 12), 0, *(_DWORD *)(a1 + 48)); result = 1; } return result; } 
Notice removed Draw attention by CommunityBot
Bounty Ended with no winning answer by CommunityBot
Notice added Draw attention by user7290573
Bounty Started worth 100 reputation by user7290573
Source Link
user7290573
  • 362
  • 2
  • 14

Has anyone encountered PNGs where the chunk data is encrypted/compressed?

I've come across some files which are used in a car's satellite navigation system. Looking at the files in a hex editor shows the ‰PNG signature, but the chunks do not follow the format spec - for example:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 05 00 10 00 43 50 52 4E 41 56 5F 32 36 02 00 00 ....CPRNAV_26... 00000010 03 00 01 00 1C 00 00 00 08 01 00 00 4B 00 CA 3D ............K.Ê= 00000020 FC 06 35 54 38 25 56 C8 1F 50 E9 06 04 58 85 5E ü.5T8%VÈ.Pé..X…^ 00000030 8C 91 E1 AD 84 DF 60 49 FC 01 61 FF 47 A9 D5 6A Œ‘á.„ß`Iü.aÿG©Õj 00000040 B5 B2 06 48 65 0D D0 FA BE C3 D3 0E A1 EF 3B BC µ².He.Ðú¾ÃÓ.¡ï;¼ 00000050 EF F0 BE C3 73 0E A1 EF 3B BC EF F0 BE C3 73 0E ïð¾Ãs.¡ï;¼ïð¾Ãs. 00000060 A1 DB E1 0F 58 E4 3E 89 50 4E 47 0D 0A 1A 0A 00 ¡Ûá.Xä>‰PNG..... // PNG begins here 00000070 00 00 0D 49 48 44 52 F0 E0 08 02 B2 E1 7C 5E 00 ...IHDRðà..²á|^. // IHDR chunk indicated as 13 (0x0D) bytes, yet this is clearly not the case 00000080 01 73 52 47 42 00 AE CE 1C E9 06 62 4B 47 44 00 .sRGB.®Î.é.bKGD. 00000090 FF A0 BD A7 93 09 70 48 59 73 0B 11 01 7F 64 5F ÿ ½§“.pHYs....d_ 000000A0 91 07 74 49 4D 45 07 E0 02 18 07 12 13 CC F8 BA ‘.tIME.à.....Ìøº 000000B0 BA B6 49 44 41 54 78 DA ED D2 C1 0D 04 00 31 C4 º¶IDATxÚíÒÁ...1Ä 000000C0 FE 2B 33 83 AF B4 23 5C 2E A7 27 E0 8B 92 00 43 þ+3ƒ¯´#\.§'à‹’.C 000000D0 83 A1 C1 D0 60 68 0C 0D 86 06 43 83 A1 C1 D0 18 ƒ¡ÁÐ`h..†.Cƒ¡ÁÐ. 000000E0 1A 0C 0D 86 06 31 34 18 1A 63 68 30 34 C6 30 8D ...†.14..ch04Æ0. 000000F0 60 86 AB 05 8F 4F 03 C2 58 19 85 B6 00 49 45 4E `†«..O.ÂX.…¶.IEN 00000100 44 AE 42 60 82 00 00 00 D®B`‚...

As you can see, several standard PNG chunk names are present (sRGB, bKGD, IDAT, etc.) however the data between them appears to be scrambled.

Some other observations:

  • bytes 0x14-17 seem to be a DWORD indicating the custom header size (0x1C or 28 bytes)
  • bytes 0x1C-1D seem to be a WORD indicating the size of the data between themselves and where the actual PNG header begins (0x4B00 or 75 bytes, including the 2 size bytes) - this unknown data could well be the chunk data in some scrambled form

Has anyone encountered this kind of PNG before?