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

 

Posted in Reverse Engineering Tagged with: , ,

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.

 

 

Posted in Reverse Engineering Tagged with: , , ,

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

Posted in Reverse Engineering Tagged with: , ,

Spies and Social Media

The Internet opens countless avenues of communication and convenience, but brings risk as well. Attackers can use seemingly innocuous social media connections and other information to find sensitive information about you, like your home address, password security questions, and more.

Goals

Learn how and why people may try to find you via the Internet, and learn how to:

  • Conduct a self-background check
  • Create free anonymous mail addresses, email addresses, and phone numbers
  • Control your privacy settings on social networks and remove sensitive data
  • Remove your personal information from public databases and people search websites

 Intended Audience

  • System administrators
  • IT Staff supporting law enforcement, other public officials, and VIPs
  • Privacy enthusiasts
  • Victims of identity theft
Presentation
Slides

Much of the presentation has an interactive component, so please open it in another window and participate when prompted.

Posted in Uncategorized

Reverse Engineering Necurs (Part 4 – IDA Pro’s Python API)

Introduction

In the previous post, we had paused execution of the malware sample at a point where the malware had “unpacked” itself. We then used the .writemem WinDbg command to output the unpacked data into a file. Finally, we used a Python script to “patch” the original malware sample so we could analyze the unpacked malware with IDA Pro. In this post, we’re going to take a look at using IDA Pro’s scripting capabilities to achieve the same thing.

Python scripts can be used to automate tasks in IDA Pro. This is a pretty nice thing because you can use standard Python functions for doing things like opening and reading files. You will only need to use IDA Pro’s Python API when you need to do something IDA Pro specific. This means the learning curve is not as bad as it could have been if IDA Pro had setup a scripting language from scratch.

Manually Patching Data in IDA Pro

A screenshot of the IDA Pro disassembly view of the malware sample at offset 0x40614C is shown below. Recall from the last blog post that this address is called the original entry point of the malware sample. When we used the Python script to patch the malware sample, we reset the entry point of the program to this address.

The data at this offset was not disassembled by IDA Pro when analyzing the original, packed malware sample. However, even if IDA Pro had disassembled the data, the disassembled instructions would not match the instructions being executed in WinDbg because the values starting at this location were changed when the malware unpacked itself.

IDA Pro disassembly view

IDA Pro disassembly view

To start to work with this data, we’re going to look at patching the information in IDA Pro manually. If you right-click on the first 4-byte value at offset 0x40614C (the value 9CCB38F8h), a context menu will be displayed.

 

IDA Pro context menu after right-clicking on data

IDA Pro context menu after right-clicking on data

If you click on “Undefine” and answer “yes” to the confirmation dialog, IDA Pro will display each byte of data on its own line. Its a little bit easier for me to work in IDA Pro if I start by reformatting the data in this way. The disassembly view should now look like this:

 

IDA Pro disassembly view after reformatting

IDA Pro disassembly view after reformatting

Next, click on the byte value (2Bh) at offset 0x40614C in the disassembly view. You should see the “2Bh” highlighted in yellow. From IDA Pro’s menu bar, select Edit -> Patch program -> Change byte…, and IDA Pro will display a dialog box where you can make changes. The dialog will allow you to change a number of bytes, not just a single one.

 

IDA Pro Patch Bytes dialog

IDA Pro Patch Bytes dialog

We’re going to replace the first nine bytes in the dialog box with the following bytes: 55 8B EC 81 EC D4 00 00 00. After clicking on “OK”, the patched bytes will be displayed. Next, right-click on the 55h at offset 0x40614C. From the context menu that is displayed, click on “Code”. IDA Pro will provide a disassembly of the data starting at that offset. Since we only patched 9 bytes, only the first three instructions will match the instructions in the WinDbg disassembly window. The fourth instruction does not match the instruction in WinDbg.

 

IDA Pro - patched instructions

IDA Pro – patched instructions

 

WinDbg disassembly at OEP

WinDbg disassembly at OEP

IDA Pro and Python

The next thing we’re going to do is experiment with entering Python commands in the IDA Pro console. Before doing so, right click on the text jns that is next to offset 0x406155 of the disassembly view, and select Undefine from the context menu that is displayed. The disassembly view should now look like:

 

IDA Pro disassembly view after undefining instructions

IDA Pro disassembly view after undefining instructions

The input for the console window will have the label “Python” next to it and is located toward the bottom of the IDA Pro display. This is where we will type our Python commands.

 

IDA Pro console

IDA Pro console

