【问题标题】:Injecting C++ DLL注入 C++ DLL
【发布时间】:2012-06-07 10:52:55
【问题描述】:

我知道有很多关于这方面的问题和书籍,但我似乎无法将我的 C++ DLL 注入任何进程。

注入DLL的代码:

#include <iostream>
#include "windows.h"

bool Inject(DWORD pId, char *dllName);

using namespace std;

int main()
{
    Inject(600, "C:\\d.dll");
    return 0;
}

bool Inject(DWORD pId, char *dllName)
{
    HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, pId);
    if(h)
    {
        LPVOID LoadLibAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
        LPVOID dereercomp = VirtualAllocEx(h, NULL, strlen(dllName), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        WriteProcessMemory(h, dereercomp, dllName, strlen(dllName), NULL);
        HANDLE asdc = CreateRemoteThread(h, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, dereercomp, 0, NULL);
        WaitForSingleObject(asdc, INFINITE);
        VirtualFreeEx(h, dereercomp, strlen(dllName), MEM_RELEASE);
        CloseHandle(asdc);
        CloseHandle(h);
        return true;
    }
    return false;
}

以及我尝试注入的 DLL:

#include <windows.h>
#include <stdio.h>

BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
switch (reason)
    {
      case DLL_PROCESS_ATTACH:
           MessageBox (0, "From DLL\n", "Process Attach", MB_ICONINFORMATION);
        break;

      case DLL_PROCESS_DETACH:
           MessageBox (0, "From DLL\n", "Process Detach", MB_ICONINFORMATION);
        break;

      case DLL_THREAD_ATTACH:
           MessageBox (0, "From DLL\n", "Thread Attach", MB_ICONINFORMATION);
        break;

      case DLL_THREAD_DETACH:
           MessageBox (0, "From DLL\n", "Thread Detach", MB_ICONINFORMATION);
        break;
    }

    return TRUE;
}

我对 C++ 了解的不够多,无法知道哪里出了问题。我已经在我试图注入的进程上运行了 Process Explorer(进程也以管理员身份运行),但它没有被注入。当我运行它时,什么也没有发生,有什么想法吗?

【问题讨论】:

  • 您是否检查过您打开进程的权限(调试权限)?
  • @Jimmy 我该如何检查这个?
  • 您可以查看msdn.microsoft.com/en-us/library/aa291232(v=VS.71).aspx 或以管理员身份运行进程
  • 您的代码没有任何错误检查,除了 OpenProcess。所以肯定你不知道为什么它不起作用。
  • 使用 OutputDebugString 代替 MessageBox,并使用 DebugView 进行检查。您可能正在访问您的MessageBox,但您只是看不到它是从DllMain 正确调用的。

标签: c++ dll


【解决方案1】:

不要从DllMain 执行MessageBox。为什么?见:

您的消息框在出现之前可能只是死锁。为确保您到达感兴趣的代码行,请改用OutputDebugString。正如您所说您熟悉 Process Explorer,您可能会注意到那里创建的线程(您可以通过在 CreateRemoteThread 中提供最后一个参数来在启动器中获取其标识符)及其在内核库中执行时的锁定状态。

这是你需要输入OutputDebugString的地方:

BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, VOID* pvReserved)
{
    pvReserved;
    TCHAR pszMessage[1024] = { 0 };
    _stprintf_s(pszMessage, _T("GetCurrentProcessId() %d, hModule 0x%p, nReason %d\r\n"), GetCurrentProcessId(), hModule, nReason);
    OutputDebugString(pszMessage);
    /*switch(nReason)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }*/
    return TRUE;
}

要确保的另一件事是您正在加载正确位数的 DLL。 Win32 DLL 进入Win32 进程,或x64 DLL 进入x64 进程。

