본문 바로가기

malware

Supreme Leader's Not-That-Supreme Malwares

728x90

Recently while surfing Reddit, I came across this beautiful subreddit which is dedicated to NK. While reading "mind blowing" miracles of Supreme Leader, I clicked on several links, one link led to another and during my visits to several NK web sites, I came across Korean Central News Agency of DPRK. Just by taking look at very top of the HTML source code of homepage, I saw this code:

As you can see, it's pointing to a relative path. So I just appended /download/FlashPlayer10.zip to kcna.kp domain and I downloaded the file. As soon as I opened the zip files, I just noticed that I received two beautiful gifts from Supreme Leader's news agency. Honored by that, I uploaded both files to Virustotal and I got this and this. Interestingly there is fair enough AV detection rate, but a Google search didn't return much information. So I understood that no analysis has been done specifically on these two pieces of malware. Therefore I decided to take a look at them.

First file is called "Install Flash Player 10 ActiveX.exe". While checking basic details of the file, I noticed that it does have a digital signature! Yeah, I got excited too, but it was an invalid certificate. Actually it's a valid certificate, but file checksum has been modified, so basically it means that the original signed file is altered. See:

At first glance, I determined that it's compiled with Visual C++ 6 and it does have an invalid digital signature. After loading malware in debugger, I just noticed that it tries to create a process with NULL commandline argument and TEMP directory as ModuleFileName argument. See:

Basically, it should return error 0x05 (Access denied). Knowing this, malware subtracts 0x05 from it, which makes EAX value equal to zero. Subsequently it does NEG, SBB and INC operations to finally return 1 from this function. If anything else occur in this function, after returning from this function call, program terminates itself. So this function should return 1 and badCreateProcess API call should set LastError to 5.

Next, it calls SetErrorMode API to tell OS which error types application will control instead of operating system. Those errors are:SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX. These parameters means that whenever these type of exceptions occur in the caller process of the API, Windows will not show critical errors dialog, windows error reporting dialog and file not found dialog. Basically they inspired this idea from supreme leader's ruling method, it doesn't matter how bad everything is, no one is allowed to report a problem.

Next, it opens its own file using _wfopen C function. Then it calls fseek with SEEK_END parameter and -48 as offset to move the file pointer to last 48 bytes of the file. Then it calls fread to read 48 bytes from end of the file.

If you wonder what those 48 bytes are, here it is:

After reading the file and closing it, it checks for a hardcoded signature, which is 0x01914848 and you can see these bytes in image above (at beginning of the 3rd line from the end). If it's not a match, it simply terminates itself. Such a complex integrity check! Wow! After this hardcore integrity check, it proceeds to re-open itself again. This time it allocates 0x5C0 (1472) bytes in memory and moves file pointer to another hardcoded location, which is 0x1D4A90 in this case and afterwards it reads the 0x5C0bytes from file pointer.

Here is what bytes at that location looks like:

After reading the bytes, it creates a new instance of explorer.exe with CREATE_SUSPENDED|IDLE_PRIORITY_CLASS flags. Classic process forking. After checking for successful creation of new process, it uses its own Import Address Table to construct one for forked child process. So there is no dynamic API resolving, simply it reads API addresses from it's own IAT. See:

Also it copies a bunch of hardcoded strings: "rb", "wb", "r+b", "@AE", ".exe" and "open". to a memory location which wil be used as source data to be written on forked memory process.

Now malware having strings and IAT prepared, starts to duplicate it's own process handle, reads current process details by calling GetThreadContext and ReadProcessMemory.

Now it does have an interesting call to a function, this function looks for a pattern in 0x5C0 bytes loaded into memory from file. That signature is 0x78563412, which ASCII representation of first 3 char of these bytes would be "xV4". This signature is located at +0x14 offset of the 0x5C0 bytes in memory. This function returns location of discovered signature in EAX register. Here it stores information about current process and thread context. This process occurs 2 times. It keeps finding signatures and overwriting them with bytes malware wants to use on child process. Finally it calls VirtualProtectEx to set page protection toPAGE_EXECUTE_READWRITE with size of 0x107A (4218 bytes) and  WriteProcessMemory twice to write new 0x5C0 bytes at first and then in second call it writes another 2746 bytes of prepared data onto suspended explorer.exe process. In the end it callsResumeThread and terminates itself. First 0x5C0 bytes is a sort of a shellcode which will be executed on new explorer.exe and second 0xABA bytes contains current process information including full path to current exe file. Both are written concurrently one after another.

