查找kernel32.dll 基地址 特征函数

从用户层高地址往下找

高地址:7ffe0000h (用户层可读的最高地址,之后的地址拒绝访问)

一直扫描到最后一块64k起始页面为止, 因此结束地址9999h

每个pe模块都会加载在64k边界的地址上,  因此每次减64k(10000h)

代码中增加了自己修复的重定位信息, 和异常处理;

***** 不要运行在调试环境中 , 否则异常首先被送到debug中

流程:

1.每次在64k的边界上查看是否是一个pe 

2.如果是,则找到导出表,如果有导出表,根据名字LoadLibraryA / GetProcAddress 来匹配,

  如果有此函数则确定为kernel32.dll

* 这种方式比较傻瓜式 , 只根据一个特征函数名(LoadLibraryA)来搜索

你也可以改成其他在kernel32.dll 中的函数

.386
.model flat, stdcall
option casemap:none

include		windows.inc
include		gdi32.inc
includelib	gdi32.lib
include		user32.inc
includelib	user32.lib
include		kernel32.inc
includelib	kernel32.lib
include msvcrt.inc
includelib msvcrt.lib

.data
buffer db 256 dup(0)
kernerl32_module dd 0

.const
ADDR_BEGIN equ 7ffe0000h
ADDR_END EQU 9999h
szGetProcAddress db 'GetProcAddress',0
szLoadLibraryA DB 'LoadLibraryA',0
szText db 'addr : %08x',0dh,0ah,0
szKernerl32 db 'Kernel32.dll',0

.code
k32_exception_handler proc C pExceptionRecord, pSehStack, pContext, DispatcherContext
	pushad
	assume edi:ptr CONTEXT
	mov edi,pContext
	mov esi,pSehStack

	push [esi+0ch]
	pop [edi].regEbp
	push [esi+8]
	pop [edi].regEip
	push esi
	pop [edi].regEsp
	
	assume edi:nothing
	popad
	mov eax,ExceptionContinueExecution
	ret
k32_exception_handler endp

isPE proc mem:dword
	local ok:dword
	pushad
	mov ok,0
	mov esi,mem
	.if esi == 0
		jmp done
	.endif

	assume esi:ptr IMAGE_DOS_HEADER
	.if [esi].e_magic != IMAGE_DOS_SIGNATURE
		jmp done
	.endif

	add esi,[esi].e_lfanew
	assume esi:ptr IMAGE_NT_HEADERS
	.if	[esi].Signature != IMAGE_NT_SIGNATURE
		jmp done
	.endif

	mov ok,1
done:
	popad
	mov eax,ok
	ret
isPE endp



get_export_api proc module:dword , name_addr:dword
	local api_addr:dword
	local str_len:dword, export_addr:dword
	pushad

	call @F
	@@:
	pop ebx
	sub ebx, offset @B

	assume fs:nothing
	push ebp
	lea eax,[ebx + offset done]
	push eax
	lea eax,[ebx + offset k32_exception_handler]
	push eax
	push fs:[0]
	mov fs:[0],esp

	mov api_addr,0

	assume esi:ptr IMAGE_DOS_HEADER
	mov esi,module
	add esi,[esi].e_lfanew
	assume esi:ptr IMAGE_NT_HEADERS
	mov ebx,[esi].OptionalHeader.DataDirectory[0].VirtualAddress
	.if	ebx == 0
		jmp done
	.endif
	add ebx,module
	mov export_addr,ebx

	mov ecx,-1
	xor eax,eax
	mov edi,name_addr
	cld
	repne scasb
	sub edi,name_addr
	mov str_len,edi

	assume ebx:ptr IMAGE_EXPORT_DIRECTORY
	mov eax,[ebx].AddressOfNames
	add eax,module
	xor edx,edx

	.while edx < [ebx].NumberOfNames
		mov esi,name_addr
		mov ecx,str_len
		mov edi,[eax]
		add edi,module
		cld
		repe cmpsb
		je found
		add eax,4
		inc edx
	.endw
	jmp done

found:
	mov esi,[ebx].AddressOfNameOrdinals
	add esi,module
	xor eax,eax
	mov ax, word ptr [esi + edx * 2]
	mov esi,[ebx].AddressOfFunctions
	add esi,module
	mov edi, dword ptr [esi + 4 * eax]
	add edi,module
	mov api_addr,edi

done:
	pop fs:[0]
	add esp,0ch
	popad
	mov eax,api_addr
	ret
get_export_api endp

getk32_byName proc 
	local k32_addr:dword
	local api_name_addr:dword
	pushad

	call @F
	@@:
	pop ebx
	sub ebx, offset @B

	assume fs:nothing
	push ebp
	lea eax,[ebx + offset read_error]
	push eax
	lea eax,[ebx + offset k32_exception_handler]
	push eax
	push fs:[0]
	mov fs:[0],esp

	mov k32_addr,0
	lea eax,[ebx + offset szLoadLibraryA]
	mov api_name_addr , eax

	mov edi,ADDR_BEGIN
	.while edi > ADDR_END
		invoke isPE,edi
		.if eax
			invoke get_export_api,edi,api_name_addr
			.if eax
				mov k32_addr,edi
				jmp done
			.endif
		.endif

		read_error:
		sub edi,10000h
	.endw

done:
	pop fs:[0]
	add esp,0ch
	popad
	mov eax, k32_addr
	ret
getk32_byName endp


main proc
	
		invoke getk32_byName
	invoke wsprintf , addr buffer , addr szText,eax
	invoke crt_printf,addr buffer
	
	
	
	invoke LoadLibraryA,addr szKernerl32
	invoke wsprintf , addr buffer , addr szText,eax
	invoke crt_printf,addr buffer

	
	

done:
invoke MessageBoxA,0,0,0,MB_OK
	INVOKE ExitProcess,0
	ret
main endp
end main


版权声明:本文为dashoumeixi原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。