#include <Thread.au3>
Func _UnloadDllEx($sDllName, $iProcessID = @AutoItPid)
If ($iProcessID = -1) Then $iProcessID = @AutoItPid
$iProcessID = ProcessExists($iProcessID)
If ($iProcessID < 1) Then Return SetError(2, 0, 0) ; ERROR_NOT_FOUND
Local $hProcess = _RTOpenProcess($iProcessID)
If ($hProcess < 1) Then Return SetError(@error, 0, 0)
Local $pStartAddr = _RTVirtualAllocEx($hProcess, 1024)
If ($pStartAddr = 0) Then Return SetError(@error, _RTCloseHandle($hProcess), 0)
Local $pDllName = $pStartAddr + 512
Local $tBuffer = DllStructCreate("ubyte ShellX[512];wchar wzDllName[256]")
Local $pBuffer = DllStructGetPtr($tBuffer)
DllStructSetData($tBuffer, "ShellX", __UnloadDllEx_ShellX())
DllStructSetData($tBuffer, "wzDllName", $sDllName)
If _RTWriteProcessMemory($hProcess, $pStartAddr, $pBuffer, 1024) = 0 Then
Return SetError(@error, __UnloadDllEx_Cleanup($hProcess, $pStartAddr), 0)
EndIf
Local $hThread = _RTCreateRemoteThread($hProcess, $pStartAddr + 16, $pDllName)
If ($hThread = 0) Then Return SetError(@error, __UnloadDllEx_Cleanup($hProcess, $pStartAddr), 0)
_RTWaitForObject($hThread)
Local $iStatus = DllCall("Kernel32.dll", "bool", "GetExitCodeThread", "handle", $hThread, "long*", 0)
$iStatus = $iStatus[2]
__UnloadDllEx_Cleanup($hProcess, $pStartAddr, $hThread)
Return SetError($iStatus, 1, $iStatus = 0)
EndFunc ;==>_UnloadDllEx
Func __UnloadDllEx_ShellX()
Local $bBinary = "0x558BEC8B450885C0742B53E8000000005B83EB2050FF1385C0740F50FF530485C0740733C05B5DC2040064A1180000008B4034EBF06A5758EBECCCCC"
Local $tBuffer = DllStructCreate("ptr Functions[4];ubyte ShellX[68]")
DllStructSetData($tBuffer, "Functions", _RTGetProcAddress("Kernel32.dll", "GetModuleHandleW"), 1)
DllStructSetData($tBuffer, "Functions", _RTGetProcAddress("Kernel32.dll", "FreeLibrary"), 2)
DllStructSetData($tBuffer, "ShellX", Binary($bBinary))
Local $tBinary = DllStructCreate("ubyte ShellX[84]", DllStructGetPtr($tbuffer))
Return DllStructGetData($tBinary, "ShellX")
EndFunc ;==>__UnloadDllEx_ShellX
Func __UnloadDllEx_Cleanup($hProcess, $pStartAddr = 0, $hThread = 0, $iReturn = 0)
If $pStartAddr Then _RTVirtualFreeEx($hProcess, $pStartAddr, 1024)
If $hThread Then _RTCloseHandle($hThread)
If $hProcess Then _RTCloseHandle($hProcess)
Return $iReturn
EndFunc ;==>__UnloadDllEx_Cleanup
操作系统会为每个模块维护一个引用计数,模块每加载一次,引用计数加1;每卸载一次,引用计数减1,直到计数达到0时,模块才真正从目标进程空间中删除。
_UnloadDllEx函数 调用示例:
; 卸载notepad.exe进程 加载的hook.dll。
While _UnloadDllEx("hook.dll", "notepad.exe")
WEnd
If @error = 126 Then
MsgBox(48, "OK", "Done.")
Else
MsgBox(48, "Error", "Failed with: " & @error)
EndIf
不要卸载 类似Ntdll.dll、Kernel32.dll、AdvApi32.dll 这样的核心模块,否则这段示例代码将会产生一个死循环。
汇编代码:
019B0010 55 push ebp
019B0011 8BEC mov ebp, esp
019B0013 8B45 08 mov eax, dword ptr [ebp+8]
019B0016 85C0 test eax, eax
019B0018 74 2B je short 019B0045
019B001A 53 push ebx
019B001B E8 00000000 call 019B0020
019B0020 5B pop ebx
019B0021 83EB 20 sub ebx, 20
019B0024 50 push eax
019B0025 FF13 call dword ptr [ebx]
019B0027 85C0 test eax, eax
019B0029 74 0F je short 019B003A
019B002B 50 push eax
019B002C FF53 04 call dword ptr [ebx+4]
019B002F 85C0 test eax, eax
019B0031 74 07 je short 019B003A
019B0033 33C0 xor eax, eax
019B0035 5B pop ebx
019B0036 5D pop ebp
019B0037 C2 0400 retn 4
019B003A 64:A1 18000000 mov eax, dword ptr fs:[18]
019B0040 8B40 34 mov eax, dword ptr [eax+34]
019B0043 ^ EB F0 jmp short 019B0035
019B0045 6A 57 push 57
019B0047 58 pop eax
019B0048 ^ EB EC jmp short 019B0036
019B004A CC int3
019B004B CC int3
|