UT Shield

UT Austin Information Security Office

The University of Texas at Austin

securus // vigilare // insanus

September 12, 2016, Filed Under: Uncategorized

Analysis of False/Morel

Introduction

About a month ago, a group called the Shadow Brokers claimed to have stolen a number of cyber espionage tools from the Equation Group. They made a number of the files available to prove the validity of their claim and are attempting to auction the remaining tools. Since then, a number of researchers have analyzed the files and determined that a number of zero day vulnerabilities could be exploited by some of the tools. A summary of some of the research results can be seen here.

This blog post provides an analysis of a pair of executables located in the TOOLS directory: false.exe and morel.exe. The executables appear to be complimentary because a single documentation file within the free file dump explains how to use both executables. false.exe appears to be an executable that can be used to gather information and morel.exe allows the end user to send commands to the remote device.

Please note: I don’t have access to a Cisco Pix, so I wasn’t able to verify the use of either executable using a Cisco device. Instead, I tried to develop a server (in python) that would simulate a Cisco device. During the analysis of the executables, it became pretty clear that the network traffic between the Pix and the client executables was encrypted. I was able to use WinDbg and IDA Pro to reverse engineer the encryption algorithm that was used to communicate with morel.exe. What follows are the results of the analysis.

Documentation

Some documentation for the pair of executables is provided in SCRIPTS/FalseMorel.txt of the Shadow Broker free tar file. The documentation includes the following at the top of the file:

  1. Allows deduction of enable password from data freely offered by the firewall.
  2. Allows privileged level access, knowing only the hash of the enable password.

Although the documentation states that the enable password can be deduced from data offered by the firewall, the documentation does not describe how to deduce the password or how the data is obtained. I’ll talk about this a little later in this post.

The documentation also states that privileged level access is possible if the hash of the enable password is known.  However, it does not describe how to obtain the hash of the enable password. Since the enable password hash is passed to morel.exe as a command line parameter, the documentation implies that morel.exe is the program that can be used to gain privileged level access to the device.

Finally, the documentation implies that a vulnerable device must accept connections on TCP port 1467. I wasn’t able to find any documentation about this port, so I’m not sure if a Cisco device must be configured to run a specific service in order for the Pix to accept connections on this port. The python server that I wrote uses port 1467 as the listening port even though I wasn’t able to determine why a Cisco device would be listening on this port.

false.exe

false.exe requires an ip address and port as arguments. For example, the command shown below can be used to run false.exe with a target host at IP address 192.168.1.1 and a target TCP port of 1467:

false.exe 192.168.1.1 1467

When the above command is executed, false.exe connects to port 1467, reads the packet payload that is sent by the Cisco device, and then closes the TCP connection. It then repeats this two more times (connects to port 1467, reads packet, then closes TCP connection). The payload is printed to the console in hex format. The help documentation for the executable implies that the enable password will be available in the payload that is read, although I have no way of verifying this. The documentation file does not go into detail about how to determine where the enable password is located within the payload from the 3 TCP sessions.

The figure below shows a packet capture of the traffic generated by false.exe. The target host was running a python script to simulate a Cisco device with a service listening on TCP port 1467. The host at IP address 192.168.1.3 is the host running false.exe, and IP address 192.168.1.1 is the host that simulates the Cisco device. Note that there are three separate TCP sessions in the packet capture. If you look closely, you’ll also see data being sent from the simulated Cisco device, but no data being sent from the host running false.exe.

Packet capture produced by running false.exe
Packet capture produced by running false.exe

false.exe displays the information received from the TCP sessions in hexadecimal format, as shown in the figure below.

Output of false.exe
Output of false.exe

Since false.exe appears to be the information gathering program of the pair, the information provided by the Cisco device may be the information required to “deduce” the enable password. However, since I don’t have access to a Cisco Pix, I wasn’t able to get much further in the analysis of how false.exe could be used to deduce the password.

morel.exe

If the end user knows the enable password hash of the Cisco device, he/she can use morel.exe to gain privileged access to the device. An example usage of morel.exe is shown below:

morel.exe -d 500 enable_hash 192.168.1.1 1467

