我在.NET中创建了一个启动器,它启动单人游戏并将DLL注入其中。 它适用于我自己的机器和其他几台机器,但在某些人的计算机上,它似乎神秘地失败了。我不知道原因可能是什么,并且无法直接调试它,因为它可以为我工作。也许你们中的一些人遇到了同样的问题,或者知道可能出现的问题。
这是启动程序的注入代码(.NET Framework 4.5.2,目标平台:任何CPU [更喜欢32位]):
static void StartProcess()
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false;
psi.WorkingDirectory = Path.GetFullPath("..");
psi.EnvironmentVariables.Add("GUCProject", projectName);
psi.FileName = Path.GetFullPath("..\\Gothic2.exe");
Process process = Process.Start(psi);
string dllPath = Path.GetFullPath("UntoldChapters\\" + projectName + "\\NetInject.dll");
//dll injection
if (LoadLibary(process, dllPath) == IntPtr.Zero)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
}
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection : uint
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 nSize, out UInt32 lpNumberOfBytesWritten);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);
public static IntPtr LoadLibary(Process process, String dll)
{
if (process == null || String.IsNullOrWhiteSpace(dll))
return IntPtr.Zero;
byte[] dllb = Encoding.ASCII.GetBytes(dll);
if (dllb == null || dllb.Length == 0)
return IntPtr.Zero;
//Alloc
uint len = (uint)dllb.Length + 1;
IntPtr dllbPtr = VirtualAllocEx(process.Handle, IntPtr.Zero, len, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
if (dllbPtr == IntPtr.Zero)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
//Write dll name
uint tmp = 0;
bool b = WriteProcessMemory(process.Handle, dllbPtr, dllb, (uint)dllb.Length, out tmp);
if (!b)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
IntPtr moduleHandle = GetModuleHandle("kernel32.dll");
if (moduleHandle == IntPtr.Zero)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
IntPtr loadlib = GetProcAddress(moduleHandle, "LoadLibraryA");
if (loadlib == IntPtr.Zero)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
return CreateRemoteThread(process.Handle, IntPtr.Zero, 0, loadlib, dllbPtr, 0, out tmp);
}
没有显示错误消息/异常抛出给它不起作用的人,所有的指针,句柄和路径似乎都很好,但注入的' NetInject.dll&#39的DLLMain ;不被称为。
(目标平台Windows 8.1,工具集VS2015(v140),多字节字符集,无CLR支持)
int WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
// this is just the testing code for the people for which it doesn't work. It doesn't even get till here.
MessageBoxW(NULL, L"Injected!", L"Error!", MB_ICONWARNING | MB_OK | MB_DEFBUTTON2);
return true;
}
提前谢谢。
答案 0 :(得分:0)
见Dynamic-Link Library Best Practices (Windows)。在"一般最佳实践"它说"你永远不应该" ..."调用User32.dll或Gdi32.dll中的函数"来自DllMain。 MessageBox在User32.dll中。即使您使用MessageBox作为测试,您也需要确保遵守通用最佳实践。
是的,我知道通用最佳实践非常有限。当我第一次找到它时,我对此感到惊讶。