更新。我是从评论中提出的:这是执行此操作的 Visual Studio 2010 项目的源代码:SVNTrac

  • 您将进程标识符放入源代码中
  • 可执行文件创建远程线程并加载库
  • 该库从 DllMain 开始并生成调试输出
  • DebugView 显示输出
  • ProcessExplorer 向您显示创建的线程,并且您还打印了它的标识符

【讨论】:

  • 感谢您的链接,我应该创建一个函数并从 DllMain 调用该函数吗?
  • 编译器无法识别_stprintf_s_T。我错过了标题吗?文档说stdio.h,但我已经添加了。谢谢
  • 谢谢,但还是不开心。我在 CodeBlocks 中编译,在 VS 中尝试过,但仍然没有任何反应。我看不到任何错误,只是没有消息框。
  • 我昨天尝试了代码,它对我有用,你可以在这里获取完整源代码alax.info/svn/public/trunk/Utilities/InjectLibrary我不明白你遇到了什么样的错误。由于上述答案中提到的原因,您将看不到任何消息框 - 您无法在 DllMain 中获得它。
【解决方案2】:

您可能遇到的问题是您的应用程序中的 LoadLibraryA() 地址可能与目标进程中的地址不同,这是由于ASLR - 一种专门用于阻止您尝试的活动的技术.现代版本的 Windows (Vista+) 默认为系统 DLL 启用此功能

为了做你想做的事,你需要在你的应用程序中实现一个适当的 ThreadProc 来加载你的 DLL,在你的目标进程中分配一些可执行内存 (PAGE_EXECUTE) 内存,将它复制到那里,然后使用这个地址作为你的线程起点。

【讨论】:

  • 谢谢,我不知道 ASLR。是否有任何链接可以找到执行此操作的代码?
  • 似乎随机化只发生在启动时,对吧? stackoverflow.com/questions/8568901/…
  • 这个逻辑是在加载器中实现的,这意味着任何时候一个DLL都会被加载器映射到应用程序的地址空间中。这包括通过导入库链接(启动)或通过 LoadLibrary()/LoadLibraryEx() 加载的 DLL 引入的 DLL。
  • ASLR 仅在启动期间,此后只要两个进程具有相同的位架构(例如 x64、x86),它们将具有相同的系统库及其函数地址,因为 kernel32.dll 具有在每个进程中加载​​到相同的地址。
  • 我还想补充一点,ASLR 用于防止远程代码执行,就像在远程计算机中一样“远程”执行。这样一来,利用缓冲区溢出等的黑客将不知道将 EIP 指向何处来执行特定功能以进行远程连接或其他恶意操作。这并不意味着阻碍同一台计算机上的其他进程。如果是这样的话,它会很容易解决。
【解决方案3】:

管理员帐户不需要隐式拥有 SE_DEBUG 权限。 如果您在 Vista/Win7 下运行,请确保已禁用 UAC。 在尝试打开进程内存之前使用此代码启用它:

BOOL EnableDebugPrivilege()
{
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    if(!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ))
    {
        return FALSE;
    }

    if(!LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ))
    {
        return FALSE;
    }

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if(!AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL ))
    {
        return FALSE;
    }

    if(!CloseHandle( hToken ))
    {
        return FALSE;
    }

    return TRUE;
}

【讨论】:

  • 谢谢 rkosegi,我试过了,但没用。我也已经禁用了 UAC。
【解决方案4】:

我会从别人的工作示例开始,然后从那里开始。 CodeProject 上的示例项目、教程和解释非常扎实。

这是Hooking and DLLs上的一个。

还有another。还有一个google search 给你。

对于某些类型的挂钩,您必须克服权限限制,或者您必须接受不能挂钩每个进程的事实。

将 UI-Access 设置为 true,将可执行文件放在 C:/Program Files/ 中,并对 dll 进行数字签名有助于访问 Windows 中的某些安全窗口。这是一个article,讨论了其中的一些内容。

希望对您有所帮助。

【讨论】:

    【解决方案5】:

    SetWindowsHookEx 还可以将您的 DLL 注入另一个进程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      相关资源
      最近更新 更多