Mini Line
7 minutos de lectura
Se nos proporciona un archivo llamado firmware.hex
que se ve así:
:100154002F6C69622F6C642D6C696E75782E736FC9
:030164002E330037
:10016800040000001400000003000000474E550082
:10017800891BDEC57F0B4D5D5D0569FF4FE7A53423
:04018800F5185E41C7
:10018C00040000001000000001000000474E550064
:10019C00000000000300000002000000000000004E
:1001AC000100000001000000010000000000000040
:0801BC0000000000000000003B
:1001C400000000000000000000000000000000002B
:1001D40000000000780300000000000003000B0092
:1001E40000000000381001000000000003001600A9
:1001F40007000000000000000000000022000000D2
:100204003C0000000000000000000000200000008E
:1002140016000000000000000000000012000000B2
:100224005800000000000000000000002000000052
:100234006700000000000000000000002000000033
:100244000100000000000000000000001200000097
:100254000061626F7274005F5F6378615F66696EEC
:10026400616C697A65005F5F6C6962635F73746176
:1002740072745F6D61696E006C6962632E736F2EB8
:100284003600474C4942435F322E34005F49544D97
:100294005F64657265676973746572544D436C6F0E
:1002A4006E655461626C65005F5F676D6F6E5F734E
:1002B400746172745F5F005F49544D5F7265676972
:1002C40073746572544D436C6F6E655461626C65F2
:0102D4000029
:1002D6000000000000000200000002000000000014
:0202E600020014
:1002E80001000100280000001000000000000000CC
:1002F8001469690D000002003200000000000000CF
:10030800080F0100170000000C0F01001700000083
:100318001C100100170000002C100100170000003D
:1003280030100100170000003C1001001700000009
:10033800201001001503000024100100150400001E
:1003480028100100150600003410010015070000F0
:100358000C10010016030000101001001605000023
:1003680014100100160600001810010016080000FD
:0C03780008402DE9270000EB0880BDE8DC
:1003840004E02DE504E09FE50EE08FE008F0BEE513
:100394006C0C010000C68FE210CA8CE26CFCBCE558
:1003A40000C68FE210CA8CE264FCBCE500C68FE292
:1003B40010CA8CE25CFCBCE500C68FE210CA8CE279
:0403C40054FCBCE544
:1003C80000B0A0E300E0A0E304109DE40D20A0E14C
:1003D80004202DE504002DE528A09FE524308FE2B8
:1003E80003A08AE020C09FE50CC09AE704C02DE571
:1003F80018309FE503309AE714009FE500009AE75C
:10040800E5FFFFEBEAFFFFEBF00B01001C0000002B
:100418002C0000003000000014309FE514209FE5F8
:1004280003308FE0022093E7000052E31EFF2F0104
:10043800DCFFFFEAD00B0100280000002C009FE53C
:100448002C309FE500008FE003308FE0000053E17F
:1004580020309FE503308FE01EFF2F0118209FE515
:10046800023093E7000053E31EFF2F0113FF2FE133
:10047800EC0B0100E80B01009C0B010024000000BC
:1004880038009FE538109FE500008FE001108FE0ED
:10049800001041E0A13FA0E1411183E024309FE535
:1004A800C110B0E103308FE01EFF2F0118209FE537
:1004B800023093E7000053E31EFF2F0113FF2FE1E3
:1004C800A80B0100A40B01004C0B01003400000034
:1004D8004C309FE54C209FE503308FE00030D3E59A
:1004E80002208FE0000053E31EFF2F1138309FE5F4
:1004F80010402DE9033092E7000053E30200000AA0
:1005080028309FE503009FE7A0FFFFEBCAFFFFEB42
:100518001C309FE50120A0E303308FE00020C3E5F5
:100528001080BDE8580B0100100B010020000000EE
:10053800280B0100180B0100D0FFFFEA04B02DE5DD
:1005480000B08DE20CD04DE20030A0E105304BE563
:1005580050309FE5003093E5FF3CC3E305205BE5A1
:100568000224A0E10210A0E138209FE5013083E1D8
:10057800003082E530309FE50528A0E3002083E5C0
:1005880028309FE50228A0E3002083E51C309FE582
:100598000127A0E3002083E50000A0E100D08BE262
:1005A80004B09DE41EFF2FE1008002E0048002E019
:1005B8000C8002E000482DE904B08DE210D04DE235
:1005C80010000BE50030A0E305304BE5080000EA19
:1005D80005305BE510201BE5033082E00030D3E5F1
:1005E8000300A0E1D4FFFFEB05305BE5013083E2B7
:1005F80005304BE505305BE510201BE5033082E054
:100608000030D3E5000053E3F0FFFF1A0000A0E13B
:100618000000A0E104D04BE20088BDE804B02DE55D
:1006280000B08DE234309FE5003093E52C209FE543
:10063800153C83E3003082E524309FE52020A0E3C9
:10064800B020C3E11C309FE51020A0E30020C3E5E3
:100658000000A0E100D08BE204B09DE41EFF2FE172
:1006680000C002E0000002E00C0002E004B02DE54A
:1006780000B08DE214D04DE20030A0E10D304BE522
:1006880068309FE58020A0E3002083E560209FE597
:100698000D305BE50338A0E12338A0E1B030C2E1BA
:1006A8000000A0E14C309FE50030D3E5FF3003E2C5
:1006B800033CA0E1433CA0E1000053E3F8FFFFAA9C
:1006C8002C309FE5B030D3E10338A0E12338A0E116
:1006D80005304BE520309FE58020A0E3002083E52E
:1006E8000000A0E100D08BE204B09DE41EFF2FE1E2
:1006F8000C8002E0080002E0040002E0048002E04E
:1007080000482DE904B08DE230D04DE26C319FE510
:1007180003308FE020C04BE20F0093E80F008CE815
:100728005C319FE524300BE558319FE503308FE0BD
:1007380034C04BE20F0093E80700ACE80030CCE58A
:1007480044319FE503308FE00300A0E198FFFFEB01
:10075800B1FFFFEB34319FE503308FE00300A0E1E8
:1007680093FFFFEB0100A0E3BFFFFFEB20319FE504
:1007780003308FE00300A0E18DFFFFEB0030A0E322
:1007880008300BE50A0000EA20204BE208301BE5A0
:10079800033082E00030D3E51A3023E2FF3003E271
:1007A8000300A0E1B0FFFFEB08301BE5013083E256
:1007B80008300BE508301BE5100053E3F1FFFFDAC2
:1007C8000030A0E30C300BE50C0000EA24204BE2DB
:1007D8000C301BE5033082E00030D3E5A330A0E104
:1007E800FF3003E2393023E2FF3003E20300A0E1E7
:1007F8009DFFFFEB0C301BE5013083E20C300BE56D
:100808000C301BE5040053E3EFFFFFDA0030A0E3F0
:1008180010300BE50C0000EA34204BE210301BE5E9
:10082800033082E00030D3E5A330A0E1FF3003E2DB
:10083800393023E2FF3003E20300A0E18AFFFFEB37
:1008480010301BE5013083E210300BE510301BE55A
:100858000D0053E3EFFFFFDA38309FE503308FE0F8
:100868000300A0E152FFFFEB0000A0E37EFFFFEBD7
:100878000030A0E30300A0E104D04BE20088BDE80B
:10088800E00200001A9614CCD402000050020000C6
:10089800500200004802000078010000F0472DE9EE
:1008A8004C609FE54C509FE506608FE005508FE057
:1008B800056046E00070A0E10180A0E10290A0E19F
:1008C800AAFEFFEB4661B0E1F087BD080040A0E357
:1008D800043095E40920A0E10810A0E10700A0E198
:1008E800014084E233FF2FE1040056E1F7FFFF1ACD
:1008F800F087BDE8540601004C0601001EFF2FE1F9
:0809080008402DE90880BDE85C
:10091000010002003A0000003D0000000A00000053
:100920003D0000000F0000003D000000240000001A
:100930003D000000320000003D0000000200000009
:100940003D000000050000003D0000001300000015
:100950003D0000000D0000003D0000000C00000004
:100960003D000000230000003D00000011000000D9
:100970003D000000260000003D00000001000000D6
:100980003D000000170000003D00000008000000CE
:100990003D000000090000003D00000000000000D4
:1009A0000000000053504920496E697469616C6908
:1009B0007A6174696F6E00005374617274206269A9
:1009C00074207365740000005472616E736D6974F5
:1009D00074696E67206461746120746F20736C6148
:1009E0007665000044617461207472616E7366659F
:1009F0007220697320636F6D706C657465640000AC
:100A0000524E5861782E68294577296E2E766945B1
:100A1000BE98AECC1412BABE103030308800000040
:100A20003A0000003D0000000A0000003D00000008
:100A30000F0000003D000000240000003D00000009
:100A4000320000003D000000020000003D000000F8
:100A5000050000003D000000130000003D00000004
:100A60000D0000003D0000000C0000003D000000F3
:100A7000230000003D000000110000003D000000C8
:100A8000260000003D000000010000003D000000C5
:100A9000170000003D000000080000003D000000BD
:100AA000090000003D000000000000000000000000
:080AB00018F9FF7F01000000AE
:040AB800000000003A
:020000021000EC
:040F080040050000A0
:040F0C00D804000005
:100F100001000000280000000C0000007803000021
:100F20000D0000000809000019000000080F010072
:100F30001B000000040000001A0000000C0F01005C
:100F40001C00000004000000F5FEFF6FAC01000073
:100F5000050000005402000006000000C40100006B
:100F60000A000000810000000B00000010000000DB
:100F70001500000000000000030000000010010048
:100F8000020000002000000014000000110000001A
:100F900017000000580300001100000008030000C3
:100FA00012000000500000001300000008000000C4
:100FB000FBFFFF6F00000008FEFFFF6FE80200006C
:100FC000FFFFFF6F01000000F0FFFF6FD60200007F
:100FD000FAFFFF6F060000000000000000000000A4
:100FE0000000000000000000000000000000000001
:100FF00000000000000000000000000000000000F1
:10100000100F010000000000000000008403000039
:10101000840300008403000084030000040900002E
:10102000000000000000000000000000A408000014
:081030000807000000000000A9
:08103800000000003C10010063
:04000003000003C82E
:00000001FF
Solo sabemos que este es el firmware de un microcontrolador LPC2148 que está enviando datos.
Intel Hex
Si investigamos un poco sobre el nombre del archivo y la extensión, descubriremos que el formato anterior es Intel HEX que transmite información binaria en formato ASCII.
Buscando herramientas para analizar esto, podemos encontrar varias herramientas como intelhex para transformar .hex
a .bin
:
# wget -q https://raw.githubusercontent.com/pda/intelhex/master/intel_hex.rb
# ruby intel_hex.rb < firmware.hex > firmware.bin
# file firmware.bin
firmware.bin: data
# xxd firmware.bin
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000130: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000140: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000150: 0000 0000 2f6c 6962 2f6c 642d 6c69 6e75 ..../lib/ld-linu
00000160: 782e 736f 2e33 0000 0400 0000 1400 0000 x.so.3..........
00000170: 0300 0000 474e 5500 891b dec5 7f0b 4d5d ....GNU.......M]
00000180: 5d05 69ff 4fe7 a534 f518 5e41 0400 0000 ].i.O..4..^A....
00000190: 1000 0000 0100 0000 474e 5500 0000 0000 ........GNU.....
000001a0: 0300 0000 0200 0000 0000 0000 0100 0000 ................
000001b0: 0100 0000 0100 0000 0000 0000 0000 0000 ................
000001c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001d0: 0000 0000 0000 0000 7803 0000 0000 0000 ........x.......
000001e0: 0300 0b00 0000 0000 3810 0100 0000 0000 ........8.......
000001f0: 0300 1600 0700 0000 0000 0000 0000 0000 ................
00000200: 2200 0000 3c00 0000 0000 0000 0000 0000 "...<...........
00000210: 2000 0000 1600 0000 0000 0000 0000 0000 ...............
00000220: 1200 0000 5800 0000 0000 0000 0000 0000 ....X...........
00000230: 2000 0000 6700 0000 0000 0000 0000 0000 ...g...........
00000240: 2000 0000 0100 0000 0000 0000 0000 0000 ...............
00000250: 1200 0000 0061 626f 7274 005f 5f63 7861 .....abort.__cxa
00000260: 5f66 696e 616c 697a 6500 5f5f 6c69 6263 _finalize.__libc
00000270: 5f73 7461 7274 5f6d 6169 6e00 6c69 6263 _start_main.libc
00000280: 2e73 6f2e 3600 474c 4942 435f 322e 3400 .so.6.GLIBC_2.4.
00000290: 5f49 544d 5f64 6572 6567 6973 7465 7254 _ITM_deregisterT
000002a0: 4d43 6c6f 6e65 5461 626c 6500 5f5f 676d MCloneTable.__gm
000002b0: 6f6e 5f73 7461 7274 5f5f 005f 4954 4d5f on_start__._ITM_
000002c0: 7265 6769 7374 6572 544d 436c 6f6e 6554 registerTMCloneT
000002d0: 6162 6c65 0000 0000 0000 0000 0200 0000 able............
000002e0: 0200 0000 0000 0200 0100 0100 2800 0000 ............(...
000002f0: 1000 0000 0000 0000 1469 690d 0000 0200 .........ii.....
...
Sin embargo, el tipo de archivo no se reconoce. Pero podemos ver algunas strings:
# strings firmware.bin
/lib/ld-linux.so.3
abort
__cxa_finalize
__libc_start_main
libc.so.6v
GLIBC_2.4
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
SPI Initialization
Start bit set
Transmitting data to slave
Data transfer is completed
RNXax.h)Ew)n.viE
Hay una ruta de archivo /lib/ld-linux.so.3
que dice que este es un binario ELF de un sistema operativo Linux de ARM. Si investigamos un poco más, veremos que Intel HEX también puede decodificarse a un binario ELF (más información en stackoverflow.com). Tendremos que usar objcopy
para eso.
Pero debemos instalar arm-linux-gnueabihf-objcopy
porque estamos lidiando con un binario de ARM (probablemente proveniente de una Raspberry Pi):
# arm-linux-gnueabihf-objcopy --input-target=ihex --output-target=elf32-little firmware.hex firmware.elf
# file firmware.elf
firmware.elf: ELF 32-bit LSB relocatable, no machine, version 1 (SYSV), stripped
Análisis del firmware
Ahora podemos cargar el firmware como un archivo binario en Ghidra. Hay varias funciones, pero la que parece más interesante es esta:
undefined4 FUN_00010708() {
undefined4 local_38;
undefined4 uStack_34;
undefined4 uStack_30;
undefined local_2c;
undefined4 local_28;
undefined4 local_24;
undefined4 uStack_20;
undefined4 uStack_1c;
undefined4 uStack_18;
int local_14;
int local_10;
int local_c;
local_24 = *(undefined4 *) (DAT_00010888 + 0x10720);
uStack_20 = *(undefined4 *) (DAT_00010888 + 0x10724);
uStack_1c = *(undefined4 *) (DAT_00010888 + 0x10728);
uStack_18 = *(undefined4 *) (DAT_00010888 + 0x1072c);
local_28 = DAT_0001088c;
local_38 = *(undefined4 *) (DAT_00010890 + 0x1073c);
uStack_34 = *(undefined4 *) (DAT_00010890 + 0x10740);
uStack_30 = *(undefined4 *) (DAT_00010890 + 0x10744);
local_2c = (undefined) *(undefined4 *) (DAT_00010890 + 0x10748);
FUN_000105bc(DAT_00010894 + 0x10754);
FUN_00010624();
FUN_000105bc(DAT_00010898 + 0x10768);
FUN_00010674(1);
FUN_000105bc(DAT_0001089c + 0x10780);
for (local_c = 0; local_c < 0x11; local_c = local_c + 1) {
FUN_00010674(*(byte *) ((int) &local_24 + local_c) ^ 0x1a);
}
for (local_10 = 0; local_10 < 5; local_10 = local_10 + 1) {
FUN_00010674(*(byte *) ((int) &local_28 + local_10) >> 1 ^ 0x39);
}
for (local_14 = 0; local_14 < 0xe; local_14 = local_14 + 1) {
FUN_00010674(*(byte *) ((int) &local_38 + local_14) >> 1 ^ 0x39);
}
FUN_000105bc(DAT_000108a0 + 0x1086c);
FUN_00010674(0);
return 0;
}
En realidad, estamos interesados en los bucles for
. Parecen estar descifrando algunos buffers con un cifrado XOR. Los buffers son señalados por local_24
, local_28
y local_38
.
El buffer local_24
se encuentra en la dirección DAT_00010888 + 0x10720
, que es 0x10a00
; local_28
está en DAT_0001088c
, que es 0x1088c
; y local_38
está en DAT_00010890 + 0x1073c
, que es 0x10a10
. Sabemos esto a partir de estas variables globales:
DAT_00010888 XREF[1]: FUN_00010708:00010714(R)
00010888 e0 02 00 00 undefined4 000002E0h
DAT_0001088c XREF[1]: FUN_00010708:00010728(R)
0001088c 1a 96 14 cc undefined4 CC14961Ah
DAT_00010890 XREF[1]: FUN_00010708:00010730(R)
00010890 d4 02 00 00 undefined4 000002D4h
DAT_00010894 XREF[1]: FUN_00010708:00010748(R)
00010894 50 02 00 00 undefined4 00000250h
DAT_00010898 XREF[1]: FUN_00010708:0001075c(R)
00010898 50 02 00 00 undefined4 00000250h
DAT_0001089c XREF[1]: FUN_00010708:00010774(R)
0001089c 48 02 00 00 undefined4 00000248h
DAT_000108a0 XREF[1]: FUN_00010708:00010860(R)
000108a0 78 01 00 00 undefined4 00000178h
Si vamos a estas direcciones, tenemos:
DAT_00010a00 XREF[1]: FUN_00010708:00010720(R)
00010a00 52 4e 58 61 undefined4 61584E52h
DAT_00010a04 XREF[1]: FUN_00010708:00010720(R)
00010a04 78 2e 68 29 undefined4 29682E78h
DAT_00010a08 XREF[1]: FUN_00010708:00010720(R)
00010a08 45 77 29 6e undefined4 6E297745h
DAT_00010a0c XREF[1]: FUN_00010708:00010720(R)
00010a0c 2e 76 69 45 undefined4 4569762Eh
DAT_00010a10 XREF[1]: FUN_00010708:0001073c(R)
00010a10 be 98 ae cc undefined4 CCAE98BEh
DAT_00010a14 XREF[1]: FUN_00010708:0001073c(R)
00010a14 14 12 ba be undefined4 BEBA1214h
DAT_00010a18 XREF[1]: FUN_00010708:0001073c(R)
00010a18 10 30 30 30 undefined4 30303010h
DAT_00010a1c XREF[1]: FUN_00010708:0001073c(R)
00010a1c 88 00 00 00 undefined4 00000088h
Estos son números enteros de 4 bytes, pero los bucles for
consideran cada uno de sus bytes de forma independiente. Entonces, podemos intentar descifrar este XOR de la siguiente manera:
#!/usr/bin/env python3
from struct import pack
local_24 = [0x61584E52, 0x29682E78, 0x6E297745, 0x4569762E]
local_28 = [0xCC14961A]
local_38 = [0xCCAE98BE, 0xBEBA1214, 0x30303010, 0x00000088]
flag = bytearray()
for d in local_24:
for b in pack('<I', d):
if b:
flag.append(b ^ 0x1a)
for d in local_28:
for b in pack('<I', d):
if b:
flag.append(b >> 1 ^ 0x39)
for d in local_38:
for b in pack('<I', d):
if b:
flag.append(b >> 1 ^ 0x39)
print(flag.decode())
Flag
Si ejecutamos el script de Python anterior, obtendremos la flag:
$ python3 solve.py
HTB{b4r3_m3t4ls_4r3_fun_30df1!!!}