Cisco IOS进程调试创建时间:2003-07-31 文章属性:转载 文章提交:freedemon (freedemon_at_citiz.net) Ciscox notes (Anthony C. Zboralski Gaius) Research is being done on a useless Cisco 1600 with 4 megs of flash running IOS 11.1. Recently after writting my first cisco warez (tunnelx), I told myself hey we need to find a way to inject arbitrary code, poke and peek at the memory on a cisco, hide interfaces, route-maps, access-lists. Let's look around: scep#show proc CPU utilization for five seconds: 10%/4%; one minute: 14%; five minutes: 14% PID QTy PC Runtime (ms) Invoked uSecs Stacks TTY Process 1 M* 0 1248 107 11663 2204/4000 1 Virtual Exec 2 Lst 802DF16 34668 313 110760 1760/2000 0 Check heaps 3 Cwe 801D5DE 0 1 0 1736/2000 0 Pool Manager 4 Mst 8058B20 0 2 0 1708/2000 0 Timers 5 Lwe 80BFD4A 24 46 521 1448/2000 0 ARP Input 6 Mwe 81F78F0 4 1 4000 1744/2000 0 SERIAL A'detect 7 Lwe 80D935A 4 1 4000 1656/2000 0 Probe Input 8 Mwe 80D8CD6 0 1 0 1744/2000 0 RARP Input 9 Hwe 80CA966 80 89 898 3116/4000 0 IP Input 10 Mwe 80F41BA 16 322 49 1348/2000 0 TCP Timer 11 Lwe 80F5EB8 8 3 2666 3244/4000 0 TCP Protocols 12 Mwe 813785E 80 177 451 1588/2000 0 CDP Protocol 13 Mwe 80D5770 0 1 0 1620/2000 0 BOOTP Server 14 Mwe 81112C0 1356 1522 890 1592/2000 0 IP Background 15 Lsi 8121298 0 25 0 1792/2000 0 IP Cache Ager 16 Cwe 80237BE 0 1 0 1748/2000 0 Critical Bkgnd 17 Mwe 802365A 12 5 2400 1476/2000 0 Net Background 18 Lwe 804E82E 16 4 4000 1192/2000 0 Logger 19 Msp 80456DE 80 1493 53 1728/2000 0 TTY Background 20 Msp 802345C 20 1494 13 1800/2000 0 Per-Second Jobs 21 Msp 80233F2 68 1494 45 1488/2000 0 Net Periodic 22 Hwe 80234DC 4 1 4000 1724/2000 0 Net Input 23 Msp 8023482 772 25 30880 1800/2000 0 Per-minute Jobs 24 Lwe 8109834 4 2 2000 3620/4000 0 IP SNMP 25 Mwe 815CE08 0 1 0 1712/2000 0 SNMP Traps 26 ME 811805A 0 26 0 1892/2000 0 IP-RT Background 27 ME 803B0F8 32 11 2909 2760/4000 2 Virtual Exec now you can even dump the memory with 'show memory'. Good but there isn't a write memory command, too bad. Maybe not... I started looking for undocumented and hidden commands and found quite a bunch of them. Among all the stupid hidden command, the best candidate for taking full control of the cisco is 'gdb'. The IOS gdb command offers three subcommands: gdb debug PID examine PID kernel the kernel subcommand works only on the console. However 'examine' and 'debug' works perfectly; the debug subcommand is a bit tricky to use though. scep#gdb debug 27 |||| oops.. Ok grab a copy of gdb-4.18 and try to compile a version for your cisco. mkdir m68k-cisco ../configure --target m68k-cisco make if you have a mips based cisco, just s/m68k/mips64/ the above 4 lines. now type make install and you should have a m68-cisco-gdb binary in your path. fire# m68k-cisco-gdb GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu --target=m68k-cisco". (cisco-68k-gdb) my cisco 1600 is connected to /dev/ttyS0, scep>en Password: scep#gdb debug 18 scep# As you can see it bails out if you hit return. while examine works it seems. scep#gdb examine 18 |||| now the console seems locked. go back to our gdb-4.18 source tree and check out gdb/remote.c which contains a nice documentation of the gdb remote communication protocol. added. IOS gdbserver implementation Don't get too excited, IOS gdbserver supports only a limited subset of those commands. I'll grab a binary of IOS 12 and check if new commands were added. I didn't have to test every command by hand.. let's just say I have reliable sources and I know that in IOS 11.2-8 (hum hum), the following commands are supported: Request Packet read registers g write regs GXX..XX Each byte of register data is described by two hex digits. Registers are in the internal order for GDB, and the bytes in a register are in the same order the machine uses. read mem mAA..AA,LLLL AA..AA is address, LLLL is length. write mem MAA..AA,LLLL:XX..XX AA..AA is address, LLLL is number of bytes, XX..XX is data continue cAA.AA AA..AA is address to resume IF AA..AA is omitted resume at same address. step sAA..AA AA..AA is address to resume If AA..AA is omitted, resume at same address. kill request k last signal ? Reply the current reason for stopping. This is the same reply as is generated for step or cont : SAA where AA is the signal number. toggle debug d toggle debug flag (see 386 & 68k stubs) All other commands will be ignored... too bad 'search' isn't implemented. The protocol is simple, quoting remote.c comments: A debug packet whose contents are <data> is encapsulated for transmission in the form. $ <data> # CSUM1 CSUM2 <data> must be ASCII alphanumeric and cannot include characters '$' or '#'. If <data> starts with two characters followed by ':', then the existing stubs interpret this as a sequence number. CSUM1 and CSUM2 are ascii hex representation of an 8-bit checksum of <data>, the most significant nibble is sent first. the hex digits 0-9,a-f are used. Before trying to make gdb work i wrote a little program that computed the right checksum: #include <stdio.h> unsigned char const hexchars[] = "0123456789abcdef"; char tohexchar (unsigned char c) { c &= 0x0f; return(hexchars[c]); } int main(int argc, char **argv) { unsigned char checksum; int count; char *command; char ch; if (argc <= 1) exit(1); printf("gdb protocol command: "); command = argv[1]; putchar ('$'); checksum = count = 0; while ((ch = command[count])) { putchar(ch); checksum += ch; count++; } putchar('#'); putchar(tohexchar(checksum >> 4)); putchar(tohexchar(checksum)); putchar('\n'); } ./gdbproto g gdb protocol command: $g#67 now paste that on the |||| prompt and you get register output: scep#gdb exa 18 ||||+$0*1b20*3320c0490*1920c02440*1080726ce0*e7#14 let's read 4 bytes of mem at 0x804e82e ./gdbproto m804e82e,4 gdb protocol command: $m804e82e,4#9d Trying to read big chunk of mem really tilts and gdb defaults to 4 bytes at a time. You can still dump memory with show memory, which is more efficient. and for patching a bit, efficiency is not an issue. one nop here, one jump here. If you're using minicom, make use ctrl-a W to enable line wrap. scep#gdb exa 18 ||||+$001461ff#f8 Woo it works! Let's try to read in the exec range: $mff,4#99 $04040004#8c Cisco people have a good sense of humour: $m0,5#fe $badadd0104#15 it is not a bad address, it is 0xba 0xda 0xdd. type $c#63 to continue and go back to a sane world. I have was having trouble with gdb.. If you have trouble with the serial connection, you can use the command `set remotedebug'. This makes GDB report on all packets sent back and forth across the serial line to the remote machine. The packet-debugging information is printed on the GDB standard output stream. `set remotedebug off' turns it off, and `show remotedebug' shows you its current state. Says the info documentation for gdb and gives extra hints on the remote gdb protocol. Now it works over the serial, DO NOT use the option -b or set baud in gdb, this is really error prone. Just do the following: (cisco-68k-gdb) target remote /dev/ttyS0 Remote debugging using /dev/ttyS0 warning: Remote reply is of odd length: 0200471c00e4f640ffffffffffffffffffff70000000000000000000006100000000000000000000d200204262008071aaa020bb6bc020bb9d4020c52c5020d21cb020d2120020d211c0000a00808071aae00000000000000000000000000000000000000000000000000000000000000000000000007 0x120020d2 in ?? () (cisco-68k-gdb) scep#show region Region Manager: Start End Size(b) Class Media Name 0x02000000 0x0217FFFF 1572864 Local R/W main 0x02005000 0x02019A43 84548 IData R/W main:data 0x02019A44 0x0203D67B 146488 IBss R/W main:bss 0x0203D67C 0x0217FFFF 1321348 Local R/W main:heap 0x02180000 0x021FFFFF 524288 Iomem R/W iomem 0x0801A1E4 0x082D8813 2876976 IText R/W text scep#show region address 0x804E82E Address 0x0804E82E is located physically in : Name : text Class : IText Media : R/W Start : 0x0801A1E4 End : 0x082D8813 Size : 0x002BE630 (cisco-68k-gdb) set *0x2180000=0 Sending packet: $m2180000,4#28...Ack Packet received: ab1234cd binary downloading NOT suppported by target Sending packet: $M2180000,4:00000000#c2...Ack Packet received: OK show subsys class show subsys name show memory free show memory processes show memory failures alloc No IOS platform built on the M68k family uses versions of the CPU that have full MMU support. Hence there is no hardware support for write protecting the text segment of the IOS image. The system does checksum the text segment (every 30 seconds) and will crash if the checksum is incorrect. However, finding the offending code is hard. mips At init time, the IOS programs the MMU of these processors to provide write protection of the text segment. If any code tries to write into the code space, the system will crash with a segmentation violation. However the protection is not completely foolproof, although very good. The physical memory in which the code sits is mapped into other segments of the address space and is writable through those segments. 206EA78 5124 206D118 206FEA4 1 80353F6 *Hardware IDB* 206FEA4 2200 206EA78 2070764 1 803540C *Software IDB* show chunk 25 chunks created, 3 chunks destroyed 12 siblings created, 2 siblings trimmed Chunk Flags Size(b) Free Max Saved(b) Name 203D6A0 D 16 0 50 1704 List Elements 204379C DS 16 0 50 1704 (sibling) 2043BE4 DS 16 20 50 584 (sibling) Total 20 150 3992 203DAE8 D 48 50 50 - 2696 List Headers 204114C D 16 50 50 - 1096 messages 204B714 D 12 0 100 3504 Reg Function 207B278 DS 12 0 100 3504 (sibling) 207E99C DS 12 0 100 3504 (sibling) 209FB9C DS 12 0 100 3504 (sibling) 20A314C DS 12 0 100 3504 (sibling) 20A4D5C DS 12 0 100 3504 (sibling) 20B5ED4 DS 12 0 100 3504 (sibling) 20B879C DS 12 0 100 3504 (sibling) 20B9064 DS 12 29 100 1996 (sibling) 206194C 32 200 200 - 7296 IDB SB Chunks 20635CC 68 200 200 - 14496 IDB List Header Chunks 2066E6C 24 898 900 - 25168 IDB List Element Chunks 206D13C 28 200 200 - 6496 IDB Notification Chunks 20A2178 D 24 49 50 - 1432 IP Addresses 20A5EE4 D 48 99 100 - 5208 IP RDB Chunk 20C24F8 D 3980 3 4 - 12012 Parseinfo Blocks 20C6398 D 836 21 21 - 17736 Parse Nodes * syntax: capture dump interface <interface> <tftp server> <file name> * * descr: This command dumps the captured packets into the specified * tftp server. EOLNS (capture_dump_cmds_eol, capture_dump_commands); STRING (capture_dump_fname, capture_dump_cmds_eol, no_alt, OBJ(string,1), "File name into which to dump"); IPADDR_NAME (capture_dump_tftp_svr, capture_dump_fname, no_alt, OBJ(paddr,1), "Name or address of TFTP server to dump onto"); INTERFACE (capture_dump_get_interf, capture_dump_tftp_svr, no_alt, OBJ(idb,1), IFTYPE_CAPTURE); KEYWORD (capture_dump_interfaces, capture_dump_get_interf, no_alt, common_str_interface, "interface in capture dumping mode", PRIV_USER); KEYWORD (capture_dump_cmds, capture_dump_interfaces, no_alt, "dump", "write captured info to a TFTP server", PRIV_USER); KEYWORD (exec_capture_dump_tftp, capture_dump_cmds, no_alt, "capture", "commands for the capturing facility", PRIV_ROOT); |