Documentation for the Python API can be found at IDA Pro Python API. The documentation is pretty lengthy, but, if you use the menu options in IDA Pro’s interface for search terms, you might have an easier time finding the functions you are interested in. In this example, we are using the Patch program… -> Change byte menu option, so I searched the web page for the text “patch”. One of the search results was a function called idaapi.patch_byte.

Even though there are a lot of API functions listed on the site, the documentation for each function does not seem very detailed to me. The only documentation I could find at this site is a function definition: bool patch_byte(ea, x). But, if you google “byte_patch”, you can find some additional help. The ea parameter refers to the address of the byte in the disassembly window, and x is the value that we want to use as the replacement value.

Suppose we want to change the byte value at offset 0x406155 from 79h to 53h. If you type patch_byte(0x406155, 0x53) into the console, and then hit the enter key, you should see the value change. So, we have verified which Python API function to use to patch a byte value at a specific location in the disassembly.

 

Patching a byte using patch_byte in the IDA Pro console

Patching a byte using patch_byte in the IDA Pro console

IDA Python Scripts

Now that we have found a IDA Pro Python function that will replace a byte in the disassembly with a byte of our choosing, we can write a script that will read the memory dump we produced in the previous post, and use the information in the file to patch the bytes in the disassembly. The script used to patch the disassembly is shown below:

 

Python script used to patch IDA Pro disassembly

Python script used to patch IDA Pro disassembly

A couple of things to note about the script. First, we are going to use the data starting at offset 0x514C to patch values at 0x40614C of the disassembly. Why? In the previous post, we used the command .writemem c:\necurs.bin 0x401000 0x410087 to dump the contents of the code section in memory to a file. Since we started dumping memory at 0x401000, the byte at offset 0x514C in the file will correspond to the byte at offset 0x401000 + 0x514C = 0x40614C in the disassembly. Second, the memory file necurs.bin must be in the same directory as the malware sample. If not, you may need to fully qualify the file path when making the open() call in the script. Third, there are a couple of print statements to show that the script started and finished. These are included because IDA Pro does not always display a message telling you if your script ran or not.

To run the script, select File -> Script file… from the IDA Pro menu bar. Select the script in the file dialog that is displayed, and click open. The script will run at this point and you should see some output that tells you the script ran in the console window. The bytes should also be patched once the script finishes.

After the script has finished, right-click on the address 0040614C in the IDA Pro disassembly view and click on Code in the context menu that is displayed. The disassembly should look like the screenshot shown below. Notice that the disassembled instructions match up with the disassembly in WinDbg.

 

Disassembly after running the patch script

Disassembly after running the patch script

Next Steps

Now that we have a disassembly of the unpacked malware, we will start to step through the code again using WinDbg.

 

 

Posted in Reverse Engineering Tagged with: , ,

Reverse Engineering Necurs (Part 3 – Patching)

Introduction

In the previous post, we started to step through the Necurs sample using WinDbg. We also used IDA Pro to perform static analysis of the malware sample so we could get an idea of where to set breakpoints. However, while stepping through the code, we jumped to a location in WinDbg that was not disassembled by IDA Pro. When we looked a little closer, the hex values in the memory window in WinDbg did not match up with the hex values displayed in IDA Pro. It looked like the malware sample had “unpacked” itself, and we had jumped to a location that’s called the “original entry point”, or OEP. This post is going to describe how to patch the original executable with the unpacked code so we can continue to use IDA Pro to perform static analysis.

I’m going spend some time talking about the information in the PE header. Since discussing the PE header in detail is outside of the scope of this blog post, I’d highly recommend taking a look at an article in CodeBreakers Magazine called Portable Executable File Format – A Reverse Engineer View. The article was written in 2006, but is applicable to this sample. It is pretty lengthy, but is well written and very interesting. It’s also a lot easier to understand than the formal specification of the PE file format.

Section Header Analysis

Before getting started, recall that we are paused at offset 0x40614C in WinDbg. Take a snapshot of the Windows VM and call the snapshot OEP. Then restore the snapshot of the VM that was paused at the entry point of the program. Enter !dh 0x400000 in the WinDbg command window. This was the command that was used to display the entry point of the executable. This command will also display information about the different sections in the malware sample.  The section we are interested in is section 1, the text section.

Section header for the "text" section

Section header for the “text” section

The first item of interested is the virtual address. It has a value of 0x1000. We can determine the location in memory of this section by adding the virtual address value to the module’s base address.  Since the start address of the module was 0x400000, this section was loaded in memory at address 0x401000. If we type this address into the Virtual textbox of WinDbg’s memory window, we can view the hex values that were loaded into memory at this location. If we jump to this location in IDA Pro, we will see that the values in IDA Pro match the values displayed in WinDbg.
WinDbg memory window. Hex values at offset 0x401000

WinDbg memory window. Hex values at offset 0x401000

