Title: Bughunting
1Killing the myth of Cisco IOS rootkits DIK(Da
Ios rootKit)?
Sebastian 'topo' Muñiz EuSecWest London, March
2008
2 Speaker info Name Sebastian 'topo' Muñiz Work
Sr. Exploit Writer at CORE Likes Reverse
Engineering Vuln Research Contact
topo_at_coresecurity.com
3- Agenda
- Introduction
- IOS characteristics and internal structure
- IOS file format structure
- IOS analysis phase
- Binary patching technique
- Rootkit source code advantages and limitations
- Setting image ready
- Countermeasures
4- What is a rootkits?
- A program that seizes control of the entire OS
by hiding files, processes, network connections
and everything else. - Allows unauthorized users to act as with super
user privileges (in IOS this means level 15, like
root in Linux). - Stealth hides attacker's presence indefinitely.
- This is achieved by intercepting OS low level
functions and manipulating internal structures.
5- Rootkits along history
- Existed on other OS's like Windows, Unix and
Linux distros for several years. - Natural evolution of backdoors.
- Present in AV virii race to avoid one to
locate each other. - More common now a days, specially in malware.
6- Rootkits on IOS
- Are IOS rootkits new? No
- Did it begin years ago? Yes, before stolen IOS
source code. - Any publicly known IOS rootkit? No, until today.
- Can a generic rootkit be created for multiple
IOS version? Yes - Does it matter if they have different arch (MIPS
or PowerPC)? No - Do I need to know a specific assembly code? No,
just plain C )
7- Consequences
- Image your company network (ISP, bank, .gov or
whoever you are) compromised on strategic points. - Network traffic concentrators owned by the
attacker. - Attackers able to see and manipulate all network
traffic. - Consequences in one word Disastrous.
8- Introduction to IOS architecture
- Monolithic architecture which runs as a single
image. - All processes have access to each others memory.
- No memory protection between processes.
- Uses 'run to completion' priority scheduling.
- FIFO (First In First Out) processes queue.
- This model reduces local security and system
stability. - Completely different to modern OS's.
9- IOS image file format
- Modern Cisco devices use ELF (Extensible File
Format). - It's a standard file format on Linux.
- File contains CODE segments (instructions) and
DATA segments (strings). - Lot's of information available about it on the
net. - Why ELF as IOS format? Implementations
available, relocatable, etc. - Values on IOS ELF headers are not equal to the
standards. - ELF infection methods (binary modification) were
well known by virus writers for years.
10- Initial setup on memory
- Bootloader performs POST and invokes IOS image.
- Downloaded image is not really the image that
runs IOS. - Image contains a self decompressing (SFX) header
code that unpacks the fully functional IOS. - A simple ZIP utility can decompress it.
- It's compressed because it contains lots of
strings that occupy precious memory. - c2600-i-mz.123-24 occupies 7.4MB -gt18.6 MB
Decomp (2.51)?
11ELF structure as IOS image ----------------------
-------- ELF header
------------------------------ SFX
code Self decompressing
code ------------------------------ --
Magic (0xFEEDFACE) ------------------
------------ Compressed image length
------------------------------
Magic Compressed image checksum
Structure ------------------------------
Uncompressed image checksum
------------------------------
Uncompressed image length
------------------------------ --
Compressed image Compressed IOS
image ------------------------------
12- ELF structure as IOS image (cont.)?
- SFX code uses Magic structure along the entire
decompression process. - Magic values are employed to validate
decompression result. - Magic structure length are expressed in words (4
bytes)? - Ex. Length of 1024 words 4096 (1024 4)
bytes - Magic length values help to verify available
memory and size of buffer to checksum. - Image is checksummed before and after
decompression.
13- ELF structure as IOS image (cont.)?
- Simple (unsecure) checksum algorithm
- int nwords compressed_size / sizeof(ulong)
- unsigned long sum 0 // contains the
checksum result - unsigned long val 0 // temporary value
- unsigned char bufp (uchar) ptrData //
pointer to - // data to verify
- while (nwords--) // Read every 4 bytes
- val bufp
- sum val
- if (sum lt val) // There was a carry
- sum
-
14- Obtain IOS image file
- If decompression was successful, resulting
(uncompressed) will be running on device memory. - This image will contain our rootkit.
- It's needed for analysis, so download using the
known CLI's copy command (from flash to ftp or
any another destination)? - Unzip the compressed (downloaded) image with
ZIP. - With the decompressed image in our hands, move
to analysis phase.
15- Analysis phase
- Why?
- What tool should we use?
- Why IDA (Interactive Disassembler Debugger) ?
16- Analysis phase (cont.)
- IOS image contains lots of debug strings with
information about the internal OS working. - Take advantage of debug strings info to locate
interesting functions for an attacker. - Feed IDA with the uncompressed IOS image (will
throw warnings)? - Come back several minutes (sometimes hours)
later )?
17- Analysis phase (cont.)?
- IDA will do a good job, but not enough.
- Several functions and string won't be recognized
- Part of the IOS image was not correctly
analyzed. - On a c2600-i-mz.123-24 IDA detected
- 28121 Functions
- 126379 Strings
- An enhanced analysis is needed.
18- Enhanced image analysis
- Let's use IDA-Python (python support for IDA
scripting). - Create a script to detect remaining functions
and strings. - Remember that MIPS and PowerPC instructions are
aligned to a 4 byte boundary. - Fixed instruction size of 4 bytes.
19- Enhanced image analysis for functions
- Iterate on every CODE section (like .text)?
- Compiler writes one function after another.
- Strings are not inlined in CODE sections.
- Move on a 4 byte boundary and tell IDA to create
functions. - Rely on IDA magic.
20- Enhanced image analysis for strings
- Iterate on every DATA section (like .data)?
- Strings length not 4 byte modulo are padded with
zeros. - DATA segments may include references to other
sections. - Move on a 4 byte boundary and analyse the memory
content. - Try to resolve if current value is the begin of
a string or a pointer to another location
(instruction or string).
21- Enhanced image analysis for strings (cont.)?
- TIPS
- Printable chars (between 0x20 and 0x7f) are
probably strings. - Also check for Tab (0xD), CR (0xA) and LF
('0xD'). - Bytes with values between CODE sections range
may be pointers. - What if both happens? Like in a CODE section
from 0x61000000 to 0x61700000? - Is 0x61616120 (AAA ) a pointer or just the
begin of a string from the AAA subsystem?
22- Enhanced image analysis results
- After enhanced analysis
- 46296 Functions (18175 new functions)?
- 143603 Strings (17224 new strings)?
- IOS image is now successfully analysed and ready
to give us info.
23- Locating low-level IOS functions
- Locate functions of interest for the attacker
like - Password checking.
- File manipulation.
- Logging information.
- Packet handling functions.
- Access lists manipulation function.
24- Locating low-level IOS functions (cont.)?
- Strings are used to diagnose key functions
result. - Some of them are usually displayed as output.
- Locating their references, we locate those
functions. - Iterate through every string to locate the ones
of attacker interest. - For each one, use string XREF property from IDA
to know it's callers (IDA-Python magic again )?
25- Locating low-level IOS functions (cont.)?
- What if function does not use strings?
- Functions are compiled in the same order as
source file. - Other functions (neighbors) next to it will
surely do (whether other IOS function call them
or not). - Apply this procedure to every function that we
want to fin using simple IDA-Python functions.
26- Rootkit code home
- IOS contains lot's of debug strings.
- Sacrifice one large (probably never used) string
to put code. - Also another CODE section could be added (known
ELF infection technique). - String overwrite is the easier to implement.
- Remember to change section's permissions on ELF
section header.
27- Analyze low-level functions
- Rootkit contains IOS functions counterpart that
do attacker's will. - Recompile rootkit code every time is not an
option. - Cross-compile it once (for MIPS and PowerPC).
- How to locate compiled counterpart functions
offsets? - Use 'objdump' to obtains symbolic info and
offsets. - Name of a counterpart functions resolves to it's
offset in compiled code.
28- Redirect IOS execution flow
- Knowing counterpart function offsets means that
they are callable now. - Intercept IOS functions and redirect it's
execution flow. - Hook every interesting IOS function with a
'trampoline' code. - Trampoline code is located at function first
instruction. - Jump to rootkit code location in memory
(sacrificed string). - Trampoline code (like jmp on x86) for
- PowerPC -gt unconditional branch instruction (1
inst.)? - MIPS -gt unconditional jump instruction
(2 inst.)?
29- Redirect IOS execution flow (cont.)?
- Can I just jump to compiled C code? No, bad boy,
you can't. - A 'glue' code is needed to create a bridge
between IOS assembly code and plain C code. - The glue code should work either on MIPS or
PowerPC. - Redirection must occur without crashing current
process state.
30- Gluing all together
- Save the return address
- Store the function parameters currently
allocated - Allocate stack space for extra parameter needed
by rootkit code. - Call the rootkit plain C code.
- Decide whether to continue or not to hooked
function. - If it continues, restore original parameters,
execute instruction at trampoline address and
jump after trampoline - If it goes back to caller, set extra parameter
value as hooked function return value and go the
saved return address.
31Glueing all together (cont.)? IOS caller
chk_pass_IOS(p) -----------------
-----------------
rchk_pass(p) ---gt trampoline
--gt
if r true rest of code
login() ... else
return legal_res deny_login()
...
----------------- -----------------
32Glueing all together (cont.)? Glue code
chk_pass_DIK(p,i)? ---------------------
- ----------------- store parent RA
--gt if p 'l337' store params p
i true create param i
- return RET add stack
else o
chk_pass_DIK(p,i)- - return CONT fix
stack if o
CONT lt-- exec
orig instruct -----------------
return params p cont chk_pass_IOS
else r i
jump to RA ----------------------
33Glueing all together (cont.)? IOS caller
chk_pass_IOS(p) -----------------
-----------------
rchk_pass(p) trampoline
if r true lt- rest of code
login() ... else
- return legal_res deny_login()
...
----------------- -----------------
----lt-------lt-----------lt--
34- Advantages of this method
- A few lines of shellcode called 'trampoline' and
'glue' code filled the gap between a C function
compiled and existing IOS code. - Only one C code is maintained instead of two
assembly codes that perform the same actions on
different architectures (a MIPS code and a
PowerPC code).
35- Limitation of C code
- Strings are put in another a DATA section.
- All code together is needed.
- Code must be PIC (Position independent Code).
- Only relevant code to rootkit is needed.
36- Workaround the Limitations
- Strings are declared with a MACRO like this
- char pszPassword(void) // String pointer
name -
- jump_to_next_inst
- var ret_addr // prev inst
address - var after function's end // string begins
there - return var
-
- asm(".ascii \"my backdoor password\")
- asm(".byte 0") // NULL terminator
37- Workaround the Limitations
- Set 'flags' in C code to mark rootkit code
region - define BOF_DIK_CODE asm(".ascii \"BOF_\"")?
- define EOF_DIK_CODE asm(".ascii \"EOF_\"")?
- Find those markers on generated code
- BOF_ 0x424f465f
- EOF_ 0x454f465f
38- IOS functions for rootkit usage
- Not only intercept low-level functions.
- Obtain other IOS functions addresses.
- Use them as functions pointers.
- Enhance rootkit functionality using them inside
our code. - Raise rootkit stealth level of the rootkit.
39- IOS functions for rootkit usage (cont.)?
- Implement functions/structures pointer table.
- Call functions as tables indexes.
- Pointers to internal structures, too.
40- Putting it all together
- Dump modified IDA sections.
- Merge changed bytes with original decompressed
IOS image on disk. - Compress using Zlib / ZIP.
- Calculate new checksums.
- Merge with compressed IOS image.
- Ready to rock n' roll )?
41- Simple runtime patching
- GDB inside every image.
- GDB can read/writer memory and processor
registers. - Debugging one process can write entire memory.
- Entire system compromised by simple process
debug. - Use TCL to automate local GDB usage and
self-patching after every boot. - This TCL file will be hidden by the rootkit once
it's running.
42- Resulting IOS image
- Binary patched IOS image.
- No new processes created (show proc won't
help). - Rootkit code execution is triggered by events.
- Cannot trust router info if it's compromised.
- Only external clean up methods will work.
43- Countermeasures
- Follow Cisco guidelines.
- Periodically cheksum images using MD5, SHA1,
etc. to see binary changes!!! - Try CIR (Cisco Incident Response) from
Recurity-Labs - Harden network infrastructure.
44 DEMO