Lately I’ve been working on taking apart some VxWorks firmware images. Unfortunately, I could find precious little information available on the subject, so today we’ll be extracting the VxWorks kernel and application code from the WRT54Gv8 firmware image and analyzing them in IDA Pro.

The WRT54G series infamously switched from Linux to VxWorks with the release of the WRT54Gv5. Because VxWorks is a proprietary RTOS, it is a less familiar environment than a Linux based system. Even once you identify the different sections of the firmware image, there usually isn’t a standard file system full of standard ELF executables that can be automatically analyzed by a disassembler.

The overall process for reversing this firmware is pretty straight forward:

Identify and extract actual executable code from the firmware image Identify the loading address for the executable code Load the executable code into IDA Pro at the appropriate loading address Augment IDA’s auto analysis with manual/scripted analysis

Debugging with JTAG or observing debug messages over a serial port can probably be substituted for steps #1 and #2, but since I don’t have any VxWorks WRT54G routers, this will be a purely firmware based analysis.

The first step is to locate any identifiable data sections in the firmware image:

embedded@ubuntu:~/WRT54Gv8$ binwalk -v FW_WRT54Gv8_8.00.8.001_US_20091005.bin Scan Time: Jul 05, 2011 @ 09:24:20 Magic File: /usr/local/etc/binwalk/magic.binwalk Signatures: 64 Target File: FW_WRT54Gv8_8.00.8.001_US_20091005.bin MD5 Checksum: 74317a70160f80fa5df01de0e479a39c DECIMAL HEX DESCRIPTION ------------------------------------------------------------------------------------------------------- 512 0x200 ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV) 101658 0x18D1A Linux Journalled Flash filesystem, little endian 103664 0x194F0 LZMA compressed data, properties: 0x6C, dictionary size: 8388608 bytes, uncompressed size: 3680864 bytes 1146276 0x117DA4 LZMA compressed data, properties: 0xA0, dictionary size: 486539264 bytes, uncompressed size: 520093696 bytes 1185153 0x121581 gzip compressed data, was "apply.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1185892 0x121864 gzip compressed data, was "apply1.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1186870 0x121C36 gzip compressed data, was "apply2.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1187499 0x121EAB gzip compressed data, was "apply2sec.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1188483 0x122283 gzip compressed data, was "apply3.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1189464 0x122658 gzip compressed data, was "applyW.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1190202 0x12293A gzip compressed data, was "bad.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1190724 0x122B44 gzip compressed data, was "basic.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1202618 0x1259BA gzip compressed data, was "bkconfig.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009 1205617 0x126571 gzip compressed data, was "chghttps.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:59 2009 1206740 0x1269D4 gzip compressed data, was "ChgLan.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:59 2009 1207440 0x126C90 gzip compressed data, was "common.js", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:59 2009 1210112 0x127700 gzip compressed data, was "Cysaja.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:59 2009 1210324 0x1277D4 gzip compressed data, was "DDNS.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:59 2009 1214620 0x12889C gzip compressed data, was "default.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1215253 0x128B15 gzip compressed data, was "DEVICE.HTM", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1216309 0x128F35 gzip compressed data, was "DHCPTable.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1217539 0x129403 gzip compressed data, was "Diag.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1220485 0x129F85 gzip compressed data, was "DMZ.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1223383 0x12AAD7 gzip compressed data, was "ERRSCRN.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1224077 0x12AD8D gzip compressed data, was "FacDef.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1226898 0x12B892 gzip compressed data, was "FilterMac.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1228632 0x12BF58 gzip compressed data, was "Filters.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1233858 0x12D3C2 gzip compressed data, was "Firewall.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1236986 0x12DFFA gzip compressed data, was "Forward.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1241779 0x12F2B3 gzip compressed data, was "getstatus.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1242777 0x12F699 gzip compressed data, was "HDDNS.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:00 2009 1244149 0x12FBF5 gzip compressed data, was "HDefault.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1245052 0x12FF7C gzip compressed data, was "HDMZ.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1246049 0x130361 gzip compressed data, was "HExile.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1247163 0x1307BB gzip compressed data, was "HFilters.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1248531 0x130D13 gzip compressed data, was "HFirewall.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1249494 0x1310D6 gzip compressed data, was "HForward.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1250527 0x1314DF gzip compressed data, was "HLog.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1251393 0x131841 gzip compressed data, was "HMAC.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1252433 0x131C51 gzip compressed data, was "HManage.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1253438 0x13203E gzip compressed data, was "HOBA.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1254564 0x1324A4 gzip compressed data, was "HRouting.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1255864 0x1329B8 gzip compressed data, was "HSetup.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1257408 0x132FC0 gzip compressed data, was "HStatus.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1258783 0x13351F gzip compressed data, was "HUpgrade.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1259855 0x13394F gzip compressed data, was "HVPN.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1260808 0x133D08 gzip compressed data, was "HWEP.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1262621 0x13441D gzip compressed data, was "HWireless.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1264097 0x1349E1 gzip compressed data, was "HWPA.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1265245 0x134E5D gzip compressed data, was "InLog.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:01 2009 1266075 0x13519B gzip compressed data, was "language.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1269311 0x135E3F gzip compressed data, was "lastpassword.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1269507 0x135F03 gzip compressed data, was "Log.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1272546 0x136AE2 gzip compressed data, was "Manage.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1277123 0x137CC3 gzip compressed data, was "md5.js", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1278995 0x138413 gzip compressed data, was "Outbreak_Alert.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1282781 0x1392DD gzip compressed data, was "OutLog.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1283619 0x139623 gzip compressed data, was "ping.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1287957 0x13A715 gzip compressed data, was "ptrigger.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1292450 0x13B8A2 gzip compressed data, was "qos.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1298667 0x13D0EB gzip compressed data, was "Quarantined.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1300366 0x13D78E gzip compressed data, was "reset.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1301699 0x13DCC3 gzip compressed data, was "Routing.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1306547 0x13EFB3 gzip compressed data, was "RTable.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1307445 0x13F335 gzip compressed data, was "Service.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1310944 0x1400E0 gzip compressed data, was "StaLan.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1313858 0x140C42 gzip compressed data, was "StaRouter.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1318404 0x141E04 gzip compressed data, was "StaWlan.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1324110 0x14344E gzip compressed data, was "summary.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1325773 0x143ACD gzip compressed data, was "sysinfo.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:02 2009 1325986 0x143BA2 gzip compressed data, was "test.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1326015 0x143BBF gzip compressed data, was "Traceroute.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1340943 0x14760F gzip compressed data, was "Unauthorized.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1341087 0x14769F gzip compressed data, was "Upgrade.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1344585 0x148449 gzip compressed data, was "UpgStat.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1345231 0x1486CF gzip compressed data, was "UpLangPak.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1346753 0x148CC1 gzip compressed data, was "VPN.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1352719 0x14A40F gzip compressed data, was "WAdv.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1356924 0x14B47C gzip compressed data, was "WanMAC.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1360319 0x14C1BF gzip compressed data, was "WClient.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1362096 0x14C8B0 gzip compressed data, was "WFilter.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1367188 0x14DC94 LZMA compressed data, properties: 0x80, dictionary size: 1110966272 bytes, uncompressed size: 218385737 bytes 1379589 0x150D05 LZMA compressed data, properties: 0x80, dictionary size: 1110966272 bytes, uncompressed size: 218385737 bytes 1390145 0x153641 gzip compressed data, was "Wireless.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1396588 0x154F6C gzip compressed data, was "wlaninfo.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1396765 0x15501D gzip compressed data, was "WMList.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1402406 0x156626 gzip compressed data, was "wps_result.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1403174 0x156926 gzip compressed data, was "wps_search.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1407322 0x15795A gzip compressed data, was "WSecurity.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:04 2009 1413245 0x15907D gzip compressed data, was "WState.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009 1414025 0x159389 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1415312 0x159890 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1415961 0x159B19 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:23 2009 1422692 0x15B564 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1424577 0x15BCC1 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1426257 0x15C351 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1426777 0x15C559 gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1427511 0x15C837 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1428222 0x15CAFE gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1440881 0x15FC71 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1444717 0x160B6D gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1446043 0x16109B gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1446740 0x161354 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1453397 0x162D55 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1455360 0x163500 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1457203 0x163C33 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1457760 0x163E60 gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1458484 0x164134 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1459130 0x1643BA gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1470606 0x16708E gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1474489 0x167FB9 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:11 2009 1475924 0x168554 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:12 2009 1476640 0x168820 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:19 2009 1484040 0x16A508 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:12 2009 1486131 0x16AD33 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:12 2009 1487922 0x16B432 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:13 2009 1488498 0x16B672 gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:13 2009 1489232 0x16B950 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:14 2009 1490002 0x16BC52 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:16 2009 1502977 0x16EF01 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Mon Jul 20 02:06:18 2009 1507309 0x16FFED gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1508872 0x170608 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1509579 0x1708CB gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:23 2009 1517398 0x172756 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1519422 0x172F3E gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1521274 0x17367A gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1521858 0x1738C2 gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1522740 0x173C34 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1523552 0x173F60 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1537579 0x17762B gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1541905 0x178711 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1543410 0x178CF2 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1544153 0x178FD9 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1551383 0x17AC17 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1553369 0x17B3D9 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1555240 0x17BB28 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1555807 0x17BD5F gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1556608 0x17C080 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1557451 0x17C3CB gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1570691 0x17F783 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1575061 0x180895 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1576468 0x180E14 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1577168 0x1810D0 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1583976 0x182B68 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1585919 0x1832FF gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1587626 0x1839AA gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1588171 0x183BCB gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1588954 0x183EDA gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1589732 0x1841E4 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1602550 0x1873F6 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1606645 0x1883F5 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1608110 0x1889AE gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1608851 0x188C93 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1616048 0x18A8B0 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1618053 0x18B085 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1619884 0x18B7AC gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1620434 0x18B9D2 gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1621256 0x18BD08 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1622020 0x18C004 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1635437 0x18F46D gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1639557 0x190485 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1640989 0x190A1D gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1641705 0x190CE9 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1648936 0x192928 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1650918 0x1930E6 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1652676 0x1937C4 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1653245 0x1939FD gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1654035 0x193D13 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1654781 0x193FFD gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1668039 0x1973C7 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1672113 0x1983B1 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1673513 0x198929 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1674220 0x198BEC gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:23 2009 1681271 0x19A777 gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1683281 0x19AF51 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1685025 0x19B621 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1685594 0x19B85A gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1686372 0x19BB64 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1687111 0x19BE47 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1699948 0x19F06C gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1703937 0x1A0001 gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1705425 0x1A05D1 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1706169 0x1A08B9 gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1713196 0x1A242C gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1715253 0x1A2C35 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1717098 0x1A336A gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1717679 0x1A35AF gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1718519 0x1A38F7 gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1719332 0x1A3C24 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1732356 0x1A6F04 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009 1736429 0x1A7EED gzip compressed data, was "capadmin.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1737865 0x1A8489 gzip compressed data, was "capapp.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:18 2009 1738572 0x1A874C gzip compressed data, was "capasg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:24 2009 1745822 0x1AA39E gzip compressed data, was "capsec.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1747816 0x1AAB68 gzip compressed data, was "capsetup.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1749609 0x1AB269 gzip compressed data, was "capstatus.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:19 2009 1750156 0x1AB48C gzip compressed data, was "ddnsmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1750922 0x1AB78A gzip compressed data, was "errmsg.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:20 2009 1751669 0x1ABA75 gzip compressed data, was "help.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:21 2009 1765090 0x1AEEE2 gzip compressed data, was "share.js", from NTFS filesystem (NT), last modified: Tue Jul 14 04:38:22 2009