IDA Pro Hex View tab. Hex values at offset 0x401000

IDA Pro Hex View tab. Hex values at offset 0x401000

The next item of interest in the section header data is the file pointer to raw data. This value is the offset of the section within the executable file itself.  It is located at offset 0x400. If we open the malware sample in a hex editor, and look at the values at this offset, we’ll see that they also match up with the values at offset 0x401000 in IDA Pro and WinDbg.
Hex dump of original exe at offset 0x400

Hex dump of original exe at offset 0x400

The final two items of interest are size of raw data and virtual size. The size of raw data is the number of bytes this section occupies in the executable (0xF200 bytes). The virtual size is the amount of space needed when loading this section into memory (0xF088 bytes). For performance reasons, sections are written to file in 512 byte increments. If a section does not end at a 512 byte increment, the remaining bytes are null padded. If we inspect the data at location 0x400 +  0xF088 = 0xF488 in the hex editor, we will see a series of null bytes used to pad the section to the 512 byte increment. The virtual size is smaller than the size of raw data because the null bytes do not need to be loaded into memory.
Null padding at end of section in executable file

Null padding at end of section in executable file

If we inspect the values at offset 0x401000 + 0xF088 = 0x410088 in IDA Pro and WinDbg, we will see the null padding as well. When an executable is loaded into memory, the memory is allocated in 4096 or 8192 byte chunks.  So, we should see null padding at the end of the text section because the section does not end at a 4096/8192 byte increment.
IDA Pro view of null padding at end of text section

IDA Pro view of null padding at end of text section

WinDbg view of null padding

WinDbg view of null padding

Patching Strategy

We know that the text section is loaded into memory at offset 0x401000. We also know that 0xF088 bytes of memory were allocated for this section.  Finally, we know that the executable has been unpacked in the OEP snapshot. So if we can dump the contents of memory at this offset into a file and replace the text section of the original executable with the memory dump, we should have an unpacked executable that can be disassembled by IDA Pro. We will also have to patch the entry point of the program so that IDA Pro knows where to start disassembling the new executable.

To dump the memory, restore the OEP snapshot. Then in the WinDbg command window, use the following command to dump the memory:

.writemem c:\necurs.bin 0x401000 0x410087.

The command window should display that F088 bytes were written. We will use the necurs.bin file to patch the text section of the malware sample.

The entry point of the malware sample is stored at offset 0x118 in the original executable. This offset shows a value of 0xd460. However, the actual value of the entry point was 0x60D4. The entry point is stored in little endian format, so when we patch this value, we will need to convert the new entry point into little endian format as well. Recall that we jumped to 0x40614C after the executable was unpacked, so we’ll change the bytes at offset 0x118 from 0x60D4 to 0x4C61.

Entry point value at offset 0x118 of malware sample

Entry point value at offset 0x118 of malware sample

The python script shown below was used to patch the malware sample. The original malware sample was named necurs-packed.exe. The memory dump was named necurs.bin, and the patched malware sample was called necurs-unpacked.exe.

python script used to patch packed malware sample

python script used to patch packed malware sample

If we use IDA Pro to disassemble the unpacked executable, and inspect the start subroutine (at offset 0x40614C), the disassembly in IDA Pro matches up with the disassembly in WinDbg. We’re now able to perform a static analysis of the unpacked code while stepping through the code with WinDbg.
IDA Pro disassembly at offset 0x40614C

IDA Pro disassembly at offset 0x40614C

 

WinDbg disassembly at offset 0x40614C

WinDbg disassembly at offset 0x40614C

Some Things To Keep In Mind

It was relatively easy to patch the Necurs malware sample so we could analyze it in IDA Pro. However, there are packing algorithms that also compress the executable code. If this happens, the size of the unpacked section may be larger than the size of raw data in the executable file. If this is the case, the memory dump will not “fit” into the text section of the original executable. If this happens, it’s still possible to patch the executable, but it gets a little bit more complicated. Specifically, the file pointer to raw data field of any other sections would need to be patched to make room for the contents of the memory dump.

Also, even though we patched the entry point of the unpacked executable, the unpacked executable may not run in a debugger in the same way as the unpacked code. Any subroutines that were executed before the jump to the OEP may have written data to memory, and the new start routine may need to access this data. Remember that the main purpose of unpacking the executable in this way was to allow IDA Pro to properly disassemble the malware sample.

Next Steps

In the next blog post, I’ll talk about using scripting in IDA Pro as an alternative to patching the executable.

Posted in Reverse Engineering Tagged with: , ,

Reverse Engineering Necurs (Part 2 – Unpacking)

Introduction

