汇编动态调用导致分段错误
Assembly dynamic call causes segmentation fault
我正在做一个大学项目,所以我想在 MASM32 中编写一个 PE 感染器。
需要的功能之一是不直接调用需要的函数,而是动态查找它们的地址:
我在内存中搜索 kernel32 库,它的导出 table 我找到了 GetProcAddressName 函数,然后是 GetModuleHandle 函数,然后我加载了 user32 句柄,我将其与 GetProcAdsress 一起使用以获取对函数的访问权限;我的示例中的 MessageBoxA:
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32rt.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.code
start:
mov ebx, dword ptr[esp]
and ebx, 0ffff0000h
.while word ptr[ebx] != 'ZM'
dec ebx
.endw
mov kernelAddr, ebx
mov eax, ebx
add eax, 3Ch
mov eax, dword ptr[eax]
add eax, ebx
pekernelFound:
mov peKernelAddr, eax
mov edx, kernelAddr
mov ebx, eax
add ebx, 78h
mov ebx, dword ptr[ebx]
add ebx, edx
mov ecx, ebx
add ecx, 1ch
mov ecx, dword ptr[ecx]
add ecx, edx
mov functionTableAddr, ecx
mov ecx, ebx
add ecx, 20h
mov ecx, dword ptr[ecx]
add ecx, edx
mov functionNameTableAddr, ecx
mov ecx, ebx
add ecx, 24h
mov ecx, dword ptr[ecx]
add ecx, edx
mov ordinalTableAddr, ecx
searchProcAddressFunc:
mov ebx, functionNameTableAddr
mov esi, dword ptr[ebx]
add esi, kernelAddr
mov edi, offset GetProcAddressName
mov edx, 1
mov ecx, 0 ; l'index
.while edx != 0
mov al, byte ptr [esi]
mov bl, byte ptr [edi]
.if al != bl
.while byte ptr [esi] != 0
inc esi
.endw
inc esi
inc ecx
mov edi, offset GetProcAddressName
.else
.if byte ptr [esi] == 0
mov edx, 0
.else
inc esi
inc edi
.endif
.endif
.endw
mov eax, 2
mul ecx
mov ecx, eax
add ecx, ordinalTableAddr
xor eax, eax
mov ax, word ptr [ecx]
mov ecx, 4
mul ecx
add eax, functionTableAddr
mov eax, dword ptr [eax]
add eax, kernelAddr
mov GetProcAddressAddr, eax
gettingGetModuleHandle:
push offset GetModuleHandleName
push kernelAddr
call GetProcAddressAddr
mov GetModuleHandleAddr, eax
push offset User32DllName
call GetModuleHandleAddr
gettingMessageBox:
mov user32Addr, eax
push offset MessageBoxName
push eax
call GetProcAddressAddr
mov MessageBoxAddr, eax
push MB_OK
push offset hello
push offset hello
push 0
call MessageBoxAddr
push 0
call ExitProcess
hello db "Hello buddy", 0
kernelAddr dd ?
user32Addr dd ?
peKernelAddr dd ?
functionTableAddr dd ?
functionNameTableAddr dd ?
ordinalTableAddr dd ?
GetProcAddressName db "GetProcAddress",0
GetModuleHandleName db "GetModuleHandleA",0
MessageBoxName db "MessageBoxA", 0
MessageBoxAddr dd ?
GetProcAddressAddr dd ?
GetModuleHandleAddr dd ?
User32DllName db "User32.dll",0
end start
结果是调用 MessageBoxAddr 时出现分段错误。
如果我调用原始函数除外,无论在哪里:
push MB_OK
push offset hello
push offset hello
push 0
call MessageBoxA
如果我将此示例放在之前或之后,两个调用都有效,这对我来说完全是胡说八道。
你有线索吗?谢谢
问题已解决:
GetModuleHandle 函数仅在 lib 已经加载到内存中时才起作用,并给出它的句柄。
我改用 LoadLibraryA(找不到 LoadLibrary,我不知道为什么...),它运行良好。还是谢谢 :p
我正在做一个大学项目,所以我想在 MASM32 中编写一个 PE 感染器。 需要的功能之一是不直接调用需要的函数,而是动态查找它们的地址: 我在内存中搜索 kernel32 库,它的导出 table 我找到了 GetProcAddressName 函数,然后是 GetModuleHandle 函数,然后我加载了 user32 句柄,我将其与 GetProcAdsress 一起使用以获取对函数的访问权限;我的示例中的 MessageBoxA:
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32rt.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.code
start:
mov ebx, dword ptr[esp]
and ebx, 0ffff0000h
.while word ptr[ebx] != 'ZM'
dec ebx
.endw
mov kernelAddr, ebx
mov eax, ebx
add eax, 3Ch
mov eax, dword ptr[eax]
add eax, ebx
pekernelFound:
mov peKernelAddr, eax
mov edx, kernelAddr
mov ebx, eax
add ebx, 78h
mov ebx, dword ptr[ebx]
add ebx, edx
mov ecx, ebx
add ecx, 1ch
mov ecx, dword ptr[ecx]
add ecx, edx
mov functionTableAddr, ecx
mov ecx, ebx
add ecx, 20h
mov ecx, dword ptr[ecx]
add ecx, edx
mov functionNameTableAddr, ecx
mov ecx, ebx
add ecx, 24h
mov ecx, dword ptr[ecx]
add ecx, edx
mov ordinalTableAddr, ecx
searchProcAddressFunc:
mov ebx, functionNameTableAddr
mov esi, dword ptr[ebx]
add esi, kernelAddr
mov edi, offset GetProcAddressName
mov edx, 1
mov ecx, 0 ; l'index
.while edx != 0
mov al, byte ptr [esi]
mov bl, byte ptr [edi]
.if al != bl
.while byte ptr [esi] != 0
inc esi
.endw
inc esi
inc ecx
mov edi, offset GetProcAddressName
.else
.if byte ptr [esi] == 0
mov edx, 0
.else
inc esi
inc edi
.endif
.endif
.endw
mov eax, 2
mul ecx
mov ecx, eax
add ecx, ordinalTableAddr
xor eax, eax
mov ax, word ptr [ecx]
mov ecx, 4
mul ecx
add eax, functionTableAddr
mov eax, dword ptr [eax]
add eax, kernelAddr
mov GetProcAddressAddr, eax
gettingGetModuleHandle:
push offset GetModuleHandleName
push kernelAddr
call GetProcAddressAddr
mov GetModuleHandleAddr, eax
push offset User32DllName
call GetModuleHandleAddr
gettingMessageBox:
mov user32Addr, eax
push offset MessageBoxName
push eax
call GetProcAddressAddr
mov MessageBoxAddr, eax
push MB_OK
push offset hello
push offset hello
push 0
call MessageBoxAddr
push 0
call ExitProcess
hello db "Hello buddy", 0
kernelAddr dd ?
user32Addr dd ?
peKernelAddr dd ?
functionTableAddr dd ?
functionNameTableAddr dd ?
ordinalTableAddr dd ?
GetProcAddressName db "GetProcAddress",0
GetModuleHandleName db "GetModuleHandleA",0
MessageBoxName db "MessageBoxA", 0
MessageBoxAddr dd ?
GetProcAddressAddr dd ?
GetModuleHandleAddr dd ?
User32DllName db "User32.dll",0
end start
结果是调用 MessageBoxAddr 时出现分段错误。 如果我调用原始函数除外,无论在哪里:
push MB_OK
push offset hello
push offset hello
push 0
call MessageBoxA
如果我将此示例放在之前或之后,两个调用都有效,这对我来说完全是胡说八道。
你有线索吗?谢谢
问题已解决: GetModuleHandle 函数仅在 lib 已经加载到内存中时才起作用,并给出它的句柄。
我改用 LoadLibraryA(找不到 LoadLibrary,我不知道为什么...),它运行良好。还是谢谢 :p