Here is what explorer.exe memory looks like after bytes being written, but just before Resumethread being called:

So I replaced the byte at OEP with a 0xCC in order to debug forked process. I did it properly and I was sure I did it right, but I never got new Olly fired up as 0xCC should cause it. I always use this method for malwares that use forking method, but it didn't work for this one, can you guess what's the problem? Let me tell you the answer, do you remember SetErrorMode API call?! Yes! That is the cause. Because by calling that API we already told Windows that we're going to handle our own critical errors and when 0xCC happens, Windows just doesn't call JIT debugger. Anyway, it took me some time to figure it out. So I patched the code which was calling SetErrorMode and this time 0xCC trick worked. So maybe main purpose of SetErrorMode API call was to prevent reverse engineers to use 0xCC trick to debug forked process. Anyway, after knowing that I  even made it easier to debug forket process by just setting breakpoint on WriteProcessMemory and then writing CC on source data address in parent process so bytes will be written with a CC in it and I will just get a new OllyDBG which is paused on 0xCC byte instantly.

Again in forked process, as first step, it calls SetErrorMode API to make sure there won't be a crash reported to user. Then it opens it's original file (as it does have address of it in memory) using _wfopen function. Again it reads the last 0x30 bytes of it. Next, malware copies itself to TEMP folder and calls GetTempFileName with @AE string (passed by main process). As a result windows generates a temporary filename with full path in TEMP folder and filename starting with @AE string. Then malware appends .exe to the filename and creates the file. In my case it was @AEA979.tmp.exe in TEMP folder. As creation flag it uses next string passed to it by main process which is "wb". Everything being ready, it reads 0x1A81E8 bytes from offset 0x1D5050. All these values are hardcoded in the malware. I know you all wondered what is the last 0x30 bytes that this malware keeps reading from end of the file, here is the answer, that's an XOR key for decrypting this part of malware. So decryption key is 0x10 bytes from last 0x30 bytes of malware. Also as an additional step of decryption it does have a ROL 0x03 call on each byte.

This part of decrypted bytes, assembles the main malware code. After writing decrypted bytes to temporary file, it callsShellExecuteW API to run it.

Now as much as supreme leader prefers to read news of people who came to read news, he also likes the stealth. He likes to read their news while they are not aware that he's reading their news. Therefore, malware moves the file pointer to 0x1D3490and reads 0x149E88 bytes from that location. Then it runs the same decryption loop (ROL 3 and XOR). Consequently it reads and writes other parts of original binary to finally form the original Flash player installer. Even digital signature is valid on the newly created file, see:

Then malware runs the real Flash player installer in order to show main purpose of it, which is delivering Flash player to visitors, not infecting them. Another interesting point of malware is setting DateTime of dropped file equal to main dropper DateTime.

In the end it terminates itself by calling ExitProcess.

This was everything about the dropper. Here is the icon and other information of dropped malware:

Quality of icon is not good as you can see, it's a 16x16 8-bit icon, best available format in NK.

The dropped malware does have the same stupid "CreateProcess with NULL commandline and TEMP directory as ModuleFileName" call and check for 0x05 error code. If someone really have an idea what they "really" mean by that, please let me know.

Second stage of malware file does have a "unique" API resolving technique which is really "smart"! It pushes every single letter of API name one by one into stack, then calls a function to copy letters from stack one by one to a memory location and then point to that memory location by a register. If you can't believe it, here is the screen shot:

After solving all APIs using this "advanced" method, it does something even more sophisticated and "advanced". It decrypts next phase of malware using Rijndael with a hardcoded key which is 1234567890123456

Also if you are interested about the code they used for Rijndael and where they found it, let me help you, they got it from right here.

Anyway, after decryption, it copies itself in following locations:

and also copies itself to AppData\Roaming\Microsoft\Defender\launch.exe

Characteristics of launch.exe:

MD5: DAAC1781C9D22F5743ADE0CB41FEAEBF

SHA-1: E2549EEEEA42A6892B89D354498FCAA8FFD9CAC4

Characteristics of WdExt.exe

MD5: 75AA66F3B633D4DB271D1FE16E15ABD2

SHA-1: 75780AB993295E8FF188DF4A82995FF7412096D6

 

728x90