In the previous post, we talked about using tcpdump on a VM to monitor network traffic produced by another VM infected with Necurs.  We noticed that some “weird” UDP packets were being generated after infection, and used this observation to verify that the malware sample would run in a virtual environment, as well as in a debugger.  In this blog post, we’re going to try to figure out the location of the instructions that are responsible for generating the UDP packets.  We’re not going to succeed (at least not yet), but we will see some interesting things.

Pausing at the Malware’s Entry Point

In the previous post, we located the entry point of the Necurs malware sample in WinDbg so we that we could use a debugger to analyze the sample.  While in WinDbg, I like to have several windows opened and docked so I can see the disassembled code, view memory, and issue commands to the debugger.  So I usually use the icons in the toolbar to open a memory window and disassembler window.  The command windows opens automatically when you open the executable.  An image of my layout is shown below.  After I setup this layout, I took a snapshot of the VM, so I could quickly return to the WinDbg session paused at the malware’s entry point.

WinDbgLayout

WinDbg Layout

Some things to note about the layout: a breakpoint was set at the entry point of the program, and the program has paused execution at the breakpoint.  This instruction is highlighted in purple in the disassembler window.  The display format in the memory window is “byte”, and the entry in the “virtual” text box is “@$scopeip”.  As long as these settings are used, the memory window will display the hex values currently in memory starting from the offset of the paused instruction in the disassembler.

Analyzing the Start Subroutine

We’re going to begin by analyzing the Start subroutine in IDA Pro.  A snapshot of the routine is shown below.  There are two instructions in the subroutine: a call instruction to sub_406E5D and a jmp to loc_403474.  Remember that our goal is to find the code that generates the UDP traffic we observed in tcpdump.  One would think that either the call to sub_406E5D will eventually execute the instructions that generate the UDP packets or the jmp instruction will do so.  In WinDbg, we are going to step over the call to sub_406E5D and then monitor the output of tcpdump on the Ubuntu VM.  If we start seeing the “weird” UDP packets that we saw when we ran the malware sample in the previous blog, we’ll know that if we further analyze sub_406E5D (and all the subroutines it may call), we should find the code that generates the UDP traffic.  If not, the jmp to loc_403474 should eventually lead us to the code that generates the UDP packets.

NecursEntryPoint

Start Subroutine as displayed in IDA Pro

To step over the call to sub_406E5D, enter p into the WinDbg command window.  If you wait a few seconds, you should see the “weird” UDP packets in the tcpdump output.  This means that we need to analyze sub_406E5D.  Next, we want to restore the snapshot so that we are in WinDbg at the malware’s entry point.  Instead of stepping over sub_406E5D, enter t into the command window to step into the subroutine.

Analyzing sub_406E5D

If we look at sub_406E5D in IDA Pro, we’ll notice that there are no call instructions.  Instead, there is a jmp instruction to an address that’s stored in the ecx register.  A few lines above the jmp instruction, you will see the address of sub_402C4B being loaded into the ecx register.  It’s pretty strange to use this set of instructions to jump to a subroutine instead of simply using a call instruction.  When a call instruction is executed, the address of the instruction after the call instruction is pushed onto the stack before code execution is transferred to the subroutine.  Once the subroutine ends, execution can be transferred to the address that was stored on the stack. We’ll see later in this post what happens when jmp is used instead of call in this subroutine.

sub_406e5d

IDA Pro View of sub_406E5D

Next, I used the p command in the WinDbg command window to step over instructions until I arrived at the first instruction in sub_402C4B.

Analyzing sub_402C4B

If we analyze sub_402C4B, we will see that it is a pretty long subroutine with a number of call instructions.  Many of the call instructions have text strings next to them (for example, the call to LCMapStringA at 0x402D38).  These are calls to Windows API functions.  If you are interested in learning more about the API calls, documentation for most of the API functions can be found on the Microsoft Developer Network website (msdn.com).  There are also calls to sub_xxx subroutines, where xxx is a location within the malware sample.  These subroutines have been disassembled by IDA Pro.  Since none of the Windows API functions in this subroutine appear to be network related, they probably do not generate the UDP packets we are seeing in tcpdump.

So, we are going to focus on the calls to the sub_xxx subroutines.  These are the subroutines that are called in sub_402C4B:

  1. sub_402BE2 (at 0x40308E and 0x4030AA)
  2. sub_401000 (at 0x403188)
One of these subroutines probably contains the instructions that will eventually generate the UDP traffic that we are interested in.  We will set breakpoints at these three locations, then step over the functions and observe the tcpdump output to see which subroutine generates the traffic.  In the WinDbg command window, type the following to set the breakpoints.
  1. bp 0x40308E
  2. bp 0x4030AA
  3. bp 0x403188
