Do you have SYNful Knock installed?

Cisco has provided a method of determining if your router has the SYNful Knock router implant.



Cisco Blog > Security

Offline Analysis of IOS Image Integrity

Forensic analysis of IOS images can be a tricky science, due in part to the diversity in IOS image versions and branches. Between IOS 11 and IOS 12.4, over five thousand different images were built, a quarter of which belong to the 12.2 train. Some IOS trains are in more widespread use than others, just as some hardware platforms are more popular than others, but even when narrowing down by feature-set or hardware, there is a large diversity of images. There are however, some steps that can be taken, both while the IOS device is running, as well as offline, that can help determine the integrity of an IOS image.

The first method that can be used to verify the integrity of an IOS image is to use the verify command, which is built into IOS; the second way is by conducting off-line analysis of an IOS core dump. The first method is covered in detail in the Cisco IOS Image Verification whitepaper. It is included below for completeness.

Built-in Tools
Running the verify command on an IOS device, produces a list of hash values that can be checked against values.
router#verify /ios disk1:s72033-ipservicesk9_wan-mz.122-18.SXF15.bin
%Filesystem does not support verify operations
Verifying file integrity of
Embedded Hash MD5 : 91AEA61961CB042A776860D5F190DF12
Computed Hash MD5 : 91AEA61961CB042A776860D5F190DF12
CCO Hash MD5 : 709685E496E1B27091DE984DD7D78751Signature Verified

A description of each of these hashes is available in the Cisco IOS Image Verification whitepaper.
Embedded Hash: MD5 hash stored by Cisco in a section of the Cisco IOS image file during the image build process; used to verify section integrity for the Cisco IOS software image file. This MD5 hash value is calculated for certain sections of the Cisco IOS image file.
Computed Hash: MD5 hash that the “Image Verification” feature calculates for certain sections of the Cisco IOS software image file when the verify command is executed. This value should be the same as the Embedded Hash to verify section integrity of the Cisco IOS image file. If this value is not equal to the Embedded Hash, the Cisco IOS image file may be corrupted or intentionally altered.
CCO Hash: MD5 hash for the entire Cisco IOS image file. This hash is computed by the verify command and is not stored in the Cisco IOS software image.

The Embedded and Computed hash values must match. The CCO hash must match the MD5 hash value provided for this image on CCO. It is also possible to verify the has provided for the image on CCO against the image stored on disk, by providing the MD5 hash as argument.

router#verify /md5 disk1:s72033-ipservicesk9_wan-mz.122-18.SXF15.bin
Verified (disk1:s72033-ipservicesk9_wan-mz.122-18.SXF15.bin) =
Writing the Core for Analysis
The second method that can be used to verify the integrity of an IOS image, is to write the core to disk for offline analysis. IOS devices can be configured to generate a full copy of its memory (called a core dump) and upload it to a specified location in the event of a crash. Further information on core dumps on IOS devices can be found in the Creating Core Dumps support document.
router(config)#exception core-file ROUTERNAME timestamp compress
router(config)#exception dump
router(config)#exception protocol ftp
router(config)#ip ftp username ftpuser
router(config)#ip ftp password ftppass
router(config)#exception region-size 65536
router(config)#do wr me

An organization’s specific policy may require that the memory contents should not be compressed prior to being sent across the wire. If this is the case, simply remove the compress keyword from the first command listed above. However, making use of the compress greatly speeds-up the transfer.

The command write core results in the IOS device dumping its memory contents to disk and uploading it to a remote host if configured to do so.

Please note that generating a core file will have an impact on a production network; it should only be done in a controlled environment.

router#write core
Remote host []?
Base name of core files to write [RTR]?
Writing RTRiomem_20081006-195646.Z
..output omitted..

Once the output is finished writing to the destination (FTP server in this case), there will be three files, which include the hostname (RTR in this case) and the datestamp:

-rw-r--r-- 28002867 Oct  7 11:00 RTRiomem_20081006-195646.Z
-rw-r--r-- 45724430 Oct  7 11:02 RTR_20081006-195646.Z
-rw-r--r--  1862436 Oct  7 11:03 RTRmore

All three files are compressed with Unix compress, including the last file which doesn’t have a .Z appended:

$ file RTRmore
RTRmore: compress'd data 12 bits
$ file *Z
RTR_20081006-195646.Z:      compress'd data 12 bits
RTRiomem_20081006-195646.Z: compress'd data 12 bits