Binwalk has identified a lot of gzipped Web files, a few LZMA signatures, an ELF header, and even a JFFS file system.

The JFFS file system is almost certainly a false positive, so we’ll ignore it.

Looking through a hex dump of the firmware, the gzipped Web files do look to be part of a simple file system, similar to the the OW file system discussed previously. However, the Web files are not particularly relevant for the purposes of this discussion, so I will forgo an analysis of the file system here; if desired, these files can simply be extracted from the firmware image and gunzipped.

There were four LZMA signatures found, but all except one have very large uncompressed sizes (several hundred MB each), so these are probably false positives. However, the first LZMA signature at offset 0x194F0 is just over 3.5 MB. This is a reasonable size, so let’s extract and decompress the LZMA data:

embedded@ubuntu:~/WRT54Gv8$ dd if=FW_WRT54Gv8_8.00.8.001_US_20091005.bin skip=1 bs=103664 of=lzma_data.7z 16+1 records in 16+1 records out 1665240 bytes (1.7 MB) copied, 0.00559597 s, 298 MB/s

embedded@ubuntu:~/WRT54Gv8$ p7zip -d lzma_data.7z 7-Zip (A) 9.04 beta Copyright (c) 1999-2009 Igor Pavlov 2009-05-30 p7zip Version 9.04 (locale=en_US.utf8,Utf16=on,HugeFiles=on,1 CPU) Processing archive: lzma_data.7z Extracting lzma_data Everything is Ok Size: 3680864 Compressed: 1665240