morel.exe basically creates a command shell. It decrypts the payload received from the Cisco device, and allows the end user to type in a plain text command. The command input by the end user is then encrypted using the same algorithm that was used to decrypt the payload received from the remote device. The enable password hash is required because it is used to encrypt the traffic between the Cisco device and the morel.exe client.

The enable password hash must be 16 bytes in length. If not, morel.exe will display a cryptic error message.

morel.exe encryption

When morel.exe is executed, the Cisco device responds with a payload in the following format:

| 4 byte header | 4 byte seed | 4 byte payload length | encrypted payload |

The 4 byte header can be further broken down as shown below:

| 0xc0 | 0x00 | seq number | 0x00 |

Note that the values at offsets 0, 1, and 3 appear to be hard coded values. The value at offset 2 is a sequence number. If the entire encrypted payload cannot fit into a single packet, the seq number appears to be incremented in each packet.

When the packet is received by the client running morel.exe, the following steps are performed to decrypt the payload:

  • A 22 byte plaintext string is created by concatenating the following:

4 byte seed + 16 byte enable password hash + 0xc0 +  1 byte sequence number

  • The md5 hash is computed on the above string
  • Each byte in the payload is xor’ed with the computed MD5 hash:

plaintext[0] = encrypted_payload[0] ^ md5[0]
plaintext[1] = encrypted_payload[1] ^ md5[1] 
plaintext[2] = encrypted_payload[2] ^ md5[2]
…
plaintext[15] = encrypted_payload[15] ^ md5[15]

  • If the payload is longer than 16 bytes, the MD5 hash that is used to compute the next 16 bytes is recomputed using the following string:

4 byte seed + 16 byte enable password hash + 0xc0 + 1 byte sequence number + md5 hash used to encrypt/decrypt previous block

Running morel.exe

The python script that was used to simulate a Cisco Pix was configured to use an enabled password hash of “abcdabcdabcdabcd”, a seed value of “seed”, and to send a command prompt of cisco pix> to the morel.exe client. The packet capture below shows the encrypted payload sent by the python script. Note that the string “cisco pix>” does not appear in the payload.

Encrypted payload sent by python script
Encrypted payload sent by python script

Even though the payload was encrypted, the command window used to run morel.exe shows the decrypted prompt, cisco pix>.

Morel prompt on client
Morel prompt on client

The command “sho ver” was typed as a command at the cisco pix> prompt. After the command was entered, seven ^ symbols were displayed, one at a time. For some reason, each letter in the command was transmitted in a separate network packet. The ^ symbol was displayed as the packets were transmitted. Note that there were eight network packets transmitted because a newline character was sent in addition to the seven letters in “sho ver”.

Once the command completes, the python server resends the “cisco pix>” prompt, and the prompt is displayed on the client. Presumably, if connected to an actual Cisco device, the Cisco device would execute the command and transmit a response to the client. morel.exe would then decrypt the response and display it.

Display after inputting "sho ver" command
Display after inputting “sho ver” command
Seven network packets needed to transmit "sho ver" command
Eight network packets needed to transmit “sho ver” command

Each of the network packets sent by morel.exe contains 13 bytes of data. Recall from the section above describing morel’s encryption that a 4 byte header + a 4 byte seed + 4 byte payload length was sent in addition to the encrypted payload. Therefore, each packet contains 13 bytes. Although no figure is provided, the 1 byte payload sent in each packet was encrypted.

The script that simulates the Cisco device will echo the decrypted command once it receives a newline character. The output after receiving the “sho ver” command is shown below.

Server output after receiving "sho ver" command
Server output after receiving “sho ver” command

One final curious thing about morel.exe: when trying to send the full Cisco command “show version” an error occurred. So, there may be some sort of limit to the length of commands that can be sent with this executable.

Revisiting the Information Provided By false.exe

Recall that the encryption algorithm computes the MD5 hash of the following string:

4 byte seed + 16 byte enable password hash + 0xc0 + 1 byte sequence number

The seed value occupies the 4 bytes starting at offset 4 of the initial payload received from the server. This seed is probably randomly generated each time a TCP session is established. The hash of this string is then used as a byte stream to encrypt the payload sent to and from the server.