In order to verify the integrity of the image running on the router, we can extract the text segment from the memory dump, run a cryptographic hash on it, and compare this hash value to that of a hash of the text segment of an image taken in a controlled environment. This implies trust in the memory-dumping process, which may itself be compromised; it is however an initial step.The text segment should be marked RO (read-only) as it contains the instructions to be executed, and these should not be overwritten.

To determine which file corresponds to each portion of the memory output in the show region command, we may look at the core files generated by the write core command, and also compare the file sizes and names with the output of show region:

router# sh region
Region Manager:

      Start         End     Size(b)  Class  Media  Name
 0x08000000  0x0BFFFFFF    67108864  Iomem  R/W    iomem
 0x40000000  0x4BFFFFFF   201326592  Local  R/W    main
 0x40101040  0x42DCFFFF    46985152  IText  R/O    main:text
 0x42DDA370  0x430F534F     3256288  IData  R/W    main:data
 0x430F5350  0x44B156EF    27394976  IBss   R/W    main:bss
 0x44B156F0  0x4BFFFFFF   122595600  Local  R/W    main:heap
 0x50000000  0x5FFF7FFF   268402688  Local  R/W    more heap
 0x80000000  0x8BFFFFFF   201326592  Local  R/W    main:(main_k0)
 0xA0000000  0xABFFFFFF   201326592  Local  R/W    main:(main_k1)


In this example, the file RTR_20081006-195646 corresponds to main memory.

From this output, we know the text segment resides between address 0x40101040 and 0x42DDA370, and is 46985152 bytes in size. Since show region outputs the virtual memory addresses, we need to look at the translation lookaside buffer (TLB) and map to the address in physical memory. The TLB contains the virtual memory to physical memory mappings.

To obtain the TLB, we may issue the show platform tlb command:

router#sh platform  tlb