It looks like the decompression went OK; let’s run strings and hexdump against the decompressed data to see what we can find:

embedded@ubuntu:~/WRT54Gv8$ strings lzma_data | less NORMAL_CODE_DATA 5VGW$LANGPACK_CODE_DATA= $MODEL_NAME=WRT54G $OEM_NAME=LINKSYS Copyright 2004-2005 CyberTAN Limited ... GetConnectedDevices GetRouterLanSettings2 GetWanInfo GetWanSettings GetMACFilters2 GetPortMappings GetDeviceSettings HTTP/1.1 307 Temporary Redirect Location: https://%s%s/HNAP1/ HTTP/1.1 500 Internal Server Error Server: httpd

embedded@ubuntu:~/WRT54Gv8$ hexdump -C lzma_data | head 00000000 22 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 |"...............| 00000010 4e 4f 52 4d 41 4c 5f 43 4f 44 45 5f 44 41 54 41 |NORMAL_CODE_DATA| 00000020 01 80 00 08 35 56 47 57 24 4c 41 4e 47 50 41 43 |....5VGW$LANGPAC| 00000030 4b 5f 43 4f 44 45 5f 44 41 54 41 3d 06 01 00 01 |K_CODE_DATA=....| 00000040 24 4d 4f 44 45 4c 5f 4e 41 4d 45 3d 57 52 54 35 |$MODEL_NAME=WRT5| 00000050 34 47 00 24 4f 45 4d 5f 4e 41 4d 45 3d 4c 49 4e |4G.$OEM_NAME=LIN| 00000060 4b 53 59 53 00 43 6f 70 79 72 69 67 68 74 20 32 |KSYS.Copyright 2| 00000070 30 30 34 2d 32 30 30 35 20 43 79 62 65 72 54 41 |004-2005 CyberTA| 00000080 4e 20 4c 69 6d 69 74 65 64 00 00 00 39 80 1c 3c |N Limited...9..

