【发布时间】:2016-01-23 18:11:07
【问题描述】:
我正在尝试将 DLL 注入 x64 进程。我的注入器是用 C# 编写的,以 64 位编译。 不调用 DllMain 函数,即使在使用注入器时一切正常。这是我的 DllMain.cpp 代码:
#include <cstdio>
#include <tchar.h>
#include <conio.h>
#include <strsafe.h>
#include <iostream>
#include <fcntl.h>
#include <io.h>
#include "stdafx.h"
#include "InternalLoop.h"
static HANDLE MainThread;
static const WORD MAX_CONSOLE_LINES = 500;
#ifdef _DEBUG
void InstanciateConsole()
{
int hConHandle;
UINT64 lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
AllocConsole();
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
lStdHandle = reinterpret_cast< UINT64 >(GetStdHandle(STD_OUTPUT_HANDLE));
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
lStdHandle = reinterpret_cast< UINT64 >(GetStdHandle(STD_INPUT_HANDLE));
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "r");
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
lStdHandle = reinterpret_cast< UINT64 >(GetStdHandle(STD_ERROR_HANDLE));
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
std::ios::sync_with_stdio();
}
#endif
void initLoop()
{
InternalLoop MainLoop;
MainLoop.MainLoop();
}
extern "C" BOOL APIENTRY
DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
Beep(750, 1000);
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: //When the injector is called.
InstanciateConsole();
printf("%s\n", "Creating thread ...");
MainThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)initLoop, 0, 0, NULL);
if (MainThread)
printf("%s\n", "Thread created !");
else
printf("%s\n", "Thread is not created :(");
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if (MainThread)
CloseHandle(MainThread);
break;
}
return TRUE;
}
哔声未执行,我找不到原因...
` 公共枚举 DllInjectionResult { DllNotFound, GameProcessNotFound, 注入失败, 成功 }
public sealed class DllInjector
{
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
static DllInjector _instance;
public static DllInjector GetInstance
{
get
{
if (_instance == null)
{
_instance = new DllInjector();
}
return _instance;
}
}
public DllInjector() { }
public DllInjectionResult Inject(string sProcName, string sDllPath)
{
if (!File.Exists(sDllPath))
{
return DllInjectionResult.DllNotFound;
}
uint _procId = 0;
Process[] _procs = Process.GetProcesses();
for (int i = 0; i < _procs.Length; i++)
{
if (_procs[i].ProcessName == sProcName)
{
_procId = (uint)_procs[i].Id;
break;
}
}
if (_procId == 0)
{
return DllInjectionResult.GameProcessNotFound;
}
if (!bInject(_procId, sDllPath))
{
return DllInjectionResult.InjectionFailed;
}
return DllInjectionResult.Success;
}
bool bInject(uint pToBeInjected, string sDllPath)
{
IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);
if (hndProc == INTPTR_ZERO)
{
Console.WriteLine("OpenProcess have failed.");
return false;
}
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (lpLLAddress == INTPTR_ZERO)
{
Console.WriteLine("GetProcAddress have failed.");
return false;
}
IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);
if (lpAddress == INTPTR_ZERO)
{
Console.WriteLine("VirtualAllocEx have failed.");
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(sDllPath);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
Console.WriteLine("WriteProcessMemory have failed.");
return false;
}
if (CreateRemoteThread(hndProc, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null) == INTPTR_ZERO)
{
Console.WriteLine("CreateRemoteThread have failed.");
Console.WriteLine(Marshal.GetLastWin32Error());
return false;
}
CloseHandle(hndProc);
return true;
}
}
`
static void Main(string[] args)
{
DllInjector injector = new DllInjector();
string process = "chrome";
string dll = "hv100.dll";
Console.Write("Waiting for chrome.exe to be executed ...\n");
while (!IsProcessOpen(process)) Thread.Sleep(500);
Console.WriteLine("Chrome found !");
DllInjectionResult result = injector.Inject(process, dll);
switch (result) {
case DllInjectionResult.Success:
Console.WriteLine("Injection is sucessful !");
break;
case DllInjectionResult.DllNotFound:
Console.WriteLine("Dll not found.");
break;
case DllInjectionResult.GameProcessNotFound:
Console.WriteLine("Game not found.");
break;
case DllInjectionResult.InjectionFailed:
Console.WriteLine("Injection failed. Something has gone wrong.");
break;
}
Thread.Sleep(5000);
return;
}
}
` 编辑:添加注入器代码
【问题讨论】:
-
DllMain函数不是为执行某些 API 函数而设计的。见这里:msdn.microsoft.com/en-us/library/windows/desktop/… -
好的,但是连哔声也没有执行。我可以使用什么函数来代替 createThread ?
-
底线是
DllMain最适合用于简单的初始化,即分配内存、将全局变量设置为某个值、初始化同步对象等。另外,正如答案所述,使用OutputDebugString显示消息。不要不要使用printf甚至MessageBox来输出消息。 -
注入时DLL是否已经与主进程异步?
-
我们看不到注射器,我们不知道,如果真的有,你怎么想。也许 DLL 永远不会被注入到目标进程中。无法回答,没有看到所有相关代码。
标签: c# c++ winapi dll code-injection