使用C#在Windows 10上将C ++ DLL注入记事本

时间:2017-02-26 04:13:03

标签: c# .net winapi dll windows-10

bool bInject(uint pToBeInjected, string sDllPath)
    {
        IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);

        if (hndProc == INTPTR_ZERO)
        {
            return false;
        }

        IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        if (lpLLAddress == INTPTR_ZERO)
        {
            return false;
        }

        IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);

        byte[] bytes = Encoding.ASCII.GetBytes(sDllPath);

        WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0);

        // This next one is the one that doesn't seem to work.
        CreateRemoteThread(hndProc, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null);
        CloseHandle(hndProc);

        return true;
    }

我在为x86编译的.NET 4.6.1中使用C#(显然)。 在上面的代码中,我评论了似乎没有工作的命令。 CreateRemoteThread调用。没有错误返回,受害者进程(记事本)没有显示以下DLL的任何迹象(我从示例项目中提取,因为我很懒。)被注入。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

extern "C" __declspec(dllexport)
DWORD WINAPI MessageBoxThread(LPVOID lpParam) {
  MessageBox(NULL, "Hello world!", "Hello World!", NULL);
  return 0;
}

extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD ul_reason_for_call,
                      LPVOID lpReserved) {
  switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
      CreateThread(NULL, NULL, MessageBoxThread, NULL, NULL, NULL);
      break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
      break;
  }
  return TRUE;
}

请记住我正在使用Windows 10.我想也许有额外的安全检查来阻止我注入所说的DLL。在此之后,我计划制作一个引导DLL以加载CLR和另一个C#DLL。

非常感谢您提供的任何帮助!

1 个答案:

答案 0 :(得分:1)

您应该使用预处理器定义作为API调用的标志,它更清晰。

我相信您VirtualAllocEx尝试将PAGE_READWRITE作为标记传递,但是您通过了0x40,而它被定义为#define PAGE_READWRITE 0x04。因此,要么直接使用PAGE_READWRITE,要么想要“酷”,请使用0x04

另外,我从未使用过字符串类,但你应该sDllPath.Length + 1,因为它也可能不会在你的路径中添加空终结符!

为了更准确(在将来的问题中),您可以在问题中添加错误代码!您可以使用:

CHAR Error[MAX_PATH]; // MAX_PATH is used for system paths, it's still big enough
wsprintfA(Error, "Error: %lu", GetLastError());
MessageBoxA(0, Error, 0, 0);

CreateRemoteThread获得system error code之后 - 它可以帮助您随时了解应用程序中的错误!