Then type g to continue the program. The first breakpoint we should hit is at offset 0x40308e. This line in the WinDbg disassembly window is highlighted in purple, which means this is the next instruction that will be executed when we continue executing the program and that there is a breakpoint set on the line as well. Note that the instruction at 0x40308e is red, which means a breakpoint is set on this line as well.
FirstBreakPoint

WinDbg – Program Paused on Break Point

Next, we type p in the command window to step over the subroutine. When program execution pauses, the instruction at 0x403093 is highlighted in blue. This means that this is the next instruction that will be executed, but its not purple because no breakpoint is set on that line. If you look at the tcpdump output on the Ubuntu VM, there should be no “weird” UDP packets generated by the infected VM. Since we did not see any UDP packets, the call to this subroutine is not responsible for the UDP traffic.

Pause At 403093

WinDbg – BreakPoint After stepping over subroutine call

Next, after typing g into the command window, program execution paused at 0x4030aa.  Once again we can type p to step over the subroutine and check the tcpdump output for UDP packets. Once again, no UDP packets are displayed in the tcpdump output, so the call to this subroutine is not responsible for the UDP traffic. Next, we type g to continue executing the program. However, this time, we do not hit another breakpoint. Instead, the program exits.  If we look at the tcpdump output, we will see UDP traffic being generated by the infected VM.

Why Didn’t We Hit Another BreakPoint

Based on the static analysis, it looked like either sub_402BE2 or sub_401000 was responsible for generating the UDP traffic.  But, we found that even though sub_402BE2 was called twice, it was not responsible for generating the UDP traffic, and that sub_401000 was never called.  What happened?

There’s a couple of reasons this may have happened. First, we may have hit a jump statement within sub_402C4B that took us someplace unexpected. The second is that we hit a retn instruction, and were returned to an unexpected place.  We will focus on finding a retn statement. First, restore the snapshot of the infected VM where the malware was paused at the entry point. Then, set a breakpoint at 0x4030AA, the last breakpoint that was hit in the previous paragraph. Type p into the WinDbg command window to step over the subroutine, then type pt. This command will continue execution until the next retn instruction, and then pause the program.  The program should pause at 0x403180. Then type p to execute the retn instruction. The program will then pause execution at instruction 0x402296.

Remember when we were analyzing sub_406E5D, and execution was transferred to sub_402C4B with a jmp instead of a call instruction? The malware placed the address of sub_402296 on the stack so that when sub_402C4B completed execution, code execution would be transferred to sub_402296. This is an example of a technique used to hinder static analysis in IDA Pro. However, stepping through the program allowed us to determine where code execution resumes, and we now have a new subroutine to analyze.

Analyzing sub_402296

Once again, we will start by looking at IDA Pro, and identify the possible subroutines that we want to step over and monitor. The following subroutines are called within sub_402296:

  1. sub_40200A (0x4023A1)
  2. sub_402241 (0x402449)
  3. sub_40320F (0x4024A6)
  4. sub_402AE8 (0x40298D)
  5. sub_4031D4 (0x4029F3)
Once again, we will set breakpoints on each of these locations, step over the function, and then monitor the Ubuntu tcpdump for UDP packets. When we do this, we hit breakpoints at the following locations:
  1. 0x4023A1
  2. 0x402449
  3. 0x4024A6
However, once we continue execution, we do not hit any of the other breakpoints. Once again, the malware completes execution and starts generating UDP packets. We can try using pt in the WinDbg command window to see if the malware hits another retn instruction. But, when we do this, the malware does not break on a retn instruction. Instead, Windbg shows that the malware is busy running. Something else weird is happening here.
MalwareBusy

WinDbg – *BUSY* – code execution is no longer paused

Once again, we will restore our snapshot at the program entry point. This time, we need to set a breakpoint at 0x4024A6, the last breakpoint that we successfully hit. Enter g in the WinDbg command window and the malware should pause at the breakpoint.

Next, we’ll take a closer look at the IDA Pro disassembly. We know that we’re not running into an unexpected retn instruction, so we’ll look at the jmp instructions instead. Most of the jmp instructions will jump to a known location in the malware sample. For example, the jmp instruction at 0x4025DB jumps to loc_4025EA. However, the instruction at 0x40290C is a little more interesting. It’s a location determined at runtime, as shown below.

dynamicjump

Jump to location determined at run time

If we set a breakpoint on this location, and then type g in the command window, the malware will pause execution at this point. Next, type p to execute the jump instruction. The next instruction that will be executed is at 0x40614c. If you look in IDA Pro, this portion of the malware was not disassembled, as shown below.

NonDisassembledCode

Code that was not disassembled by IDA Pro