There are definitely some interesting strings in this data, including what appears to be application strings for services such as HTTP and HNAP.

There is some binary data in there as well, which may or may not be executable code. However, if it is executable code, there is no distinguishable header or section information; this makes analysis much more difficult. We also don't yet know the CPU architecture or endianess of the target (although this could be found with a Google search).

We do, however, have an ELF header located at offset 0x200 in the firmware image, so let's take a closer look at that:

embedded@ubuntu:~/WRT54Gv8$ dd if=FW_WRT54Gv8_8.00.8.001_US_20091005.bin bs=512 skip=1 of=elf 3453+1 records in 3453+1 records out 1768392 bytes (1.8 MB) copied, 0.020778 s, 85.1 MB/s

embedded@ubuntu:~/WRT54Gv8$ file elf elf: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), statically linked, not stripped

embedded@ubuntu:~/WRT54Gv8$ strings -n 10 elf | head VxWorks5.4.2 Oct 5 2009, 15:15:53 memPartFree %-5s = %8x 0123456789abcdef 0123456789ABCDEF bug in vfprintf: bad base WIND version 2.5 workQPanic: Kernel work queue overflow. DDDDDDDDDD

It's a little endian MIPS ELF file with several string references to 'VxWorks', 'Wind River' and 'Kernel'; this looks like it could be the VxWorks kernel. Let's load it into IDA and see what we can make of it (be sure to select the mipsl CPU):

Because this image has an ELF header, IDA's auto analysis does a very good job of identifying functions and resolving symbols for us. Let's take a look at the first subroutine, startInflate:

The address 0x80001000 is loaded into $v0 and the decompressImage function is called; execution then jumps to the address stored in $v0 (0x80001000). So presumably, the decompressImage function decompresses some code to address 0x80001000, which then takes over execution.

Looking at the arguments to decompressImage, the first is _binArrayStart and the second is the address 0x80001000. Let's take a look at _binArrayStart:

The first five bytes at the _binArrayStart address are 6C 00 00 80 00, which looks like the beginning of an LZMA image. Comparing the bytes in _binArrayStart to the LZMA data that we extracted earlier, we see that they are identical:

embedded@ubuntu:~/WRT54Gv8$ hexdump -C lzma_data.7z | head 00000000 6c 00 00 80 00 60 2a 38 00 00 00 00 00 00 11 00 |l....`*8........| 00000010 2c 20 00 df 1e 01 d7 44 6b 43 41 4d a8 aa 91 9c |, .....DkCAM....| 00000020 11 ed 0d 6b bd 40 da 21 19 b1 16 8b 51 48 b8 a6 |...k.@.!....QH..| 00000030 c9 1f 7e 0b 24 4c 24 14 2b db 64 59 fb 79 2a 3c |..~.$L$.+.dY.y*

Looking further into the decompressImage function, we also see that it calls another function named LzmaDecode:

So it appears that the LZMA data that we extracted earlier does contain executable code, and that it is decompressed and loaded into memory at address 0x80001000. A Google search for 'vxworks lzmadecode' turns up some source code that confirms this conclusion.

Based on the strings we saw earlier, the LZMA data likely contains the OS application code.

We now have enough information to load the extracted LZMA data into IDA for analysis. As with the kernel, we'll set the architecture to mipsl, but since this is a binary file we will also have to supply IDA with the proper loading information.

To do this, we'll set the ROM start address to 0x80001000, and the ROM size to the size of the file, 0x382A60. We'll also set the loading address to 0x80001000:

Once the file is loaded into IDA, go to the first byte and press 'c' to convert it to code. IDA will start converting bytes to code and performing an analysis of the binary file. The very first instruction is a jump that conveniently skips over some strings that are located near the beginning of the file:

The code looks sane, IDA has identified just over 5,000 functions, and string references look correct too:

Contrast the above disassembly with the same data after performing the same code analysis in IDA, but without setting the proper loading address:

There is also a decent amount of blue (code) in IDA's navigation bar:

Although our efforts have improved IDA's initial analysis, there is still a good deal of code that has been missed. I've written some simple IDA scripts which can be used to get more out of the disassembly.

First, we want to locate unidentified functions by iterating through the code looking for common function prologues. If one is found, we'll tell IDA to create a function there. This is sometimes a bit trickier for MIPS than for the Intel architecture, since function prologues are less standardized in MIPS.

The addui instruction is often used to manipulate the stack register ($sp) at the beginning of a function. We can see that this is the case for many of the functions identified by IDA:

However, there are some functions that precede the addui instruction with an lw instruction:

The create_functions.py IDAPython script will search the code (starting at the cursor position) for byte sequences that correspond to these instructions, and instruct IDA to convert them to functions.

Looking at the disassembly, the section of data containing the binary's strings appears to start at 0x802DDAC0, so I've coded the script stop at that address:

After running the script, IDA now has over 9,600 defined functions, and a lot more code has been identified:

However, there are still some sections of data that have not yet been analyzed:

These sections are surrounded by code, and navigating to several of these sections and converting them directly to code results in a valid disassembly:

Since these sections all appear to end with 'jr $ra' (the MIPS return instruction), and since they are not referenced by the surrounding functions, they are likely functions themselves.

The create_code.py script will walk through the code converting these unreferenced bytes to functions (as before, the script will start at the cursor position and end at address 0x802DDAC0):

We now have a nice solid block of code in IDA's navigation bar:

With the code taken care of, let's turn our attention to the strings. Without symbols like we had in the ELF file, we will have to rely on string references to provide key insights into what is going on in the firmware. However, there are still some ASCII byte arrays that have not been converted to strings by IDA:

Converting these ASCII arrays to strings will make reading the code much easier, so the create_ascii.py script converts all ASCII byte arrays to strings. As we saw before, the section of the image that contains the string data starts at offset 0x802DDAC0, so we'll place the cursor at that address in IDA and run the script from there. This results in data that is much easier to read and recognize:

With our strings now fixed up, let's try to identify some basic functions in the disassembly:

There are two function calls here; the first, sub_802A7F90, takes a single argument: the number 1, shifted left 16 bits (65536). If the return value is zero, a second function, sub_802A06E8 is called.

The second function takes two arguments: a string that contains common printf formatting, and the number 65536. The pseudo code looks like:

if(!sub_802A7F90(65536)) { sub_802A06E8("Can't allocate %d bytes of memory

", 65536); }

This makes it pretty obvious that sub_802A7F90 is the equivalent of malloc, and sub_802A06E8 is printf. We'll rename these functions appropriately so that references to them elsewhere in the code will be readily apparent:

That's it! We now have working disassemblies of both the kernel and application code that we can use to further analyze VxWorks for additional functions, bugs or vulnerabilities.