Analyze the malware found in the file Lab09-02.exe using OllyDbg to answer the following questions.
Questions and Short Answers
-
What strings do you see statically in the binary?
A: The imports and the string cmd are the only interesting strings that appear statically in the binary.
-
What happens when you run this binary?
A: It terminates without doing much.
-
How can you get this sample to run its malicious payload?
A: Rename the file ocl.exe before you run it.
-
What is happening at 0x00401133?
A: A string is being built on the stack, which is used by attackers to obfuscate strings from simple strings utilities and basic static analysis techniques.
-
What arguments are being passed to subroutine 0x00401089?
A: The string 1qaz2wsx3edc and a pointer to a buffer of data are passed to subroutine 0x401089.
-
What domain name does this malware use?
A: The malware uses the domain practicalmalwareanalysis.com.
-
What encoding routine is being used to obfuscate the domain name?
A: The malware will XOR the encoded DNS name with the string 1qaz2wsx3edc to decode the domain name.
-
What is the significance of the CreateProcessA call at 0x0040106E?
A: The malware is setting the stdout, stderr, and stdin handles (used in the STARTUPINFO structure of CreateProcessA) to the socket. Since CreateProcessA is called with cmd as an argument, this will create a reverse shell by tying the command shell to the socket.
Detailed Analysis
We will use dynamic analysis and OllyDbg to analyze this piece of malware in order to determine its functionality. But before we get into debugging, let’s begin by running Strings on the binary. We see the imports and the string cmd. Next, we’ll simply run the binary to see if anything interesting happens.
Based on the process launch and exit in Process Explorer, the process seems to terminate almost immediately. We are definitely going to need to debug this piece to see what’s going on.
When we load the binary into IDA Pro, we see the main function begins at 0x401128. OllyDbg will break at the entry point of the application, but the entry point contains a lot of uninteresting code generated by the compiler, so we’ll set a software breakpoint on main, since we want to focus on it.
Decoding Stack-Formed Strings
If we click the Run button, we hit the first breakpoint at main. The first thing to notice is a large series of mov instructions moving single bytes into local variables beginning at \({\color{red}1}\), as shown in Listing 9-4L.
Listing 9-4L: Building an ASCII string on the stack, one character at a time
This code builds two ASCII strings by moving each character onto the stack followed by NULL terminators at \({\color{red}2}\) and \({\color{red}3}\), which is a popular method for string obfuscation. The obfuscated strings will be referenced by the first variable of the string, which will give us the full NULL-terminated ASCII string. We single-step over these moves to look for signs of these strings being created on the stack in the lower-right pane. We stop executing at 0x4011C6, right-click EBP, and select Follow in Dump. By scrolling up to the first string [EBP-1B0], we can see the string 1qaz2wsx3edc being created. The second string is created at [EBP-1A0] and named ocl.exe.
这是因为第一个字符串在内存 EBP-1B0 = 12FF80 - 1B0 = 12FDD0;第二个字符串在 EBP-1A0 = 12FF80 - 1A0 = 12FDE0,利用鼠标滚轮在 12FF80 附近偏移相应的位置就能找到。
Filename Check
After these strings are created, we can see a call to GetModuleFileNameA in Listing 9-5L at \({\color{red}1}\), and then a function call within the Lab09-02.exe malware to 0x401550. If we try to analyze this function in OllyDbg, we’ll find that it’s rather complicated. If we examine it in IDA Pro, we’ll see that it is the C runtime library function _strrchr. OllyDbg missed this due to the lack of symbol support. If we load the binary into IDA Pro, we can let IDA Pro use its FLIRT signature detection to correctly identify these APIs, as shown as shown at \({\color{red}2}\).
IDA:
OllyDbg:
Listing 9-5L: IDA Pro labels strrchr properly, but OllyDbg does not.
Let’s verify this by setting a breakpoint on the call at 0x401217. We can see two arguments being pushed on the stack. The first is a forward slash, and the second is the value being returned from the GetModuleFileNameA call, which would be the current name of the executable. The malware is searching backward for a forward slash (0x5C character) in an attempt to get the name (rather than the full path) of the executable being executed. If we step-over the call to _strrchr, we can see that EAX is pointing to the string \Lab09-02.exe.
The next function call (0x4014C0) reveals a situation similar to _strrchr. IDA Pro identifies this function as _strcmp, as shown in Listing 9-6L.
Listing 9-6L: IDA Pro labels strcmp properly, but OllyDbg does not.
We’ll determine which strings are being compared by setting a breakpoint on the call to _strcmp at 0x401236. Once our breakpoint is hit, we can see the two strings being sent to the _strcmp call. The first is the pointer to the GetModuleFileNameA call (incremented by one at \({\color{red}1}\) to account for the forward slash), and the other is ocl.exe (our decoded string from earlier). If the strings match, EAX should contain 0, the test eax,eax
will set the zero flag to true, and execution will then go to 0x40124C. If the condition is false, it looks like the program will exit, which explains why the malware terminated when we tried to execute it earlier. The malware must be named ocl.exe in order to properly execute.
Let’s rename the binary ocl.exe and set a breakpoint at 0x40124C. If our analysis is correct, the malware should not exit, and our breakpoint will be hit. Success! Our breakpoint was hit, and we can continue our analysis in OllyDbg.
然后,control+F2 -> F9,ocl.exe 程序成功在断点处停下:
Decoding XOR Encoded Strings
WSAStartup and WSASocket are imported, so we can assume some networking functionality is going to be taking place. The next major function call is at 0x4012BD to the function 0x401089. Let’s set a breakpoint at 0x401089 and inspect the stack for the arguments to this function call.
The two arguments being passed to this function are a stack buffer (encoded string) and the string 1qaz2wsx3edc (key string). We step-into the function and step to the call at 0x401440, which passes the key string to strlen. It returns 0xC and moves it into [EBP-104]. Next, [EBP-108] is initialized to 0. OllyDbg has noted a loop in progress, which makes sense since [EBP-108] is a counter that is incremented at 0x4010DA and compared to 0x20 at 0x4010E3. As the loop continues to execute, we see our key string going through an idiv and mov instruction sequence, as shown Listing 9-7L.
Listing 9-7L: String decoding functionality
注:OllyDbg 中在反汇编窗口使用 control+g 可调到指点地址处;IDA 使用 g 即可实现该功能。
This is getting an index into the string. Notice the use of EDX after the idiv instruction at \({\color{red}1}\), which is using modulo to allow the malware to loop over the string in case the encoded string length is longer than our key string. We then see an interesting XOR at \({\color{red}2}\).
If we set a breakpoint at 0x4010F5, we can see which value is being pointed to by EDX and being moved into ECX, which will tell us the value that is getting XOR’ed later in the function. When we click Follow in Dump on EDX, we see that this is a pointer to the first argument to this function call (encoded string). ECX will contain 0x46, which is the first byte in the encoded string. We set a breakpoint at \({\color{red}2}\) to see what is being XOR’ed on the first iteration through the loop. We see that EDX will contain 0x31 (first byte of key string), and we again see that ECX will contain 0x46.
Let’s execute the loop a few more times and try to make sense of the string being decoded. After clicking play(F9) a few more times, we can see the string www.prac. This could be the start of a domain that the malware is trying to communicate with. Let’s continue until var_108 ([EBP-108], our counter variable) equals 0x20. Once the jge short 0x40111D
at \({\color{red}3}\) is taken, the final string placed into EAX is www.practicalmalwareanalysis.com (which happens to be of length 0x20), and the function will then return to the main function. This function decoded the string www.practicalmalwareanalysis.com by using a multibyte XOR loop of the string 1qaz2wsx3edc.
ECX 寄存器的值到达 0x1F 后,转 Step-over(F8)调试。直到 ECX 为 0x20 为止:
F7/F8 执行一步,发现跳过了循环:
Back in the main function, we see EAX being passed to a gethostbyname call. This value will return an IP address, which will populate the sockaddr_in structure.
Next, we see a call to ntohs with an argument of 0x270f, or 9999 in decimal. This argument is moved into a sockaddr_in structure along with 0x2, which represents AF_INET (the code for Internet sockets) in the sockaddr_in structure. The next call will connect the malware to www.practicalmalwareanalysis.com on TCP port 9999. If the connection succeeds, the malware will continue executing until 0x40137A. If it fails, the malware will sleep for 30 seconds, go back to the beginning of the main function, and repeat the process again. We can use Netcat and ApateDNS to fool the malware into connecting back to an IP we control.
If we step-into the function call made at 0x4013a9 (step-into 0x401000), we see two function calls to 0x4013E0. Again, this is another example where OllyDbg does not identify a system call of memset, whereas IDA Pro does identify the function. Next, we see a call to CreateProcessA at 0x40106E, as shown in Listing 9-8L. Before the call, some structure is being populated. We’ll turn to IDA Pro to shed some light on what’s going on here.
Listing 9-8L: Creating a reverse shell using CreateProcessA and the STARTUPINFO structure
Reverse Shell Analysis
This appears to be a reverse shell, created using a method that’s popular among malware authors. In this method, the STARTUPINFO structure that is passed to CreateProcessA is manipulated. CreateProcessA is called, and it runs cmd.exe with its window suppressed, so that it isn’t visible to the user under attack. Before the call to CreateProcessA, a socket is created and a connection is established to a remote server. That socket is tied to the standard streams (stdin, stdout, and stderr) for cmd.exe.
Listing 9-8L shows this method of reverse shell creation in action.
The STARTUPINFO structure is manipulated, and then parameters are passed to CreateProcessA. We see that CreateProcessA is going to run cmd.exe because it is passed as a parameter at \({\color{red}1}\). The wShowWindow member of the structure is set to SW_HIDE at \({\color{red}2}\), which will hide cmd.exe’s window when it is launched. At \({\color{red}3}\), \({\color{red}4}\), and \({\color{red}5}\), we see that the standard streams in the STARTUPINFO structure are set to the socket. This directly ties the standard streams to the socket for cmd.exe, so when it is launched, all of the data that comes over the socket will be sent to cmd.exe, and all output generated by cmd.exe will be sent over the socket.
In summary, we determined that this malware is a simple reverse shell with obfuscated strings that must be renamed ocl.exe before it can be run successfully. The strings are obfuscated using the stack and a multibyte XOR. In Chapter 13, we will cover data-encoding techniques like this in more detail.