【发布时间】:2016-04-20 17:20:16
【问题描述】:
我在 .NET 中创建了一个启动器,它启动单人游戏并将 DLL 注入其中。 它可以在我自己的机器和其他几台机器上运行,但在某些人的计算机上它似乎神秘地失败了。我不知道可能是什么原因,也不能直接调试它,因为它对我有用。也许你们中的一些人遇到了同样的问题,或者知道可能出了什么问题。
这是启动器的注入代码(.NET Framework 4.5.2,目标平台:Any CPU [首选32bit]):
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”的 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;
}
- Launcher 始终以管理权限启动。
- 操作系统似乎不是问题,因为它在某些情况下可以正常工作并出现故障 具有相同操作系统的人。 (工作在Win8.1 64Bit,Win7 Professional 64 位、Win7 企业版 64 位、Win7 家庭高级版 64 位) (不适用于 Win7 Professional 64Bit、Win 10 64Bit)
- 关闭防病毒软件对他们也不起作用(无论如何,我与有问题的测试人员之一拥有相同的防病毒软件)。
- 在发布模式下编译。
提前谢谢你。
【问题讨论】:
-
这只是一个猜测,但请尝试在 Process.Start 之后执行 WaitForInputIdle()。
-
试过了,没有任何改变。不过谢谢。
标签: c# .net dll code-injection