If the seed is randomly generated, it may offer a clue as to why false.exe creates 3 separate TCP sessions and dumps the output for each session. The payload that is received by false.exe is described as a “banner” in the FalseMorel documentation. The “banner” is probably the same for each TCP session that is established with the Cisco device. But, if a different seed is used for each TCP session, the encrypted payload will be different for each session. At this point, we have the same payload encrypted using three different keys. We know the seed and the sequence number used to generate the key because they are provided unencrypted as part of the payload. But, we do not know the enable password hash because it is not transmitted.

Unfortunately, I’m not an expert in crypto attacks, so at this point I’m a bit stumped. I’m not sure if its possible to use this information, along with knowledge of the encryption algorithm to deduce anything meaningful from the data produced by false,exe.

Conclusion

Since I don’t have access to a Cisco Pix, there are a lot of holes in the analysis of these two executables. However, since a python script could be used to communicate with morel.exe, it looks like at least the algorithm used to encrypt traffic generated by this service has been deciphered. A copy of the script that was used is shown in the figures below.

 

Python Server Script Part 1
Python Server Script Part 1
Python Server Script Part 2
Python Server Script Part 2

 

July 21, 2016, Filed Under: Uncategorized

Using NodeJS To Deobfuscate Malicious JavaScript

Introduction

A group of analysts in the office are spending some time reverse engineering an Angler sample found at http://malware-traffic-analysis.net/2016/03/02/index2.html. The website shows a screen capture of the malicious javascript that was injected into a page served by a compromised website. I had recently started using Node JS to try to setup some test suites for some client scripts and started wondering if this might be useful for deobfuscating malicious JavaScript.

Before describing the steps I took to deobfuscate the malicious script, a word of warning. When you run a Node JS application, you’re no longer running an application in a web browser environment. It is just like any other command line application. Since there are Node modules that can be used to access files on your computer and perform network communications, you may accidentally damage your own files or attack other computers by running the script. So, I always use a virtual machine on a host only network when analyzing the malicious code. Since we’re only interested in deobfuscating the malicious script, there is no need to try to observe what the script will actually do once it has been deobfuscated.

Virtual Environment

I have Node JS installed on an Ubuntu virtual machine. I also have the python js-beautify package installed. The js-beautify script will parse a javascript file that is combined into a single line, and create a line-by-line, indented representation of the script. The only way to set a breakpoint in the Node JS debugger is by line number, so if you want to step through the code line by line, parsing the obfuscated single line script into a multiline script will be very helpful.

Deobfuscation

The first step is to extract the javascript from between the script tags. A screenshot of the original, obfuscated code is shown in the figure below. The code that was extracted is highlighted. The code was copied into a file called minified.js.

Original obfuscated javascript, including tags
Original obfuscated javascript, including tags

Next, the command shown below was used to parse the single line into a multiline script:

js-beautify minified.js > obfuscated.js

The contents of obfuscated.js are shown below.

Malicious javascript parsed into multiline script
Malicious javascript parsed into multiline script

Next, there is a nested function call on line 8 of the script. Since a nested function call is equivalent to multiple function calls on a single line, you may have problems single-stepping through this line in a debugger. The easiest way to unnest the calls is to assign the return value of the inner eval() function to a variable. The variable can then be passed to the second eval() function.

But, what are the two eval() function calls doing? The inner eval() function call is probably deobfuscating the weird looking long string stored in the variable fnefybka on line 3 of the script. Once the inner eval() deobfuscates this string, the outer eval() is going to execute the deobfuscated string as if it were a piece of javascript.

So, to prevent the malicious code from being executed, I replaced the outer eval() function call with a call to console.log(). The edited script is shown below:

Unnesting the calls to eval()
Unnesting the calls to eval()

At this point, I ran the command shown below to output the contents of the deobfuscated string variable to a file:

nodejs obfuscated.js > deobfuscated.js

Deobfuscated string variable
Deobfuscated string variable

