lzmyst 发表于 2011-9-5 17:07:11

[已解决]如何从PID获取进程基址?

本帖最后由 lzmyst 于 2011-9-13 20:38 编辑

我已经通过搜索“基址”查找,没有找到获取进程基址的相关资料
但在http://www.autoitx.com/forum.php?mod=viewthread&tid=27307找到了获取模块基址的方法
还请各位大侠指教获取进程基址的方法!谢谢。

www378660084 发表于 2011-9-5 18:04:19

$pid = ProcessExists("notepad.exe")
$addr = _MemoryModuleGetBaseAddress($pid,"notepad.exe")
MsgBox(0,0,$addr)

lzmyst 发表于 2011-9-5 18:17:12

首先感谢楼上的兄台的回复!
我已经试过你的代码,在实际使用中不起效。
我是想用XueTrCmd卸载某个进程中的特定DLL模块
XueTrCmd在使用时需用到“进程对象地址”,按以上方法取得的基址,和XueTrCmd自身列出的不相同,从而无法使用XueTrCmd卸载指定模块。
PS:XueTrCmd的回显也无法取得,否则直接取XueTrCmd的回显就可以了。

pusofalse 发表于 2011-9-5 18:36:17

创建远程线程。
#include <Thread.au3>

$pGetModuleHandleW = _RTGetProcAddress("Kernel32.dll", "GetModuleHandleW")

$hProcess = _RTOpenProcess("notepad.exe")
$hThread = _RTCreateRemoteThread($hProcess, $pGetModuleHandleW, 0)
_RTWaitForObject($hThread)

$pBaseAddress = DllCall("Kernel32.dll", "bool", "GetExitCodeThread", "handle", $hThread, "ptr*", 0)
$pBaseAddress = $pBaseAddress

_RTCloseHandle($hThread)
_RTCloseHandle($hProcess)

MsgBox(0, "Image Base", $pBaseAddress)

直接读取PE文件。
#include <PeShellX.au3>

$sImagePath = @WindowsDir & "\notepad.exe"
$pFileView = _PeMapFileView($sImagePath, $PE_FILE_READ)

$pBaseAddress = _PeGetImageBase($pFileView)
_PeUnmapFileView($pFileView)

MsgBox(0, "Image Base", $pBaseAddress)

第3种方法,如顶楼链接中说的,先枚举所有模块,然后比较模块名称。

yd111070 发表于 2011-9-5 20:01:19

这个问题我前几天也问了,你通过我的用户名查一下吧。

yd111070 发表于 2011-9-5 20:02:35

还有,找某个软件的基址还可能用到一个叫cheat engine的软件,网上有简单的教程,我也是刚开始研究,祝你好运!

lzmyst 发表于 2011-9-5 20:36:37

本帖最后由 lzmyst 于 2011-9-5 20:57 编辑

感谢P版(偶的仰慕者)及yd111070 的回复!

能请P版提供PeShellX.au3吗?谢谢!

已经试过P说的创建远程线程的方法,取得的地址和取模块基址得到的相同,不是进程对象地址,而模块的基址,XueTrCmd卸载模块时需用到两个地址,一个是进程地址,一个是模块地址
模块地址已经取到,并且和XueTrCmd回显的相同
但进程地址还取不到。
我的本意是想利用XueTrCmd卸载某个模块,如果AU3能直接实现更好,否则我只能用XueTrCmd实现,但XueTrCmd要取得“进程对象地址”才可以卸载,这个难住了我。
以下XueTrCmd列出的EPROCESS:0x894F1020才是需要用到的,而且采用获取模块基址的方法得到的和这个不相同,因此无法使用。T_tools.exe:
      PID:5120      Parent Pid:3440 EPROCESS:0x894F1020
      Path:E:\AU3\autoit3\T_tools.exe
      File Corporation:-

pusofalse 发表于 2011-9-5 22:28:41

#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;wchar wzDllName")
        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

        __UnloadDllEx_Cleanup($hProcess, $pStartAddr, $hThread)
        Return SetError($iStatus, 1, $iStatus = 0)
EndFunc        ;==>_UnloadDllEx

Func __UnloadDllEx_ShellX()
        Local $bBinary = "0x558BEC8B450885C0742B53E8000000005B83EB2050FF1385C0740F50FF530485C0740733C05B5DC2040064A1180000008B4034EBF06A5758EBECCCCC"

        Local $tBuffer = DllStructCreate("ptr Functions;ubyte ShellX")
        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", 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
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
019B0027   85C0                     test    eax, eax
019B0029   74 0F                  je      short 019B003A
019B002B   50                     push    eax
019B002C   FF53 04                  call    dword ptr
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:
019B0040   8B40 34                  mov   eax, dword ptr
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

asdasdasd 发表于 2012-1-26 02:45:19

在卸载如全局钩子或其他的DLL时,会出现目标进程崩溃。。。。
页: [1]
查看完整版本: [已解决]如何从PID获取进程基址?