There’s something else that is odd about this code. If you switch to the hex view in IDA Pro, and jump to address 0x40614C (by selecting “Jump to address” from the “Jump” menu item), you will be able to view a hex dump of the code at that offset. If you look at the hex output in the WinDbg memory window, you will see that the hex outputs do not match.

HexView

Hex Output In IDA Pro for Offset 0x40614C

WinDbgMemory

WinDbg Hex Output at Offset 0x40614C

Some of the previous subroutines that we stepped over probably unpacked this portion of the executable. Once unpacked, code execution was transferred to this portion of the malware. So, even if we tried to manually disassemble this portion of code with IDA Pro, since the values at this offset were changed, the disassembly would not match the code being executed in WinDbg.

Next Steps

In the next blog post, I’ll talk about some techniques for patching the malware sample and the data in IDA Pro. After doing so, we’ll be able to use IDA Pro to disassemble the unpacked code so we can continue with our static analysis.

 

 

Posted in Reverse Engineering Tagged with: , , ,

Reverse Engineering Necurs (Part 1 – Preliminaries)

A few weeks ago, a fellow analyst sent me a link to a write-up of a new peer-to-peer botnet called Necurs.  The write-up included a link to a SANS blog entry.  The blog entry included a pcap containing traffic captured from an infected host as well as a sample of the malware.  Since I’m pretty interested in malware that communicates via peer-to-peer mechanisms, I decided to take a look at this sample.  Hopefully, the notes I take during the analysis will be helpful to anybody else that is new to reverse engineering.

A little background about myself (as a reverse engineer): I took the SANS GREM course a number of years ago and learned quite a bit about reverse engineering.  But, even though I made it through the course, it was very difficult to get started analyzing malware samples because of the different types of obfuscation and evasion techniques that I encountered.  The SANS course mentioned a number of tools that could be used to make analysis easier, but I decided to start limiting myself to four tools: IDA Pro (a disassembler), WinDbg (a debugger), Process Explorer (a Windows Sysinternals tool for inspecting running processes on a Windows System), and tcpdump (for capturing/analyzing network traffic).

When I first started analyzing malware, I wanted to be able to analyze a sample even if I couldn’t use a tool that automated the unpacking of the malware.  So, instead of searching for automated unpackers, I spend a lot of time in WinDbg stepping through an executable.

I also make use of a pretty standard virtual machine setup to aid with the analysis.  I use two virtual machines with the following IP address configuration:

  1. WindowsXP With IP Address 192.168.1.2, subnet mask 255.255.255.0, default gateway 192.168.1.1, DNS server 192.168.1.1
  2. Ubuntu with IP address 192.168.1.1, subnet mask 255.255.255.0

The network cards on each of the machines is configured as on the “Host-only” network so that network traffic does not escape the virtual environment that has been created.  The Ubuntu VM will run tcpdump and capture traffic sent by the infected Windows XP VM after it has been infected with the malware.  The virtual environment is very important because you can create snapshots of the Windows XP virtual machine at various stages of the infection.  So, if you accidentally step too far in the debugger, you can return to a previous state in very little time.

A final note.  Many malware samples employ defenses to evade analysis.  Some will not run when executed in a debugger.  Some will not run while executing in a virtual environment. So, there are a couple of preliminary checks that I make to verify that the malware will run in the virtual environment before I start the lengthy task of stepping through the executable.   First, we’d like to verify that the malware will run in a virtual machine, then we would like to verify that the malware will run when executed in a debugger.  If we don’t do this, we may spend a lot of time in the debugger stepping through instructions that are used by the malware to evade analysis.  The steps that follow will not guarantee that you will not run into some other type of evasion technique, but they will hopefully verify that you can start stepping through the executable in a virtual environment.

First Run: execute the malware within VM

First, I need to be able to observe something that tells me that I have successfully infected the Windows XP VM.  Since this malware sample will try to send network traffic to other infected hosts within the botnet, we can use tcpdump to monitor the network traffic generated by the Windows XP VM.  I run tcpdump twice on the Ubuntu VM.  I use one tcpdump instance to write to a file for later analysis, and one tcpdump instance that outputs to the console.   Note that the Windows VM does generate some Netbios traffic that is unrelated to the malware.  You should see this traffic before executing the malware on the Windows XP VM.  The tcpdump commands used on the Ubuntu were as follows:

  1. tcpdump -nnSX -i eth0
  2. tcpdump -nS -i eth0 -w necurs.pcap

When I executed the Necurs sample on the Windows XP VM, the tcpdump instance displayed UDP traffic with a source port of 14820 with a payload size of 29 bytes.  This looks kind of strange, so hopefully we have verified that the malware will run within a virtual environment.