The contents of deobfuscated.js are also on a single line, so its a little hard to tell what’s going on. Once again, we can use the js-beautify command to fix this:

js-beautify deobfuscated.js > pretty.js

Deobfuscated multiline script
Deobfuscated multiline script

The screenshot above shows a multiline script that is now much easier to decipher. We can see an iframe with a URL that contains the word “helloresearcher” being inserted into the document towards the end of the script. The “helloresearcher” string is shown in a pcap at the Malware Analysis Traffic link in the introduction to this post.

Debugging With Node JS

In the section above, we used Node JS to execute the obfuscated java script after we made some edits to the script. However, if you would like to step through the script one line at a time, you can use the Node JS debugger to do so. The debugger can also be used to examine the values stored in different variables in the script as you are stepping through the script. To use the debugger, add the line debugger; at the point where you would like to pause execution in the script:

debugger statement added to pause script execution
debugger statement added to pause script execution

Next, type the following command to debug the script:

nodejs debug obfuscated.js

At this point you should see a debug> prompt, as well as a few lines from the script. Type c to continue executing the script, and execution should pause at the debugger statement.

Node JS paused at debugger statement
Node JS paused at debugger statement

Suppose I’m interested in the value of the zeeeafkz variable at this point in the script. We can use the debugger to display the value. The Node JS debugger is a little odd in that you can step through the script one line at a time by entering commands at the debug prompt. But, you need to open another shell within the debugger to view variables. To open the second shell, type repl. Once we’re in the repl shell, we can use the console.log() function to display the contents of the variable as shown below.   

Displaying a variable's value in the Node JS debugger
Displaying a variable’s value in the Node JS debugger

The for loop has somehow transformed the lengthy string stored in the variable fnefybka into a string that is now a list of integers. The remainder of the script finishes transforming this data into a string that can be fed to eval().

To exit the repl shell, type Ctrl + C, and you will be returned to the debugger shell. This should return you to the debug prompt, where you can start stepping through the script. Documentation for the Node debugger is available here.

 

 

July 8, 2016, Filed Under: Uncategorized

Reverse Engineering a Malicious MS Word Document

Introduction

This blog post analyzes a Word document that was used to deliver a ransomware executable. The Word document includes a macro that will execute when the document is opened if the end user clicks a button called “enable content”. If the macro runs, a ransomware executable is downloaded from a malicious website and executed on the computer. The ransomware encrypts documents on the victim computer and demands payment for the encryption key that is needed to decrypt the files.

The analysis was performed on a virtual machine running Windows 7 on an isolated, host only network. The virtual machine did not have access to the public internet during the analysis, so the ransomware could not be downloaded. Microsoft Office 2016 was installed on the virtual machine.

One again, please note that if macros are not enabled to run automatically, the end user must click on a button to run the macro. The figure below shows the button that must be clicked to run the macro after opening the malicious document. If the end-user does not click this button, he/she will not get infected with the ransomware.

Enable Content button to run macros
Enable Content button to run macros

Some Prep Work

For some reason, I wasn’t able to use the Microsoft Word’s built in debugger to step through the macros in the malicious document without clicking the Enable Content button, so I had to make some edits to the macros before starting the analysis. I’m not very familiar with VBA development, so there may be an easier way to analyze this sort of malicious document.  However, I’ll describe the steps I used.

First, I clicked on the View tab, and then clicked on the Macros icon, then clicked on View Macros. MS Word will display a dialog box with the different macros that are available.

Macros Dialog Box
Macros Dialog Box

The autoopen macro is a special macro that is executed when the document is opened. I selected this macro, then clicked Edit. Word then displayed a window with the macro’s definition.

autoopen macro
autoopen macro

I renamed the macro to autoopen2 and clicked on the Save icon. Renaming the macro will prevent it from running even if the Enable Content button is clicked. After making this edit, we can close the window that displays the macros, so that the main Word document window is displayed.

Rename autoopen macro to autoopen2
Rename autoopen macro to autoopen2

After clicking on the Enable Content button, nothing should happen because there is no longer an autoopen function.  We should be ready to start stepping through the macros.

General Info About Debugging VBA Macros

