从用户层高地址往下找
高地址: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版权协议,转载请附上原文出处链接和本声明。