WinAPI:重新注入后CreateRemoteThread超时?

时间:2018-08-17 14:38:53

标签: c# winapi dll-injection

在托管应用程序中,我将托管dll注入notepad.exe(所有64位),然后调用dll的导出。但是必须有……。因为我的代码不对:

  • 调用导出后,我在Process Explorer中看到模块两次列出。
  • 在注入,调用,弹出和再次注入之后,我无法再调用导出的过程,并且CreateRemoteThread进入超时状态。

那我在做什么错(请参见下面的源代码)?

class Injector
{
    private string _dll = AppDomain.CurrentDomain.BaseDirectory + "MyDLL.dll";

    public bool IsModuleInjected(int pid, string moduleName)
    {
        var process = Process.GetProcessById(pid);

        foreach (ProcessModule module in process.Modules)
        {
            if (!module.FileName.Equals(_dll)) continue;                
            return true;
        }
        return false;
    }

    public bool Inject(int pid)
    {
        var process = Process.GetProcessById(pid);

        if (IsModuleInjected(pid, _dll)) { 
            return false;
        }

        var hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id);

        if (hProcess == IntPtr.Zero)
        {           
            _log.Error("Opening process failed with '{0}'.",
                new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var allocAddress = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)Encoding.Unicode.GetByteCount(_dll.ToCharArray()), AllocationType.Commit, MemoryProtection.ReadWrite);

        if (allocAddress == IntPtr.Zero) { 
            _log.Error("Allocating memory for '{0}' faild with '{1}'.", _dll, new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        if (!WriteProcessMemory(hProcess, allocAddress, Encoding.Unicode.GetBytes(_dll),
            Encoding.Unicode.GetByteCount(_dll.ToCharArray()), out _))
        {
            _log.Error("Writing path to remote process failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var moduleHandle = GetModuleHandle("kernel32.dll");

        if (moduleHandle == IntPtr.Zero) { 
            _log.Error("GetModuleHandle resulted in '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var procAddress = GetProcAddress(moduleHandle, "LoadLibraryW");

        if (procAddress == IntPtr.Zero) {
            _log.Error("Getting address failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var hRemoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, procAddress, allocAddress, 0, IntPtr.Zero);

        if (hRemoteThread == IntPtr.Zero) {
            _log.Error("Creating remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var result = WaitForSingleObject(hRemoteThread, int.MaxValue);

        switch ((WaitForSingleObjectReturnValues)result)
        {
            case WaitForSingleObjectReturnValues.WaitFailed:
                _log.Error("Waiting for remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
                return false;
            case WaitForSingleObjectReturnValues.Timeout:
                _log.Error("Timeout while waiting for remote thread with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
                return false;
        }

        if (!VirtualFreeEx(hProcess, allocAddress, Encoding.Unicode.GetByteCount(_dll), AllocationType.Decommit))
        {
            _log.Error("Freeing memory for dll path failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        if (!CloseHandle(hProcess))
        {
            _log.Error("Closing process handle failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        return true;

    }
    public bool Eject(int pid)
    {
        var process = Process.GetProcessById(pid);

        ProcessModule targetModule = null;

        foreach (ProcessModule module in process.Modules)
        {
            if (module.FileName.Equals(_dll))
            {
                targetModule = module;
            }
        }

        if (targetModule == null)
        {
            _log.Warn("Module '{0}' not inside process. Not calling.", _dll);
            return false;
        }

        var hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id);

        if (hProcess == IntPtr.Zero)
        {
            _log.Error("Opening process failed with '{0}'.",
                new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var moduleHandle = GetModuleHandle("kernel32.dll");

        if (moduleHandle == IntPtr.Zero)
        {
            _log.Error("GetModuleHandle resulted in '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var procAddress = GetProcAddress(moduleHandle, "FreeLibrary");

        if (procAddress == IntPtr.Zero)
        {
            _log.Error("Getting address failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var hRemoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, procAddress, targetModule.BaseAddress, 0, IntPtr.Zero);

        if (hRemoteThread == IntPtr.Zero)
        {
            _log.Error("Creating remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var result = WaitForSingleObject(hRemoteThread, 10 * 1000);

        switch ((WaitForSingleObjectReturnValues)result)
        {
            case WaitForSingleObjectReturnValues.WaitFailed:
                _log.Error("Waiting for remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
                return false;
            case WaitForSingleObjectReturnValues.Timeout:
                _log.Error("Timeout while waiting for remote thread with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
                return false;
        }

        return true;            
    }

    public bool Call(int pid)
    {
        var process = Process.GetProcessById(pid);

        ProcessModule targetModule = null;

        foreach (ProcessModule module in process.Modules)
        {
            if (module.FileName.Equals(_dll))
            {
                targetModule = module;
            }                
        }

        if (targetModule == null)
        {
            _log.Warn("Module '{0}' not inside process. Not calling.", _dll);
            return false;
        }

        var hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id);

        if (hProcess == IntPtr.Zero)
        {
            _log.Error("Opening process failed with '{0}'.",
                new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var hLoaded = LoadLibraryEx(_dll, IntPtr.Zero, LoadLibraryFlags.DontResolveDllReferences);

        if (hLoaded == IntPtr.Zero) {
            _log.Error("Failed loading library with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var procAddress = GetProcAddress(hLoaded, "ShowMessage");

        if (procAddress == IntPtr.Zero)
        {
            _log.Error("Getting address failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }            

        var offset = (ulong)procAddress - (ulong)hLoaded;

        if (!FreeLibrary(hLoaded))
        {
            _log.Error("Unloading library failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var hRemoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, (IntPtr)((ulong)targetModule.BaseAddress + offset), IntPtr.Zero, 0, IntPtr.Zero);

        if (hRemoteThread == IntPtr.Zero)
        {
            _log.Error("Creating remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
            return false;
        }

        var result = WaitForSingleObject(hRemoteThread, 10 * 1000);

        switch ((WaitForSingleObjectReturnValues)result)
        {
            case WaitForSingleObjectReturnValues.WaitFailed:
                _log.Error("Waiting for remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
                return false;
            case WaitForSingleObjectReturnValues.Timeout:
                _log.Error("Timeout while waiting for remote thread with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
                return false;
        }

        if (CloseHandle(hProcess)) return true;
        _log.Error("Closing process handle failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
        return false;

    }
}

0 个答案:

没有答案