Once again, we’ll need to click on View Macros to display the Macros dialog box. After selecting autoopen2, click on Step Into instead of Edit. Execution of the macro should pause at the beginning of the autoopen2 function. This function will be highlighted in yellow with a yellow arrow next to it. Several other windows with macro code will also be present. The windows have names in their title bars that look like Module 1, Module 4, …

Paused at the beginning of autoopen2 function
Paused at the beginning of autoopen2 function

To start debugging the macros, I chose to display the debug toolbar. The toolbar can be displayed by selecting View -> Toolbars -> Debug. The toolbar contains icons for stepping into and over lines of code, and continuing code execution (if breakpoints are set). Breakpoints can be set by clicking in the grey column to the left of a macro line.

The debug toolbar also contains an icon for opening a watch window. The watch window can be used to inspect the state of a variable. The malicious macros in this document store deobfuscated information in global variables. The deobfuscated information is used in later macros to download and execute ransomware from the malicious website. If you click on the Watch Window icon, the watch window will be displayed on the bottom of the macros window. To add a variable to the watch window, right-click anywhere in the watch window, and select Add Watch… We’ll start by adding a watch entry for the global variable TextLenPart. In the Expression input field, type TextLenPart. In the Procedure drop down box, select (All Procedures), and in the Module drop down box, select (All Modules).

Add Watch Window
Add Watch Window

After clicking on OK, the variable will be displayed in the watch window.

Watch Window
Watch Window

Function ReplaceText

The first function that is called in autoopen2 is ReplaceText. If you step over one line of code, execution of the macro will pause at the ReplaceText function. To determine what the ReplaceText function does, step into the function. Within this function the global variable TextLenPart is assigned a value. All of the global variables are declared in the window titled Module 1. A portion of the function is shown in the figure below.

Function ReplaceText
Function ReplaceText

The Split function is used to split a long hard-coded string (using the string “921029” to mark the places where the string should be split). Set a breakpoint on the line below the Split function call and click on continue. When execution pauses, there should be a plus sign next to the TextLenPart variable in the watch window. If you click on the plus sign, you will see the values that were assigned to the variable after the Split function completed. Notice that TextLenPart is an array of values, some of which are shown in the figure below. We will see later that this array of values is decoded into a URL in a subsequent function call.

Values assigned to TextLenPart global variable
Values assigned to TextLenPart global variable

There is additional code within the ReplaceText function. However, the additional code does not seem to serve any purpose, other than to cause confusion and make analysis more time consuming. Additional, unused code appears in all of the other functions that are executed as well.

To return to the autoopen2 function, set a breakpoint on the second function that is called, KJn…Word and then click on continue.

Function KJn…Word

Step into the KJn…Word function. The function is shown in the figure below.

Function KJn...Word
Function KJn…Word

The purpose of the first 4 highlighted lines of the function is to assign a value to the global variable massiveMyData. The obfuscated value is stored in a ControlTipText property of a textbox of a form that is part of the VBA project (shown in the figure below). The pirognoe function is used to deobfuscate the text.

Obfuscated data stored in ControlTipText property of TextBox Field
Obfuscated data stored in ControlTipText property of TextBox Field

If you add this variable to the watch window and set a breakpoint on the line after massiveMyData is assigned a value, and then continue, you will be able to examine the value of the variable. The variable should now be an array of values as shown in the figure below.

Global variable massiveMyData
Global variable massiveMyData

The remaining highlighted lines of the function create several objects that are assigned to global variables:

  1. the global variable substruct1 references an adodb.stream object
  2. the global variable stadyBradus references a shell.Application object
  3. the global variable YKJJJnnnn3_pe__1 references a Microsoft.xmlhttp object

To return to the autoopen2 function, set a breakpoint on the third function that is called, KJn…Email and then click on continue.

Function KJn…Email

The KJn…Email function is shown below.

Function KJn...Email
Function KJn…Email

The first two highlighted lines of the function are used to create an WshEnvironment object and assign it to the global variable YKJJJnnnn3_pe__3. The TextLenPart variable is also decoded into a URL, which is stored in the global variable DJeremy. The function RemoveSpecialChar is used to decode each element in the TextLenPart array into a single character. The decoded characters are combined to form the url shown below.

