# I Built My Own RE Tool Because Tutorials Only Taught Me How to Use Ghidra
Every firmware RE resource I found was a tutorial on operating Ghidra or IDA Pro. Nothing on how any of it actually worked. I couldn't learn from tool tutorials, so I built Ablation -- a binary analysis framework written from scratch in Python with no dependency on any existing RE tool. ELF parsing, section mapping, instruction scanning, taint tracking, all built from first principles over three months.
Then I pointed it at FortiManager.
## What Fortinet Is Doing
FortiManager, FortiAnalyzer, and FortiWeb ship as VMware appliance archives with AES-128-CTR encryption on `rootfs.gz`. Two layers stand between the firmware download and the plaintext rootfs.
*Layer 1 -- bzImage XOR.* The 32 bytes before the compressed vmlinux payload in `vmlinuz` are Fortinet's XOR key (null in a standard bzImage). XOR-decrypt and decompress to get a raw ELF64 vmlinux.
*Layer 2 -- AES key in `.init.data`.* The kernel's `.init.data` section holds the 16-byte AES key and IV in plaintext. Both are inside the same firmware archive they protect.
## How Ablation Found the Keys
Ablation scans `.init.text` for the key-load pattern:
```
ba 10 00 00 00 ; mov edx, 0x10 (keylen = 16)
48 c7 c6 XX XX XX XX ; mov rsi, imm32 (VA of key in .init.data)
```
Convert the VA to a file offset, read 32 bytes, decrypt:
1 comment
[ 0.24 ms ] story [ 3.3 ms ] threadEvery firmware RE resource I found was a tutorial on operating Ghidra or IDA Pro. Nothing on how any of it actually worked. I couldn't learn from tool tutorials, so I built Ablation -- a binary analysis framework written from scratch in Python with no dependency on any existing RE tool. ELF parsing, section mapping, instruction scanning, taint tracking, all built from first principles over three months.
Then I pointed it at FortiManager.
## What Fortinet Is Doing
FortiManager, FortiAnalyzer, and FortiWeb ship as VMware appliance archives with AES-128-CTR encryption on `rootfs.gz`. Two layers stand between the firmware download and the plaintext rootfs.
*Layer 1 -- bzImage XOR.* The 32 bytes before the compressed vmlinux payload in `vmlinuz` are Fortinet's XOR key (null in a standard bzImage). XOR-decrypt and decompress to get a raw ELF64 vmlinux.
*Layer 2 -- AES key in `.init.data`.* The kernel's `.init.data` section holds the 16-byte AES key and IV in plaintext. Both are inside the same firmware archive they protect.
## How Ablation Found the Keys
Ablation scans `.init.text` for the key-load pattern:
``` ba 10 00 00 00 ; mov edx, 0x10 (keylen = 16) 48 c7 c6 XX XX XX XX ; mov rsi, imm32 (VA of key in .init.data) ```
Convert the VA to a file offset, read 32 bytes, decrypt:
```python key_foff = init_data['file_off'] + (key_va - init_data['va']) cipher = Cipher(algorithms.AES(key), modes.CTR(iv)) pt = cipher.decryptor().update(open("rootfs.gz","rb").read()) assert pt[:6] == b'\xfd7zXZ\x00' # confirmed ```
The pattern is fixed across versions. One batch job extracted every key.
## The Keys
``` Version Key IV ------- -------------------------------- -------------------------------- 7.2.9 3461638e65158e278bb467317a63edaa a426471e59993b4dda681e90a9ad9f05 7.2.10 6cb3c1a3bd61f127e22e0e13e590df69 02971e0a19d57f0be7ca460204e80d95 7.2.11 614f00a90834166cdf609d79ae17e75d 02261cd66e5a5cd491e124ea90e9751f 7.2.12 ac28fb9f10516f31b3005c38a85d3c6e a902bb4e377716c523e03e2ce9e196ce 7.4.6 8819efc5e336496d460f3f6acce05f42 fbe9c610f08db321886f38f799db9759 7.4.7 9ed9401b6cfa75d55946c643513da670 647860d9c81663f562dec1095bb71a7d 7.4.8 06eacfdba41bce4bd34002fcab388d1a 8f49fae7e5086ff2df0cf67e40c799fd 7.4.9 b1f828cdbff4b71ea05823a30e436211 68f87a57608d178aa955d4d2db642ae7 7.4.10 0d4e40abffe51c156fdbff87680a2dd5 f6c1727f82a2c149d13b81645fc1e8b6 7.4.11 f1ee3fc98aeb4daffb217a4a53dcdd1b f0b81a68baf998f2f77f8c9aaa2088d1 7.6.2 970e8e69cb60441724ff3411cfa6b634 7cd3f9c87bd53818bb336d6f3290397c 7.6.3 29b10587466a43805360db917a917971 560275963caf53e599b2281d1aabbb5b 7.6.4 f86eec39baa58a2c80c2b9f9edc1bc98 068e798d0d4c82cb6c4bc9186cdd29ec 7.6.5 adac18f97f0022bf039dcdab368e3682 a8bf2055a83977773e83ca32d889d36e 7.6.6 3c77ca6b385649c694fa508bfd98ac02 09d7eb174f4c0f0296ecc918daf3c999 7.6.7 2b146f196c5351405075954293b91be7 e5f4142de8103488062497fa4dbe064f 8.0.0 e640945cbf2027dc6583b1da2c84fee2 414faf05902d253f9569289b03aa9a75 ```
Building the tool taught me more about binary analysis than any Ghidra tutorial ever could have.
Ablation: [github.com/Ablation-Tool/ablation](https://github.com/Ablation-Tool/ablation)