Second Run: Execute From Within WinDbg

Next, I executed the sample from within WinDbg while monitoring network traffic on the Ubuntu VM using tcpdump.  The following steps were taken after starting Windbg:

  1. File -> Open Executable …
  2. Selected the Necurs sample in the file dialog
  3. Type g in the command window

Once again, UDP packets from an odd port on the infected Windows VM were displayed in the tcpdump output.  This shows that the malware will run even if it is being executed in a debugger. However, this time, the source port of the packets was 5255.

ScreenShot of Packet Capture

Output of tcpdump on Ubuntu VM

This suggests that the malware chooses a random port upon infection as opposed to having a port hard-coded into the binary.Another odd thing happened. The UDP packets were being sent even after the malware had finished executing in the WinDbg command window.  This indicates that another process was spawned and that the newly spawned process was responsible for generating the network traffic.  I used Process Explorer to display information about the processes that were running in the infected VM. A process called syshost.exe was running with PID of 576. The process properties showed that this process was listening on port 5255 for both TCP and UDP traffic, so this is probably the process that the malware spawned.

ScreenShot of ProcessExplorer

Process Explorer and syshost.exe properties

Third Step: Break At Program Entry Point

Now that we have verified that the malware sample will run on a debugger in a virtual machine, we need to start stepping through the instructions in the executable.  This is a little bit difficult when using WinDbg because we’ll need to set a breakpoint on the entry point of the executable. The following steps can be used to accomplish this:

  1. Open the malware in WinDbg as described above.
  2. Type the command lmf into the command window.  This command will display modules loaded by WinDbg.  Ordinarily, I would hope to see a module with a name that matches the malware executable, but for some reason, this name was not displayed.  Instead, a module named xl4n6aq.exe with a base address of 0x400000 was included.
ScreenShot 3 Weird Module Name

Module with weird name displayed in WinDbg command window

 

  1. Next, I used the command !dh 0x400000 to determine the entry point of the program. The entry point is shown at offset 0x60D4, so the breakpoint should be set at 0x4060D4 (base address + entry point offset).
ScreenShot 4 Entry Point

Determining the entry point of the malware sample

  1. We can now set a breakpoint using the command bp 0x4060D4.
  2. We can type g into the console, and the malware will execute until we reach the breakpoint.

At this point, I took a snapshot of the VM so I can easily get back to this point.  I also opened an IDA Pro session so I could compare the disassembly produced by IDA Pro with the instructions shown in a disassembly window in WinDbg.  The first two disassembly lines in WinDbg matched the disassembly shown in IDA Pro, so we’ve reached a good starting point for debugging the malware.

Posted in Reverse Engineering Tagged with: , , ,

Android 5.x Lockscreen Bypass (CVE-2015-3860)

A vulnerability exists in Android 5.x <= 5.1.1 (before build LMY48M) that allows an attacker to crash the lockscreen and gain full access to a locked device, even if encryption is enabled on the device. By manipulating a sufficiently large string in the password field when the camera app is active an attacker is able to destabilize the lockscreen, causing it to crash to the home screen. At this point arbitrary applications can be run or adb developer access can be enabled to gain full access to the device and expose any data contained therein.

September 2015: Elevation of Privilege Vulnerability in Lockscreen (CVE-2015-3860)

The attack requires the following criteria:

  • Attacker must have physical access to the device
  • User must have a password set (pattern / pin configurations do not appear to be exploitable)

Proof-of-concept – Nexus 4 factory image 5.1.1 (build LMY48I):


