Title: Killing the Myth of IOS rootkits: DIK, Da IOS rookit
1Killing the myth of Cisco IOS rootkits DIK(Da
Ios rootKit)?
Sebastian 'topo' Muñiz EuSecWest London, May
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
sebastianmuniz_at_gmail.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 rootkit?
- 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 low-level OS
functions and manipulating internal structures.
5- Rootkits along history
- Existed on other OSes 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 versions? Yes - Does it matter if they have different arch (MIPS
or PowerPC)? No - Do I need to know assembly code for a specific
arch? No, just plain C )
7- Consequences
- Imagine your companys 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) process queue.
- This model reduces local security and system
stability. - Completely different to modern OSes.
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). - Lots 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.5x)?
11ELF structure as IOS image
ELF header
SFX code
MAGIC (0xFEEDFACE)
Compressed image length
Compressed image checksum
Uncompressed image checksum
Uncompressed image length
Compressed Image
Self de-compressing code
Magic Structure
Compressed IOS image
12- ELF structure as IOS image (cont.)?
- SFX code uses Magic Structure along the entire
decompression process. - Values in Magic Structure are employed to
validate decompression result. - Length values in Magic Structure are expressed
in words (4 bytes)? - Ex. Length of 1024 words 4096 (1024 4)
bytes - Length values help to verify available memory
and size of buffer to checksum. - Images checksum is calculated before and after
decompression.
13- ELF structure as IOS image (cont.)?
- Simple (insecure) 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, the resulting
(uncompressed) image will end up running on the
devices memory. - This image will contain our rootkit.
- It's needed for analysis, so download using the
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 workings of the
OS. - Take advantage of debug strings info to locate
functions of interest to 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
- Parts of the IOS image were not analyzed
correctly. - 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 over 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 over every DATA section (like .data)?
- Strings where (0 ! length mod 4) are padded
with null bytes. - 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 beginning
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 (0x09), CR (0x0a) and LF
(0x0d). - Bytes with values within CODE section ranges
may be pointers. - What if both happens? Like in a CODE section from
0x61000000 to 0x61700000? - Is 0x61616120 (AAA ) a pointer or just the
beginning 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 results of key
functions. - Some of them are usually displayed as output.
- By locating their references, we locate those
functions. - Iterate over every string to locate those of
interest to an attacker. - For each one, use IDAs string XREF property to
identify it's callers (IDA-Python magic again )?
25- Locating low-level IOS functions (cont.)?
- What if a function does not use any string?
- Functions are compiled in the same order as
source file. - Other functions (neighbours) next to it will
surely do (whether other IOS function call them
or not). - Apply this procedure to every function that we
want to find using simple IDA-Python functions.
26- A home for the rootkits code
- IOS contains lots 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 counterparts to IOS functions
that do attacker's will. - Recompiling the rootkit code every time is not
an option. - Cross-compile it once (for MIPS and PowerPC).
- How to locate offsets of compiled counterpart
functions? - Use 'objdump' to obtain symbolic info and
offsets. - Name of a counterpart function resolves to it's
offset in compiled code.
28- Redirect IOS execution flow
- Knowing offsets of counterpart functions means
that they are callable now. - Intercept IOS functions and redirect their
execution flow. - Hook every interesting IOS function with a
trampoline code. - Trampoline code is placed at functions first
instruction. - Jumps to the location of rootkit code 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- Glueing all together
- Save the return address
- Store the function parameters currently
allocated - Allocate stack space for extra parameter needed
by rootkit code. - Call the rootkits plain C code.
- Decide whether flow should continue or not to
the hooked function. - If it should restore original parameters,
execute instruction at trampoline address and
jump after trampoline - If it should go back to caller, set extra
parameter value as the hooked functions return
value and go to the saved return address.
31Glueing all together
chk_pass_DIK()
Glue code
IOS caller
r chk_pass(p) if (r true) login()
else deny_login()
- add stack
- store parents RA
- store params p
- create param i
- o chk_pass_DIK(p)
- fix stack
- if (o CONT)
- execute orig inst
- return params p
- cont chk_pass_IOS
- else
- r i
- jump to RA
-
if (p 1337) i true return RET else
return CONT
chk_pass()
trampoline chk_pass code return (value)
32- Advantages of this method
- A few lines of shellcode called trampoline and
glue code bridge the gap between a compiled C
function 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).
33- Limitations of C code
- Strings are put in another DATA section.
- All code together is needed.
- Code must be PIC (Position Independent Code).
- Only relevant code to rootkit is needed.
34- 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
35- 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
36- IOS functions for rootkit usage
- Not only able to intercept low-level functions.
- Obtain addresses of other IOS functions.
- Use them as function pointers.
- Enhance rootkit functionality using them inside
our code. - Increase rootkits stealthness level.
37- IOS functions for rootkit usage (cont.)?
- Implement tables of function/structure pointers.
- Call functions as tables indexes.
- Pointers to internal structures, too.
38- 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 rockn'roll )?
39- Simple runtime patching
- GDB inside every image.
- GDB can read/write 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.
40- 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.
41- Countermeasures
- Follow Cisco guidelines.
- Periodically checksum images using MD5, SHA1,
etc. to see binary changes!!! - Try CIR (Cisco Incident Response) from
Recurity-Lab to detect anomalies. - Harden network infrastructure.
42 DEMO