back to write-ups
PMA May 3, 2020

PMA Lab 9-3: OllyDbg

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 lo

pmachapter-9

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.

Analysis

Let’s begin by taking a look at the exe.

Looking at the strings of the 4 files, the following ones stand out:

FileInteresting strings
Lab09-03.exeDLL1.dll
DLL2.dll
DLL3.dll
DLL3GetStructure
DLL3Print
malwareanalysisbook.com
DLL1.dll
DLL2.dlltemp.txt
DLL3.dllping www.malwareanalysisbook.com

In terms of Imports, we can see some possible functionalities of this Malware:

  • The Malware may dynamically resolve and import external resources (GetProcAddress, LoadLibraryA, and GetModuleFilenameA)
  • The Malware may write files to the system. (WriteFile)
  • Also, the Malware may allocate memory and use it in some fashion. (VirtualAlloc, HeapAlloc, VirtualFree, HeapFree, etc.)
  • The Malware is importing functions from DLL1 (DLL1Print), and DLL2 (DLL2ReturnJ, and DLL2Print). Since these names are similar to the String DLL3Print and DLL3GetStructure, the Malware will most likely dynamically load DLL3, and use these functions.

Looking at the DLL exports:

  • DLL1 exports the function DLL1Print
  • DLL2 exports DLL2ReturnJ and DLL2Print
  • DLL3 exports DLL3GetStructure and DLLPrint

After executing the file the following content is presented:

image-20200503153236355

Apart from this Window and a file named temp.txt that is created in the same directory of the executable nothing interesting happens. Using procmon we can confirm that DLL3.dll is dynamically loaded by the exe.

Let’s take a look at the exe file in IDA:

From the Graph view, the file isn’t complex:

The executable is actually pretty straightforward:

It starts by calling DLL1Print, DLL2Print, and DLL2ReturnJ. The file then calls WriteFile to write a buffer containing “malwareanalysisbook.com” to a file.

Then, the Malware dynamically loads DLL3.dll with LoadLibrary, it gets the address of DLL3Print with GetProcAddress and calls the function.

Let’s take a look at these “DLLXPrint” functions:

DLL1Print has the following aspect:

image-20200503185421032

As we can see, an address and a string format are being pushed into the stack prior to the printf call. By using Cross References (xrefs) in dword_10008030 we can see that its value is set in DLLMain:

image-20200503161541490

This address will contain the process identifier of the calling process, returned by GetCurrentProcessId.

DLL2Print is pretty similar to DLL1Print:

image-20200503185453946

Using the same technique on dword_1000B078 (using xrefs) we can see that its value is set up in DLLMain as well:

image-20200503161828468

dword_1000B078 will get the return value of CreateFileA which is a handle of file temp.txt.

The function DLL2ReturnJ moves dword_1000B078 to eax and returns (meaning that it will return the handle to temp.txt).

As expected, DLL3Print is similar to DLL1Print and DLL2Print:

image-20200503185602932

The value at offset WideCharStr is set in DLLMain using the API Call MultiByteToWideChar:

image-20200503162808150

In sum, this call converts a string into Unicode. The original string is at offset aPingWww_malwar and the function takes as the lpWideCharStr parameter a pointer to a buffer that receives the converted string. As we can see, that buffer is offset WideCharStr thus, the value that is going to be printed in DLL3Print is the address of the string in Unicode format.

Finally, we have the DLL3GetStructure function. Just like DLL3Print, this function is dynamically loaded with a call to GetProcAddress and a call to the returned Address.

This function takes only one argument. which is a Buffer.

After the call to DLL3GetStructure, NetScheduleJobAdd is called:

image-20200503163731667

This function submits a job to run at a specified future time and date. In terms of parameters the function has the following syntax:

NET_API_STATUS NET_API_FUNCTION NetScheduleJobAdd(
  IN LPCWSTR  Servername,
  IN LPBYTE   Buffer,
  OUT LPDWORD JobId
);

Since Servername is NULL, the local computer will be used. Buffer is a pointer to an AT_INFO structure describing the job to submit and JobId is a pointer that receives a job identifier for the newly submitted job.

As we can see in the following image, the program execution is paused right before the NetScheduleJobAdd call:

image-20200503164256477

The second parameter (highlighted in yellow) in the stack is a pointer to 0x0039B0A0. This value was pushed to the stack (returned) after the call to DLL3GetStructure. In the hex dump, we can see a Unicode string “ping www.malwareanalysisbook.com”. The same string that is converted to Unicode in DLLMain in DLL3.

By now we know that a Task will be scheduled, and is related to DLL3.dll. Let’s execute the Malware and inspect the Scheduled Tasks:

image-20200503174005855

As we can see, this last part of the code creates a new task with the objective of pinging www.malwareanalysisbook.com every day at 1AM.

Questions:

1) What DLLs are imported by Lab09-03.exe?

In the Import Table of Lab09-03.exe we can see the following DLLs:

  • kernel32.dll
  • netapi32.dll
  • DLL1.dll
  • DLL2.dll

However, the Malware also loads DLL3.dll dynamically.

2) What is the base address requested by DLL1.dll, DLL2.dll, and DLL3.dll?

The image-base of the 3 DLLs is 0x10000000.

3) When you use OllyDbg to debug Lab09-03.exe, what is the assigned based address for: DLL1.dll, DLL2.dll, and DLL3.dll?

Inside Olly we can inspect the assigned based addresses for the DLLs with the Memory Map:

image-20200503175538599

The screenshot was taken after DLL3 was Dynamically loaded. As we can see, DLL1 which was the first being loaded got its preferred address: 0x10000000. The other DLLs were rebased, DLL2 was loaded at 0x00330000 and DLL3 at 0x00360000

4) When Lab09-03.exe calls an import function from DLL1.dll, what does this import function do?

DLL1Print prints the string “DLL1 mystery data %d\n” where %d is current PID.

5) When Lab09-03.exe calls WriteFile , what is the filename it writes to?

In the following highlighted instructions prior to the WriteFile function being called, we can see that the return value of DLL2ReturnJ (handle to file temp.txt) is moved from eax to ss:[LOCAL.6] which is later moved to ecx and pushed into the stack as the first argument (hFile) to WriteFile:

image-20200503180913704

Thus, the filename that the Malware writes to is temp.txt.

6) When Lab09-03.exe creates a job using NetScheduleJobAdd , where does it get the data for the second parameter?

The second parameter to NetScheduleJobAdd (Buffer) is returned by DLL3GetStructure.

7) 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?

The Malware prints the following strings during execution:

image-20200503182333436

The meaning of the numbers is:

  • 2524 is the Current PID of Lab09-03.exe.
  • 44 is the value of handle to temp.exe
  • 3780800 is the memory address of Buffer (second argument to NetScheduleJobAdd)

8) How can you load DLL2.dll into IDA Pro so that it matches the load address used by OllyDbg?

As we’ve seen previously, DLL2 was loaded at 0x00330000:

image-20200503182644483

In order to load DLL2.dll into IDA Pro with this address, we can do it in two different ways.

When opening the file, we can either select “Manual Load” :

image-20200503182929128

And then selecting the Address:

image-20200503183002865

Or, after loading DLL2.dll into IDA we can rebase the dll:

Edit >>> Segments >>>Rebase program…

image-20200503183303963

After pressing OK, the addresses should match.