Attack breakdown:

  1. From the locked screen, open the EMERGENCY CALL window.
    01-lockscreen
  2. Type a few characters, e.g. 10 asterisks. Double-tap the characters to highlight them and tap the copy button. Then tap once in the field and tap paste, doubling the characters in the field. Repeat this process of highlight all, copy, and paste until the field is so long that double-tapping no longer highlights the field. This usually occcurs after 11 or so repetitions.
    02-dialer03-dialer-asterisks04-dialer-copy05-dialer-paste06-dialer-nocopy
  3. Go back to the lockscreen, then swipe left to open the camera. Swipe to pull the notification drawer down from the top of the screen, then tap the Settings (gear) icon in the top right. This will cause a password prompt to appear.
    07-camera08-camera-settings09-camera-password
  4. Long-tap in the password field and paste the characters into it. Continue to long-tap the cursor and paste the characters as many times as possible, until you notice the UI crash and the soft-buttons at the bottom of the screen disappear, expanding the camera to fullscreen. Getting the paste button can be finicky as the string grows. As a tip, always make sure the cursor is at the very end of the string (you can double-tap to highlight all then tap towards the end to quickly move the cursor there) and long-tap as close to the center of the cursor as possible. It may take longer than usual for the paste button to appear as you long-tap.
    10-camera-paste11-camera-pasted12-camera-secondpaste13-crash-nosoftkeys
  5. Wait for the camera app to crash and expose the home screen. The duration and result of this step can vary significantly but the camera should eventually crash and expose sensitive functionality. You should notice the camera lagging as it attempts to focus on new objects. Taking pictures via the hardware keys may speed up the process, though it is not strictly necessary. If the screen turns off due to inactivity, simply turn it back on and continue waiting. In some cases the camera app will crash directly to the full home screen as seen below, whereas other times it may crash to a partially rendered homescreen as seen in this alternate proof-of-concept video.
    13-crash-nosoftkeys14-crash-background15-crash-desktop
  6. Navigate to the Settings application by any means possible, e.g. by tapping the app drawer button in the bottom center and finding it in the app list. At this point it is possible to enable USB debugging normally (About phone > tap Build number 7 times, back, Developer options > USB debugging) and access the device via the adb tool to issue arbitrary commands or access the files on the device with the full permissions of the device owner.
    16-settings17-settings-about18-settings-developer

Timeline:

2015-06-25: Vulnerability reported privately to Android security team.
2015-07-01: Android confirms vulnerability can be reproduced, assigns LOW severity issue.
2015-07-15: Android promotes issue to MODERATE severity.
2015-08-13: Android commits a patch to fix vulnerability.
2015-09-09: Android releases 5.1.1 build LMY48M containing fix.
2015-09-14: Android marks issue public.
2015-09-15: UT ISO publishes this writeup.

jgor

Posted in Vulnerability

Arbitrary File Deletion as Root in Webmin

A vulnerability exists in Webmin <= 1.680 (CVE-2014-2952) that allows authenticated users to delete arbitrary files on the host server as root. The problem exists in the cron module, specifically in creating a new environment variable (System > Scheduled Cron Jobs > Create a new environment variable), in the “user” parameter. Here’s the normal request to create an environment variable:

Screen Shot 2014-09-09 at 10.45.52

Using directory traversal and null byte injection techniques we’re able to force webmin to delete any file on the filesystem. Modifying our request a bit:

Screen Shot 2014-09-09 at 10.48.36

..and the response:

Screen Shot 2014-09-09 at 10.48.58

We get an error, but this request also immediately deletes /etc/passwd on the server. Why? Let’s take a look at the relevant code in /usr/share/webmin/cron/save_env.cgi:

Screen Shot 2014-09-08 at 17.16.55

We get a list of files in the cron directory, then call lock_file() on each file. Note that the filename is constructed from the value of the user parameter then passed unsanitized to lock_file(). The purpose of lock_file(), defined in web-lib-funcs.pl, is to create a file of the form /path/to/filename.lock to indicate the file is in use. We can see the lock file being created on line 5202 of /usr/share/webmin/web-lib-funcs.pl:

Screen Shot 2014-09-09 at 10.16.32

Looking further down lock_file():

Screen Shot 2014-09-09 at 10.31.41

On line 5231 it’s storing the filename in locked_file_list, and on 5232 it gets added to temporary_files as well. These data structures come into play when webmin throws the error we saw earlier. Taking a look at the end of the error() function in web-lib-funcs.pl, we see:

Screen Shot 2014-09-09 at 11.05.31

First let’s take a look at unlock_all_files():

Screen Shot 2014-09-09 at 11.08.11

It iterates through locked_file_list calling unlock_file() on each filename. Now on to unlock_file():

Screen Shot 2014-09-09 at 11.09.52

Line 5283 calls unlink() on the filename with “.lock” appended, to delete the lock file. However since we injected a null byte at the end of the filename, everything after the %00 gets ignored. This means the real file, ../../../../etc/passwd, gets passed to unlink() and deleted.

The damage is already done but even if the unlock_all_files() call were not present cleanup_tempnames() would do the same job. Let’s take a look:

Screen Shot 2014-09-09 at 11.16.01

Again we’re iterating through the list of files, in this case temporary_files, and calling unlink on the file. Even though the filenames stored in temporary_files were added with “.lock” appended, our null byte knocked that off and stored ../../../../etc/passwd instead, which of course causes /etc/passwd to be deleted.


Timeline:

2014-05-14: UT ISO reports the vulnerability to Webmin developer Jamie Cameron as well as CERT. CERT reserves CVE-2014-2952 for the vulnerability.
2014-05-14: Jamie patches Webmin on github.
2014-05-20: Webmin 1.690 is released with the fix.
2014-09-09: UT ISO publishes this writeup.

jgor

Posted in Vulnerability