REVERSING RORPIAN – DHCP Hijacking Malware
We have seen our fair share of malware codes from time to time. With the help of disassemblers and debuggers, we have a shot of understanding them. But malware are not that simple to understand, one has to know assembly language. But even knowing the language is not enough by itself, most of the latest malware, if not all, are either packed, encrypted or anything in between.
This paper will be the first of many; in helping us understand deciphering codes that malware has to offer. We will walk through detailed specifics on our way to continuing to help you understand how malware works.
Rorpian worm is the first in line. We will discuss some of its decryption algorithm, how and where it injects its code and some of its common malware activities.
INITIAL DECRYPTION
Rorpian initially allocated a virtual memory space to copy itself. But it doesn’t copy the code as is. It uses a simple decryption algorithm that preserves some of the original malware code and at the same time generates part of the second decryption algorithm.
The malware started decrypting codes at the very end of the file in memory. It decrypted the code using the algorithm shown in Figure 1. Each and every passed on the algorithm generates a single byte and copies it to the allocated virtual memory.
It started slowly. Due to the fact that it is decrypting the code starting at the end of the file, it only produced zeros for at least a couple of hundred bytes. After a couple more dozen bytes, we finally came out with some hexadecimal values that seems unreadable to the naked eye. But after finishing the initial decryption algorithm, we can see that it actually produced almost the same copy of the original malware in the memory. Well, almost.
Figure 1
DISSECTION OF THE INITIAL DECRYPTION
Let’s now take a closer look at the decryption algorithm. The decryption algorithm, shown on Figure 1, looks similar to a regular decryption routine that we seldom see in a malware. But if we take a closer look, you will find out that everything is not what it seems.
The value from DWORD PTR SS:[EBP+10], contains the COUNTER or the number of iterations this block of code will be executed. Its initial value is 0x16000 and will end up at 0. (The counter is counting backwards.)
After executing the first 3 instructions of this decryptor,
MOV EAX,DWORD PTR SS:[EBP+10]
MOV ECX,DWORD PTR SS:[EBP+10]
PUSH EAX,
EAX and ECX registers will contain the value of the counter which is initially 0x16000 and the content of the EAX is then saved to the top of the stack.
Every time the block of code is executed, the first few things that it does is to initialize EAX and ECX with the latest value of the counter and save it at the top of the stack.
And here is that part of the code that applies the “not everything is what they seem to be”.
The following codes below looks complicated but they are not. It actually doesn’t do anything. The last jump instruction, JGE 00401249, will always jump to address 00401249.
1. MOV EAX,DWORD PTR DS:[4064EC]
2. MOV DWORD PTR DS:[EAX],4DDB
3. MOV EAX,DWORD PTR DS:[4064EC]
4. MOV EAX,DWORD PTR DS:[EAX]
5. ADD EAX,004064EC
6. SUB EAX,DWORD PTR DS:[4064EC]
7. ROL EAX,2
8. SUB EAX,2D09
9. ROR EAX,3
10. AND EAX,1CCD
11. CMP EAX,4C
12. JGE 00401249
Let’s see.
At instruction 1, EAX contains any word value from address 0x004064EC (assume that it is 0x004060EC),
EAX = 0x004060EC
At 2, the address pointed by EAX will contain 0x4DDB,
At 3, EAX = 0x004060EC (same as instruction 1)
At 4, EAX will now contain 0x4DDB
At 5, EAX = 0x4DDB + 0x004064EC = 0x0040B2C7
At 6, EAX = 0x0040B2C7 – 0x004060EC = 0x51DB
At 7, EAX = 0x0001476C (after the ROL instruction)
At 8, EAX = 0x0001476C – 0x2D09 = 0x11A63
At 9, EAX = 0x6000234C (after the ROR instruction)
At 10, EAX = 0x6000234C AND 0x1CCD = 0x4C
At 11, the result of CMP EAX,4C will always be TRUE because after the computation, the result will always be 0x4C, therefore At 12, it will always jump to address 0x00401249 .
NOT INCLUDED
Since it will always jump to address 0x00401249, the instructions below will never be executed. The malware includes call to APIs (Application Programming Interface) all throughout the file, but most of them are not called or executed.
PUSH 800048DE
CALL DWORD PTR DS:[
PUSH 80002381
CALL DWORD PTR DS:[
JMP SHORT 00401268
THE REST OF IT
The instructions starting at address 00401249, are not all relevant to the whole decryption routine.
The list of instructions below is only modifying a specific memory location:
0040124F SHR DWORD PTR DS:[4061B8],6
00401256 SHR DWORD PTR DS:[406104],0D
0040125E XOR DWORD PTR DS:[4060F0],64E3
00401269 ROL DWORD PTR DS:[4062D0],6
00401287 SHR DWORD PTR DS:[406318],0A
00401291 XOR DWORD PTR DS:[40623C],1EC7
0040129E SHL DWORD PTR DS:[4062B4],0B
004012AB MOV DWORD PTR DS:[406058],6989
004012B9 MOV DWORD PTR DS:[406308],EBX
RELEVANT INSTRUCTIONS
After weeding out the instructions listed above, the rest of the codes are explained below:
00401249 XOR DWORD PTR DS:[4061A8],EDI
– EDI, starting address of allocated memory, is stored at 0x004061A8
0040125D POP EAX
- EAX contains the counter
00401268 DEC ECX
- decrements the counter
00401270 MOV DWORD PTR SS:[EBP+10],ECX
- saving the counter to [EBP+10]
00401273 OR DWORD PTR DS:[406254],EDI
00401279 TEST EAX,EAX
0040127B MOV DWORD PTR DS:[406174],EAX
- checks if the counter plus the starting address of the allocated memory is the same as the starting address of the allocated memory
00401281 JE df5a4cf5.004012C4
- this instruction will jump out of the decryption routine
0040128E MOV EAX,DWORD PTR SS:[EBP+8]
- EAX contains the starting address of allocated memory
0040129B ADD EAX,DWORD PTR SS:[EBP+10]
- EAX contains the address of allocated memory plus counter
004012A5 MOV ECX,DWORD PTR SS:[EBP+C]
- ECX contains the starting address of the running program
004012A8 ADD ECX,DWORD PTR SS:[EBP+10]
- ECX contains starting address of the malware and counter
004012B5 MOV CL,BYTE PTR DS:[ECX]
- CL contains the byte pointed by the ECX
004012B7 MOV BYTE PTR DS:[EAX],CL
- copies CL to the allocated memory
004012BF JMP df5a4cf5.004011F1
- jumps back to the start of the decryption routine
After a long analysis of this decryptor, only few bytes change from the original codes. The whole 0x16000 iterations of the decryptor code just basically copy the malware to the allocated memory.
The decryptor doesn’t do much, but we saw that some codes even though it looks complicated, they basically just don’t do anything. Even API calls can be deceiving. All throughout the malware code: the original file has lots of instructions that are NOT needed; there are lots of APIs that don’t belong on the actual malware activities. They are designed to make analysis harder.
There are still some layer of sort-of decryptor that lies somewhere in the malware code. But now, we will look into the decryptor that generates the actual malicious codes.
DECRYTOR 2
It started by allocating another virtual memory. This decryptor is way longer than the previous one. We will not walk through each and every code for this decryptor; we will just point to the locations where we can find the important aspect of any decryptor in general.
This decryptor is running at the virtual memory, 0x008A0000, previously created by the initial decryptor.
The initialization of the registers and memory variables before the actual decryption starts at 0x008A7652 (Figure 2). While the end of the whole decryption routine is at address 0x8A7942(Figure 3). A total of 752 (0x2F0) lines of code.
Figure 2
Figure 3.
The jump instruction, JB 008A76B9, from Figure 3, jumps to the very start of the decryption algorithm (Figure 4).
Figure 4.
Another important aspect in analyzing a decryptor is where it will jump out after decrypting everything. In this decryptor, we can find that exit point at address 0x008A7948(Figure 5), just right below the jump to the very beginning of the decryptor algorithm.
Figure 5.
When the instruction pointer reaches the address 0x008A7948, it means that it is done decrypting our malware code.
THE MALWARE
When analysing a malware that is highly encrypted, the first thing to determine if we are doing it right is, if we see some strings generated. The strings in Figure 6 can be seen after the decryptor 2 is fully executed. It has rich information regarding the malware operation. (The IP address was intentionally modified to avoid unnecessary infection from the reader.)
Rorpian tries to download and executes the file from the IP address shown.
Figure 6.
APPLICATION PROGRAMMING INTERFACE (API)
APIs are built-in functions from Windows DLL files; they are the very heart of any Windows application. By listing the APIs used by the malware, we can basically have an idea on what the malware does.
Below is the partial list of APIs(Application Programming Interface) used by Rorpian:
77E37251 ADVAPI32.CreateServiceW
77DE5BED ADVAPI32.CloseServiceHandle
77DF0E4A ADVAPI32.QueryServiceStatusEx
77DF25D8 ADVAPI32.StartServiceA
77DED705 ADVAPI32.OpenSCManagerA
77DEE2AE ADVAPI32.OpenServiceA
7C810647 kernel32.CreateThread
7C80B4DF kernel32.GetModuleFileNameA
7C809F01 kernel32.InitializeCriticalSection
7C80BAB1 kernel32.lstrcmpiA
7C80180E kernel32.ReadFile
7C86158D kernel32.WinExec
7C83647C kernel32.GetPrivateProfileIntA
7C9010E0 ntdll.RtlLeaveCriticalSection
7C85D653 kernel32.MoveFileExA
7C901000 ntdll.RtlEnterCriticalSection
7C8323A9 kernel32.LockFile
7C80B6B1 kernel32.GetModuleHandleA
7C80ADB0 kernel32.GetProcAddress
7C8356A3 kernel32.MoveFileExW
7C8359FF kernel32.GetTempFileNameW
7C80B984 kernel32.UnmapViewOfFile
7C80B915 kernel32.MapViewOfFile
7C809478 kernel32.CreateFileMappingA
7C801625 kernel32.DeviceIoControl
7C831F7B kernel32.DeleteFileW
7C810770 kernel32.CreateFileW
7C82F88F kernel32.CopyFileW
7C809930 kernel32.GetCurrentProcessId
7C8307A5 kernel32.GetTempPathW
7C8017E5 kernel32.GetSystemTimeAsFileTime
7C80E44D kernel32.GetModuleHandleW
7C832B9E kernel32.GetPrivateProfileStringA
7C831EF5 kernel32.DeleteFileA
7C810A87 kernel32.GetFileSize
7C810D97 kernel32.WriteFile
7C860B1F kernel32.GetTempFileNameA
7C835E12 kernel32.GetTempPathA
7C830A82 kernel32.QueueUserWorkItem
7C802442 kernel32.Sleep
7C809AF4 kernel32.VirtualFree
7C809A61 kernel32.VirtualAlloc
7C835D9C kernel32.WritePrivateProfileStringA
7C809B57 kernel32.CloseHandle
7C801A24 kernel32.CreateFileA
7C8314F5 kernel32.SetFileAttributesW
7C812792 kernel32.SetFileAttributesA
7C8092B8 kernel32.GetTickCount
7C8286FE kernel32.CopyFileA
7C90FE21 ntdll.RtlGetLastWin32Error
71B2B2C0 MPR.WNetOpenEnumA
71B2AC75 MPR.WNetEnumResourceA
71B230D7 MPR.WNetCloseEnum
76BF1EB8 PSAPI.GetMappedFileNameA
76BF1E20 PSAPI.GetMappedFileNameW
77E987CB RPCRT4.UuidCreateSequential
7CAB4FD0 SHELL32.ShellExecuteW
77FA8E23 SHLWAPI.PathAddExtensionA
77FA707E SHLWAPI.PathRemoveExtensionA
77F67CA9 SHLWAPI.PathFileExistsW
77F70D83 SHLWAPI.SHGetValueA
77F780C4 SHLWAPI.PathFindFileNameA
77F76494 SHLWAPI.PathAppendA
77F73C33 SHLWAPI.SHSetValueA
77FA6F6F SHLWAPI.PathFileExistsA
77FA14D9 SHLWAPI.SHDeleteValueA
77F66813 SHLWAPI.PathRemoveExtensionW
77F66F97 SHLWAPI.PathFindFileNameW
77F6967F SHLWAPI.SHSetValueW
77F64597 SHLWAPI.SHGetValueW
77D4ACE9 USER32.CharUpperBuffA
77D4DF6B USER32.DefWindowProcA
77D6F002 USER32.CharLowerBuffA
77D5760B USER32.IsCharAlphaA
77D4DED3 USER32.SetWindowLongA
77D6A101 USER32.RegisterDeviceNotificationA
77D6EA45 USER32.GetMessageA
77D48BCE USER32.TranslateMessage
77D4BCBD USER32.DispatchMessageA
77D664EF USER32.UnregisterDeviceNotification
77D4E666 USER32.DestroyWindow
77D5190B USER32.CreateWindowExA
771C4D3C WININET.InternetCloseHandle
771C827C WININET.InternetReadFile
771BB195 WININET.InternetSetOptionA
771B7153 WININET.InternetQueryOptionA
771C60C9 WININET.HttpSendRequestA
771C3674 WININET.HttpOpenRequestA
771C573E WININET.InternetOpenA
771C308A WININET.InternetConnectA
771C7519 WININET.InternetCrackUrlA
7300E3C9 WINSPOOL.AddPrintProvidorW
7C92D195 ntdll.LdrAddRefDll
7C966671 ntdll.RtlRandom
7C901295 ntdll.RtlInitUnicodeString
7C9243CE ntdll.atol
7C910339 ntdll.RtlImageNtHeader
7C91BA32 ntdll._snwprintf
7C9718AA ntdll._snprintf
7C90281D ntdll.strncpy
7C90D08E ntdll.ZwCreateEvent
7C902435 ntdll.memset
7C9015F8 ntdll._chkstk
775285D3 ole32.CoInitialize
774F41C0 ole32.CoUninitialize
77526009 ole32.CoCreateInstance
DROPPED FILE
Rorpian drops a copy of itself in the %temp% folder, with a filename format of srvYYY.tmp. The filename always starts with “srv” followed by the unique processID of the malware, in hexadecimal value, and the extension TMP. This TMP file will be injected to spoolsv.exe process.
The malware also drops an INI file using the TMP’s filename. Figure 7 shows the code snippet for creating the srv files.
Figure 7.
CODE INJECTION
Code injection is the method of loading or adding the malware code to a running process. It can be the complete malware or just a partial code. Injecting codes to a running process ensure that the malware is still running even if the original file execution terminates.
Rorpian injects its code to spoolsv.exe process. One way to know if it already injected its code is by selecting spoolsv.exe process in Process Explorer (from sysinternals) and looking for the file SRVxxx.TMP from the list of files loaded.
(See Figure 8 )
Figure 8.
AS A WORM
Once Rorpian is loaded in spoolsv.exe process, it launches its other malicious activities like dropping files in a shared folder. Rorpian dropped files if a network shared folder is found in the infected machine. The dropped files listed below can be seen in the shared folder:
- setupXXXXX.fon
- setupXXXXX.lnk
- myporno.avi.lnk
- pornmovs.lnk
- autorun.inf
XXXXX in the filename is a random number generated by Rorpian. The file setupXXXX.fon is an exact copy of the first dropped file, srv52C.tmp, which is loaded in the spoolsv.exe process. The lnk files are shortcut files which exploits the vulnerability that automatically launches the setupXXXX.fon. The autorun.inf file is also created to launch the malware when the shared folder is accessed. Figure 9 shows the snapshot of the code that will drop the files and Figure 10 shows the dropped files in the shared folder.
Figure 9.
Figure 10.
DHCP Hijacking
DHCP (Dynamic Host Configuration Protocol) is designed to assign dynamic IP addresses to the computers connected to the network. It greatly helps network administrator in allocating the IP addresses for the computers connected to a given network. It also helps to avoid using duplicate IP addresses.
The DHCP protocol makes sure that the IP addresses given to a single machine will not be in conflict with the rest of the devices. The DHCP server can automatically assign the IP address, subnet mask, default gateway and DNS servers for any client computer connected to the network.
Figure 11.Normal DHCP network setup
DHCP hijacking is a method of intercepting the client’s request for IP addresses from the DHCP server. The hijacking computer intercepts the request before it reaches the valid DHCP server. Note that – the hijacker machine can be any machine connected to the network. Its main purpose is to give the client an IP addresses that is suited for its malicious goal.
Figure 12.Hijacked network setup
HIJACKED BY RORPIAN
One of the main payload of Rorpian is to hijack the DHCP requests made by the computers connected to a network.
Once a single machine is infected by Rorpian, it immediately checks if it is connected to a network. It also checks if the network uses DHCP protocol. Once those checks had been satisfied, it will launch a network listener.
This network listener intercepts DHCP request from the client machines connected to the network. It basically acts as a DHCP server but it only changes the DNS server IP of the client machines.
The new DNS server is a malicious server registered to Rorpian. Any attempts to connect to any website will be checked first against this malicious DNS server. Some reports say that it may also ask for a browser update, (It is not evident during the writing of this paper), which may lead to downloading the malware.
Figure 13.
If the DNS server is not active (as of the case in this writing) you will get a “Server not found” error from your browser as shown in Figure 13. You might find a hard time troubleshooting the problem, because they worked before. You can even scan your machine for viruses but it will show nothing. Perhaps, one of the machines connected to the network is infected by Rorpian.
Figure 14 shows part of the code responsible for the DCHP hijacking. It uses common APIs, like inet_addr and socket, from the Ws2_32.dll; this DLL file contains APIs related to network connections, network protocols, internet access, and so on.
Figure 14.
CONCLUSION
Reversing Rorpian is a bit challenging task. We won’t be able to walkthrough the code if we haven’t seen that it is injecting its code to spoolsv.exe. We can only observe the decryption and the dropping of the srvYYY.tmp file while we are reversing the original malware. But most of its activities are executed within the spoolsv.exe process.
Another interesting fact about Rorpian is its DHCP hijacking. It is a subtle way of redirecting users to a malicious website or a way of downloading the malware. Who would have guessed that somebody just messed up with your DNS server?
We have seen that DHCP hijacking is just a matter of programming. Given the existence of malware capabilities like code injection, code hooking, complicated encryption algorithm, memory manipulation – DHCP hijacking is not really far-fetched. This kind of attack is just around the corner. We will see more of these in different varieties and different combinations. But who is being caught in the crossfire? Of course, us, the users who thought that we were still safe because we installed a couple of antivirus in our computer.
We need more proactive approach against DHCP hijacking. Maybe AV companies needs to have a way of determining if DNS or DHCP setup has been compromised. Or, maybe we can also proactively check if something or someone is waiting to intercept a machine’s request for a DHCP configuration and see if it is valid. Or, maybe, we need to educate our users to be vigilant in anything and everything security.
Safe computing to all!