Mistral revision 5
TLB entries : 45
Virt Address range      Phy Address range      Attributes
0x10000000:0x1001FFFF   0x010000000:0x01001FFFF   CacheMode=2, RW, Valid
0x10020000:0x1003FFFF   0x010020000:0x01003FFFF   CacheMode=2, RW, Valid
0x10040000:0x1005FFFF   0x010040000:0x01005FFFF   CacheMode=2, RW, Valid
0x10060000:0x1007FFFF   0x010060000:0x01007FFFF   CacheMode=2, RW, Valid
0x10080000:0x10087FFF   0x010080000:0x010087FFF   CacheMode=2, RW, Valid
0x10088000:0x1008FFFF   0x010088000:0x01008FFFF   CacheMode=2, RW, Valid
0x18000000:0x1801FFFF   0x010000000:0x01001FFFF   CacheMode=0, RW, Valid
0x19000000:0x1901FFFF   0x010000000:0x01001FFFF   CacheMode=7, RW, Valid
0x1E000000:0x1E1FFFFF   0x01E000000:0x01E1FFFFF   CacheMode=2, RW, Valid
0x1E880000:0x1E899FFF   0x01E880000:0x01E899FFF   CacheMode=2, RW, Valid
0x1FC00000:0x1FC7FFFF   0x01FC00000:0x01FC7FFFF   CacheMode=2, RO, Valid
0x30000000:0x3001FFFF   0x070000000:0x07001FFFF   CacheMode=2, RW, Valid
0x40000000:0x41FFFFFF   0x000000000:0x001FFFFFF   CacheMode=3, RO, Valid
0x42000000:0x427FFFFF   0x002000000:0x0027FFFFF   CacheMode=3, RO, Valid
0x42800000:0x429FFFFF   0x002800000:0x0029FFFFF   CacheMode=3, RO, Valid
0x42A00000:0x42BFFFFF   0x002A00000:0x002BFFFFF   CacheMode=3, RO, Valid
0x42C00000:0x42C7FFFF   0x002C00000:0x002C7FFFF   CacheMode=3, RO, Valid
0x42C80000:0x42CFFFFF   0x002C80000:0x002CFFFFF   CacheMode=3, RO, Valid
0x42D00000:0x42D7FFFF   0x002D00000:0x002D7FFFF   CacheMode=3, RO, Valid
0x42D80000:0x42D9FFFF   0x002D80000:0x002D9FFFF   CacheMode=3, RO, Valid
0x42DA0000:0x42DBFFFF   0x002DA0000:0x002DBFFFF   CacheMode=3, RO, Valid
0x42DC0000:0x42DC7FFF   0x002DC0000:0x002DC7FFF   CacheMode=3, RO, Valid
0x42DC8000:0x42DCFFFF   0x002DC8000:0x002DCFFFF   CacheMode=3, RO, Valid
0x42DD0000:0x42DD7FFF   0x002DD0000:0x002DD7FFF   CacheMode=3, RW, Valid
0x42DD8000:0x42DDFFFF   0x002DD8000:0x002DDFFFF   CacheMode=3, RW, Valid
0x42DE0000:0x42DFFFFF   0x002DE0000:0x002DFFFFF   CacheMode=3, RW, Valid
0x42E00000:0x42FFFFFF   0x002E00000:0x002FFFFFF   CacheMode=3, RW, Valid
0x43000000:0x437FFFFF   0x003000000:0x0037FFFFF   CacheMode=3, RW, Valid
0x43800000:0x43FFFFFF   0x003800000:0x003FFFFFF   CacheMode=3, RW, Valid
0x44000000:0x45FFFFFF   0x004000000:0x005FFFFFF   CacheMode=3, RW, Valid
0x46000000:0x47FFFFFF   0x006000000:0x007FFFFFF   CacheMode=3, RW, Valid
0x48000000:0x49FFFFFF   0x008000000:0x009FFFFFF   CacheMode=3, RW, Valid
0x4A000000:0x4BFFFFFF   0x00A000000:0x00BFFFFFF   CacheMode=3, RW, Valid
0x4C000000:0x4DFFFFFF   0x00C000000:0x00DFFFFFF   CacheMode=3, RW, Valid
0x4E000000:0x4FFFFFFF   0x00E000000:0x00FFFFFFF   CacheMode=3, RW, Valid
0x08000000:0x09FFFFFF   0x00C000000:0x00DFFFFFF   CacheMode=2, RW, Valid
0x0A000000:0x0BFFFFFF   0x00E000000:0x00FFFFFFF   CacheMode=2, RW, Valid
0x50000000:0x51FFFFFF   0x080000000:0x081FFFFFF   CacheMode=3, RW, Valid
0x52000000:0x53FFFFFF   0x082000000:0x083FFFFFF   CacheMode=3, RW, Valid
0x54000000:0x55FFFFFF   0x084000000:0x085FFFFFF   CacheMode=3, RW, Valid
0x56000000:0x57FFFFFF   0x086000000:0x087FFFFFF   CacheMode=3, RW, Valid
0x58000000:0x59FFFFFF   0x088000000:0x089FFFFFF   CacheMode=3, RW, Valid
0x5A000000:0x5BFFFFFF   0x08A000000:0x08BFFFFFF   CacheMode=3, RW, Valid
0x5C000000:0x5DFFFFFF   0x08C000000:0x08DFFFFFF   CacheMode=3, RW, Valid
0x5E000000:0x5FFFFFFF   0x08E000000:0x08FFFFFFF   CacheMode=3, RW, Valid


From the TLB we can see that the translation simply requires changing the 0x4 by 0x0 in calculations. Different tools can be used to extract the text segment from the memory dump, dd is used in this example.

In order to eliminate block errors, we can specify a block size of 1, skip to the beginning of the text segment and provide the value listed under Size(b) in the output to show region as count:

dd if=RTR_20081006-195646 bs=1 skip=1052736 count=46985152 of=RTR_text_segment

We can compare the content present at the beginning and end of the RTR_text_segment with that at the beginning and end of the text segment:

$ xxd RTR_20081006-195646 | grep -i 0101040\:
0101040: 27bd ffe0 afb0 0010 0080 8021 afb1 0014  '..........!....
$ xxd RTR_main_text | head -1
0000000: 27bd ffe0 afb0 0010 0080 8021 afb1 0014  '..........!....
$ xxd RTR_20081006-195646 | grep -i 2dcfff0\:
2dcfff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
$ xxd RTR_main_text | tail -1
2ccefb0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

A cryptographic hash can now be computed on the text segment, to compare with the text segment of a known-good IOS copy.

$ md5sum RTR_main_text
441ec282be815e24c74ac917f3a42fec  RTR_main_text

Perimeter Defense

When designing a layered defense no component exists in a vacuum: verifying the integrity of an IOS image is only one component, configuring AAA and logging on IOS devices, and enabling perimeter defense to record connections destined to router interface IPs, are other essential components that facilitate subsequent forensic investigations and post-mortem analyses.

Tags: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *