Lab 9-1
Full Analysis available after the questions sections.
Analyze the malware found in the file Lab09-01.exe using OllyDbg and IDA Pro to answer the following questions. This malware was initially analyzed in the Chapter 3 labs using basic static and dynamic analysis techniques.
Full Analysis
As seen in Figure 1.1, our main function starts by comparing the argc with 1. So, if there is one argument specified for this malware upon running, the jump to loc_402B1D will be taken.
Figure 1.1
For now, let’s follow the left side, the one where the jump is not taken.
In Figure 2.1, we can see that there is a call to sub_401000 made.
Figure 2.1
Let’s look into that in Figure 3.1.
Figure 3.1
In here, the malware checks for a registry key, SOFTWARE\Microsoft\XPS. If it is found, it checks for Configuration. When that is also found, the handle to the object is closed and EAX stores the value 1. If it is not found, the program returns to 402B03, so right where we were in Figure 2.1.
We can name this function query_regkey_XPS for easier reading.
Now, let’s keep following the course of action in Figure 2.1. We can see that the EAX register is checked if it is 0. If it is 0 (if the registry key is not found), it jumps to 402B13. At this address, there is a call made to sub_402410, so let’s look into that in Figure 4.1.
Figure 4.1
The malware uses GetModuleFileNameA which means that it wants to get the full path of where it is located. Then, it is using GetShortPathNameA to get the short path of the file.
Also, really interesting for us, is the presence of /c del, which is a sign that the malware might try to delete something. (/c is usually used to create a new shell, execute the provided command and exit from the shell automatically.del is used to delete one or more files) This, in combination with the functions mentioned above, gives us the clue that the malware would try to delete itself.
At the bottom of the figure, repne scasb is called. repne (repeat while not equal) combined with scasb (scan string) are used for block comparions of words. We will see much easily how this works in the debugger.
Furthermore, in Figure 4.2, we can see that there are a lot more string comparions made, especially with » NULL(this redirects the output to the NUL device. It’s basically a virtual black hole. It is a way of not sending any output to the console).
Figure 4.2
In the end, as expected, a cmd.exe shell is created that will run with the above mentioned arguments.
With all the information that we have this far, we can name the function as self_delete.
We’ve come to an end with this left side of the main function. Let’s open the debugger OllyDbg (Figure 5.1) and set a breakpoint at the address of our main function, 0x402AF0 and run the program. We can do this by pressing Ctrl+G and specifying the desired address. From here, we will run (F9) and then press F7 to step into different instructions, and jump over windows functions with F8.
Figure 5.1
Now, let’s press F7 a few times until we get to the first conditional jump. As seen in IDA, this jump was the one checking if we had any arguments upon launching the malware. As seen in Figure 5.2, the jump is not taken.
Figure 5.2
Then, a call is being made to the function at 401000, which we named query_regkey_XPS, as seen in Figure 5.3.
Figure 5.3
In Figure 5.4, we can see that after the execution of the RegOpenKeyExA function, the EAX register holds the 2 value, meaning that it the call to the function wasn’t succesful. So, the jump will not be taken.
Figure 5.4
Then, the function returns, EAX is compared to 0. After that, the function named by us as self_delete is being called. In here, we can easily observe what the malware does. In Figure 5.5, we see how it used GetModuleFileName to get the full path of the executable.
Figure 5.5
After a few iterations in repne scasb, we observe how it checks the string /c del in Figure 5.6.
Figure 5.6
In the end of the function, in Figure 5.7 our assumption is confirmed. EAX stores the command _ /c del PathOfFile » NULL _ , meaning that the malware will delete itself.
Let’s apply what we know for now and reopen the malware in the debugger. This time we will specify a random argument so that we will follow the other chain of code. I’ve randomly chosen exec,as seen in Figure 6.1.
Figure 6.1
Let’s now go to 402B01 which is the address of the jump, made possible by providing an argument.
In Figure 6.2, we can see that now the jump has been taken because we provided an argument to the malware.
Figure 6.2
Now, we will follow address 0x402B1D, to which we would have jumped if we would have had one argument upon running the malware.
Further down, EDX stores the argument that we passed to the malware. In our case, “exec”.
Figure 6.3
Then, it is passed to EAX before calling sub_402510.
Figure 6.4 shows the function sub_402510. At 00402539 EDX, which holds the ascii character “e” from our “exec” string, is compared to 61. This value represents “a” in ASCII. So, the jump is not taken. Because the jump is not taken, the function will return and it will call, in the end, the function self_delete.
Figure 6.4
(Note_1) Now, if we try with “a” as an argument, we encounter the follow chain of code. Inside 402510, ECX is compared with 4 (the value that is stored in ECX from our “a” character is 1), so the jump is not taken. (Figure 6.5).
Figure 6.5
So, we jump to 004025A0, where the function returns us to 402B33 which is right after the step where we check if argc==1. EAX is compared to 0, and the jump at 402B38 to 402B3F is not taken, so we follow 402410 which is our self_delete function. So, we wrote a wrong input to the malware.
The jump that we failed to take was at Note_1. ECX compares the number of characters from our argument with 4. So, let’s use “aaaa” as our input.
Now, in Figure 6.6, we can see that the jump is taken. :) Hooray ! Let’s keep going.
Figure 6.6
I’ve kept an eye on IDA ever since debugging this sample. Let’s look at Figure 6.7, to figure out where we are right now.
Figure 6.7
We’ve already compared our first character with “a”, but then, in the second block after the jump is taken, we can see some arithmetic operations being done that aren’t that easy to spot in IDA. So, let’s go back to OllyDBG to figure out what’s going on.
In Figure 6.8, in the red rectangle, there is a substraction being made. It “substracts” the second character from the first one. Then, it is compared to 1. So, if the difference between them has to be 1, it means that the second character should be 62 in hex. 62 in hex represents “b” in ASCII.
Figure 6.8
With this information in mind, let’s run our program with “abcg”. From the IDA view, it is clear that the next character will be “c”. Let’s see what’s happening next.
In the red rectangle from Figure 6.9, the next comparison takes place. First, 1 is added to AL, which holds the value “c”. So, it becomes “d”. This value is further compared with our “g” that represents, in our case, 67. The jump will not be taken. So let’s make the necessary changes and run the malware once more, but with “abcd” as our arguments.
Figure 6.9
After confirming that “d” is the last character, 1 is saved into the EAX register and the function returns. We can rename this function check_abcd_argument.
Figure 6.10 shows what follows our check_abcd_argument function. EAX is compared to 0. The value that was saved in it after the function call is 1, so we will jump to the right block, to address 402B3F.
Figure 6.10
-in command
Two strings are being compared which are not identified by IDA. But, after double-clicking on byte_40C170 and pressing the “A” key, it’s clear that the “Str2” value is “-in”. (Hex values starting with 2 have an ASCII representation. So we just changed that into ASCII characters). Figure 6.11 represents the value before changing it.
Figure 6.11 - Before pressing "A"
Figure 6.12 - After pressing "A"
Let’s follow this in OllyDBG, as I think it is easier.
Upon further inspecting the program in OllyDbg and following all the possible paths with different arguments, I figured that in the very beginning, the malware checks for the last argument. So our password, “abcd”, should be the last argument.
Now, it compares our argument with “-in”. If it is -in, it jumps to address 00402B63 which represents a cmp for checking if we have 3 arguments. In Figure 6.13, this comp statements can be seen. We are going to jump at 00402B9A because our input has 4 arguments. (the first one is considered to be the name of the file, then the next 3 are our arguments). So, we go further down at 00402BBD.
Figure 6.13
Next, in Figure 6.14, we see an argument being passed as lpServiceName. That represents our second argument; in my case it is bobstar. (this was easy to find out using OllyDbg, Figure 6.15)
Figure 6.14
Figure 6.15 - OllyDbg View
Function sub_402600 that we are going to follow is a pretty big one, so we will analyze it in small steps. Let’s look at Figure 7.1.
Figure 7.1
At first, the sample will just get the splitpath of where it is located. If it is successful, it will try to build a string, which represents the location of system32. It also uses the enivornment variable %SYSTEMROOT%. At 004062CC it tries to open a handle to the service control manager database. This behaviour can be seen in Figure 7.2 and 7.3.
Note 1: Don’t forget to run OllyDbg as an Administrator. If you are not doing this, you will get an ACCESS_DENIED_ERROR when the malware tries to call OpenSCManager, CreateService and other similar functions. So, to be able to keep on debugging, we have to run this sample as an administrator while also being careful of the changes the malware might do to our system.
Figure 7.2
Figure 7.3
Then it tries to access the service “Testing”. Figure 7.4. (I changed the name of the 2nd argument to “Testing” for better visibility)
Figure 7.4
In our case, the service doesn’t exist (as seen in Figure 7.5, we get an ERROR_SERVICE_DOES_NOT_EXIST) so we will make the jump.
Figure 7.5
On the left side of Figure 7.6 is the case where the service that we specified already existed. If it would have, the sample will then proceed to modify it in order to make it run itself, automatically, upon system start-up.
Figure 7.6
On the right side, we can see the process of creating the service name. This is confirmed by OllyDbg in Figure 7.7.
Figure 7.7
In Figure 7.8 we see that upon succeeding to create the service we close the service handle and the manager.
Figure 7.8
So, as of right now, we should have a Service on our machine named Testing Manager Service with the binary path %SYSTEMROOT%\system32\Lab09-01.exe. Let’s check this in Figure 7.9.
Figure 7.9
Then, after the function ExpandEnvironmentStringsA, it will try to move from where it is located right now ( in the default folder for PMA sample ) to %SYSTEMROOT%\system32\Lab09-01.exe so the service can run it succesfully. We can observe this behaviour in Figures 7.10 and 7.11.
Figure 7.10 - NewFileName
Figure 7.11 - NewFileName
Figure 7.12 - CopyFileA returned 1, so it was a success!
Now, it will push the path as an argument and run sub_4015B0. (Figure 7.13)
Figure 7.13
In Figure 7.14 we can see how it tries to get the path to kernel32.dll. Let’s follow that to address 00401618 where it calls sub_4014E0.
Figure 7.14
Using OllyDbg we can easily find what the arguments to this function call are.
Figure 7.15
Then, at the CreateFileA function, the FileName argument is C:\Windows\System32\kernel32.dll which exists, so the function gets a handle to it. Afterwards, it will run the GetFileTime function which retrieves the date and time that a file or directory was created, last accessed, and last modified. (Figure 7.16)
Figure 7.16
Now it will close the handle to kernel32.dll and create the Lab09-01.exe file and set the file time.
Figure 7.17
The function will return.
Let’s look into the call at 004028D8 which has some interesting arguments. (Figure 7.18)
Figure 7.18
This function creates the SOFTWARE\Microsoft\XPS registry key with the above mentioned values in the Configuration key.
Figure 7.19
It then proceeds to close the handles and perform the return call.
After all of this, it finally comes to an end and exits . Note 2: Don’t forget to reverse to a clean snapshot !!
-re command
Taking a quick glance into IDA, we can see tat the check for the -re command also requires 3 or 4 arguments to run a function. Otherwise, it will perform self delete.
Figure 7.20
So, we will run our debugger now with 3 arguments: “-re Testing abcd”.
We set a breakpoint right before the “-re” argument check at 0x402BE7. We pass all the right checks, till we get to an interesting function that takes “Testing” as an argument. (Figure 8.1)
Figure 8.1
Looking at Figure 8.2, we can see that it tries to delete a service. Let’s run olly to see what service it tries to delete.
Figure 8.2
The service that it tries to delete is the one that just got installed. ( or specificed as an argument ) .
As I have just ran this one from a clean install, there is no such service on my machine so it exits right away. Further down the code it also deletes itself. We can rename this function remove_malware.
-c command
We set a breakpoint at 0x402C71 and proceed. For this argument we can see that it sets the Configuration with those 5 values that we should have specified.
Figure 8.3
Figure 8.4
-cc command ( -cc abcd )
For this command, the sample prints to the console the values stored in the Software\Microsoft\XPS registry key.
Lab 9-2
Analyze the malware found in the file Lab09-02.exe using OllyDbg to answer the following questions.
Questions
- What strings do you see statically in the binary?
Figure 9.1 and Figure 9.2 show the strings found using pestudio.
Figure 9.1
Figure 9.2
At the very beginning we can spot cmd, which tells us that it might launch a cmd prompt with additional informations that we will uncover during the analysis.
We can definetly assume that this sample will write files to the system (WriteFile), allocate virtual memory (VirtualAlloc,HeapAlloc), try to create an internet connection to maybe receive or send commands (WSASocket, connect), and also inject code into a remote process through LoadLibrary.
- What happens when you run this binary?
Upon running this binary, nothing happens. It might need special requirements for a proper execution.
- How can you get this sample to run its malicious payload?
In Figure 9.3, we can see the state of the registers which hold right now the strings “Lab09-02.exe” (the name of our binary) and “ocl.exe”.
Figure 9.3
Following the call at 00401236 (which is identified by IDA as strcmp), we can assume that a comparison between the first letter of our executable with “o” from ocl.exe will be made. (“L” is compared to “o”)
Looking back into IDA, if the strings don’t match, the program will exit.
So, if we want to execute this sample, we have to rename it to ocl.exe .
- What is happening at 0x00401133?
Starting with 0x00401133 in Figure 9.4, there are a few operations made with strings in order to obfuscate the “real” strings (such as ocl.exe) that are used by the malware from static analysis tools.
Figure 9.4
- What arguments are being passed to subroutine 0x00401089?
The subroutine 0x00401089 is called at 004012BD, so let’s place a breakpoint right before that, at 004012BC.
In Figure 9.5 we can see that the argument 1qaz2wsx3edc is being passed along with a pointer to a buffer of data.
Figure 9.5
- What domain name does this malware use?
By going through a few number of loops, I found that the malware uses the “www.practicalmalwareanalysis.com” domain.
We can also see this string in the EAX register in FIgure 9.6.
Figure 9.6
- What encoding routine is being used to obfuscate the domain name?
In order to obfuscate the domain name, a XOR loop of the string 1qaz2wsx3edc was used.
- What is the significance of the CreateProcessA call at 0x0040106E?
This address is part of sub_401000, so let’s look into it.
Figure 9.7
We can see that a few arguments are passed to the cmd instance.
Firstly, the ShowWindow value is set to 0 so that the user can’t see the window. Then, the handle to the created socket is being passed to edx.
Afterwards, we can see that hStdInput is being passed. hStdInput is the standard input handle for the process.
So, we encountered a reverse shell. All the data that comes from the socket will be executed by the cmd instance and all the output from the cmd instance will be sent through the socket.
Work in progress
Lab 9-3
Analyze the malware found in the file Lab09-03.exe using OllyDbg and IDA Pro. This malware loads three included DLLs (DLL1.dll, DLL2.dll, and DLL3.dll) that are all built to request the same memory load location. Therefore, when viewing these DLLs in OllyDbg versus IDA Pro, code may appear at different memory locations. The purpose of this lab is to make you comfortable with finding the correct location of code within IDA Pro when you are looking at code in OllyDbg.
-
What DLLs are imported by Lab09-03.exe?
-
What is the base address requested by DLL1.dll, DLL2.dll, and DLL3.dll?
-
When you use OllyDbg to debug Lab09-03.exe, what is the assigned based address for: DLL1.dll, DLL2.dll, and DLL3.dll?
-
When Lab09-03.exe calls an import function from DLL1.dll, what does this import function do?
-
When Lab09-03.exe calls WriteFile, what is the filename it writes to?
-
When Lab09-03.exe creates a job using NetScheduleJobAdd, where does it get the data for the second parameter?
-
While running or debugging the program, you will see that it prints out three pieces of mystery data. What are the following: DLL 1 mystery data 1, DLL 2 mystery data 2, and DLL 3 mystery data 3?
-
How can you load DLL2.dll into IDA Pro so that it matches the load address used by OllyDbg?