I’m back, it’s been a while. Static Crypt, a malware crypter is using a C based stub now apparently so I am doing an analysis of it. For context, it has been running for a few years and in the past it was using an AutoIt wrapper which executed a C shellcode. The shellcode has significantly changed since then, and the wrapper is now in C.
File Type: MSVC++ PE32 executable.
First thing we notice is there are not-so-legitimate looking resource entries. Considering there are no off-looking sections we can probably assume that the payload and configuration are stored in resource.
The stub uses copy pasted code from github as junk:
It seems that more and more packer are adopting this “technique”. It was also seen in other higher-priced packers like NtCrypt and TitanCrypt.
Setting a breakpoint on kernel32.VirtualProtect and running once, the resulting stack is most interesting. As we can see the third parameter is 0x40, which is PAGE_EXECUTE_READWRITE.
Following 01557450 we can see this confirmed.
Further analysis shows that this is mostly a ripoff of the open source crypter that was released by Luminos months ago. First of all, the jmp-to-entrypoint technique is one that Luminos suggested, as to quote his readme file, “the shellcode needs a JMP instruction added at the top, so it jumps to the entrypoint of it, E9 <32bit little endian>”. This, while functional, is a technique with no good reason to be used, and comes to show how the developer is incompetent and has no experience with using the linker properly to set linking order. Second, we have small push/call/call/ret blocks littered throughout the code.
This is one of the most revealing things about how it is a paste of Luminos’s release: 155B6D5 is equivalent to get_syscall_number and 15578C5 is equivalent to KiFastSystemCall. The disassembly of both confirms this:
Breaking on the entrypoint of the shellcode, we see the same resource names in the first image passed in as parameters. The first call to shellcode+05after the string “initializers” was load_api(), which searched for APIs using hashed name and saved them to an array.
The next 2 calls (I restarted the debugger so the address is now different) to 8E9F05 (or shellcode+2AA5) retrieves the resources that were passed into the shellcode. The second resource is subsequently decrypted in 2 calls a while after that, the first of which obtains the length of the decryption key, and the second perform xor decryption.
After the second call, we get a PE header as expected:
The final call in the function takes in the APIs structure (which contains the address of the APIs resolved by load_apis()) and then executes the actual payload through runpe. The runpe used is copy pasted verbatim from Luminos’s code, as shown by the first few instructions:
As it is a practically exact copy paste, it faces the same many problems that Luminos’s packer had, which I will not detail as I would rather not help the crypter developer fix it. In short, the runpe creates a new process, uses NtCreateSection and NtMapViewOfSection to map the new payload to the process, and then uses SetThreadContext/GetThreadContext and ResumeThread to execute the payload.
Static Crypt also apparently has a rather “sophisticated” startup mechanism, however the file I received did not have such enabled. The post will be updated when I receive a file with such.
Static Crypt is as such in no way an innovative malware of any sort. However, it is interesting to see a previously AutoIt crypter move to C, even if the C version is simply a poorly copy pasted version of an open source packer, which is plenty of improvement compared to the previous AutoIt loader and shellcode. It comes to show how malware developers can easily make use of publicly available resources to make a profit selling their malware.
Archive containing the extracted shellcode and the original file. Standard password for infected files. The file isn’t “actually malicious” as it is simply Putty crypted, but use a VM anyways.