Decoded URL
Decoded URL

To return to the autoopen2 function, set a breakpoint on the fourth function that is called, KJn…Name and then click on continue.

Function KJn…Name

The function KJn…Name is shown in the figure below. This function uses the objects created in the previous function calls to download a ransomeware executable from the URL stored in the global variable DJeremy. The lines of code can be translated as follows:

  1. xmlhttpObject.open(“GET”, DJeremy, False)
  2. xmlhttpObject.send()
  3. YKJJJnnnn3_pe__4 = WshEnvironmentObject(“Temp”)
  4.  YKJJJnnnn3_peNaStole = concatenation of the temp directory with “\filarmon.exe”
Function KJn...Name
Function KJn…Name

The first two lines use the xmlhttp object to send an HTTP GET request to the URL stored in the global variable Djeremy. The global variable YKJJJnnnn3_peNaStole is used to store the name of a file in the temporary directory stored in the TEMP environment variable.

Since we are debugging this macro in an isolated environment, we will receive error messages when attempting to send the requests to the website. So, instead of stepping through the rest of the code, we will perform static analysis instead.

Function CheckDriveSpecError

So far, we’ve seen some lines of code that are used to send an HTTP GET request to a website. But, we haven’t seen the downloaded file written to disk, or being executed. The CheckDriveSpecError function is the final function that is called from within autoopen2. It calls three other functions that appear to be responsible for performing these actions. These functions are shown below.

CheckDriveSpecError Function
CheckDriveSpecError Function

Each of the functions is examined below.

Function KJn…Alpha

The function KJn…Alpha is shown in the figure below. The global variable substruct1 is referenced in two locations. Recall substruct1 stores a reference to a Stream object. The highlighted lines in the figure show the stream’s type being set to 1, so the data stored by the stream object will be binary data, and the stream object being opened so data can be written to it.

Function KJn...Alpha
Function KJn…Alpha

Function KJn…Paragraph

The function KJn…Paragraph is shown in the figure below. The first highlighted line shows the response body received by the xmlhttp object YKJJJnnnn3_pe__1 being stored in the variable somebody. The response body contains the ransomware executable that was downloaded from the malicious website. The second highlighted line shows the contents of somebody being written to the stream object substruct1. Finally, the third highlighted line shows the contents of the stream object being written to a file. The name of the file was stored in the global variable YKJJJnnnn3_peNaStole. Recall that this variable contained the name of the temp directory stored in the environment variable TEMP with the filename “\filarmon.exe” appended to the end of the temp directory.

Function KJn...Paragraph
Function KJn…Paragraph

Function CheckKJn…BetterThen

The function CheckKJn…BetterThen is shown in the figure below. The stadyBradus variable stores a reference to a ShellDispatch object. It uses the Open method to execute the file that was written to the temporary directory. After this line is executed, the ransomware executable is running and infecting the target computer.

Function CheckKJn...BetterThen
Function CheckKJn…BetterThen
  • 1
  • 2
  • Next Page »

UT Austin ISO Blog

Find out more about the UT Austin Information Security Office at: security.utexas.edu

Facebook: facebook.com/utaustiniso

Twitter: @UT_ISO

Recent Posts

  • Spectre and Meltdown Vulnerabilities for IT Professionals
  • Analysis of False/Morel
  • Using NodeJS To Deobfuscate Malicious JavaScript
  • Reverse Engineering a Malicious MS Word Document
  • Spies and Social Media

Recent Comments

    Archives

    • January 2018
    • September 2016
    • July 2016
    • May 2016
    • March 2016
    • September 2015
    • September 2014

    Categories

    • Reverse Engineering
    • Security Alert
    • Uncategorized
    • Vulnerability

    Meta

    • Log in
    • Entries feed
    • Comments feed
    • WordPress.org

    UT Home | Emergency Information | Site Policies | Web Accessibility | Web Privacy | Adobe Reader

    © The University of Texas at Austin 2023

    • UT Austin
    • UT Blogs
    • Log in