c# - 试图在我自己的程序中注入一个库
问题描述
我目前正在尝试将一个库注入我制作的程序中(出于学习目的,这只是好奇)。我想我设法做到了,但似乎我所做的代码可能缺少入口点?
这是我编写的代码:我使用 Visual Studio 代码生成了一种 hello-world dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace InjectDll
{
public class Inject
{
[DllImport("kernel32")]
static extern bool AllocConsole();
public Inject()
{
AllocConsole();
Console.WriteLine("blablabla");
}
public string test()
{
AllocConsole();
return "dll is injected";
}
}
}
然后我制作了一个基本程序,我想在其中测试我的注入 =>
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace basicProgram
{
class Program
{
static void Main(string[] args)
{
while(true){
Thread.Sleep(1000);
Console.WriteLine("Hello world");
}
}
}
}
所以现在我有了我的 dll 和我想尝试注射的程序。我只需要编写注射器,这就是我所做的 =>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace injectorTest.Inject
{
public enum DllInjectionResult
{
DllNotFound,
GameProcessNotFound,
InjectionFailed,
Success
}
class Injector
{
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);
//[DllImport("InjectDll.dll", CallingConvention = CallingConvention.StdCall)]
private const string DLL_NAME = "hello.dll";
private Process myProcess;
private string myPath;
public Injector()
{
}
public Injector(Process myProcess)
{
this.myProcess = myProcess;
this.myPath = Path.GetDirectoryName(myProcess.MainModule.FileName);
}
private void checkDll()
{
if (!File.Exists(myPath + @"\hello.dll")) {
}
}
public DllInjectionResult inject()
{
if (!File.Exists(myPath + "\\hello.dll"))
{
return DllInjectionResult.DllNotFound;
}
Console.WriteLine("process id : " + myProcess.Id);
if (myProcess == null)
{
return DllInjectionResult.GameProcessNotFound;
}
if (!startInject((uint)myProcess.Id, myPath + "\\hello.dll"))
{
return DllInjectionResult.InjectionFailed;
}
return DllInjectionResult.Success;
}
private bool startInject(uint processId, string dllPath)
{
IntPtr handleProcess = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, processId);
if (handleProcess == INTPTR_ZERO)
{
return false;
}
IntPtr lpAddress = VirtualAllocEx(handleProcess, (IntPtr)null, (IntPtr)dllPath.Length, (0x1000 | 0x2000), 0X40);
Console.WriteLine("lpaddr: " + lpAddress);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(dllPath);
if (WriteProcessMemory(handleProcess, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (lpLLAddress == INTPTR_ZERO)
{
return false;
}
var remoteThread = CreateRemoteThread(handleProcess, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null);
if (remoteThread == INTPTR_ZERO)
{
return false;
}
CloseHandle(handleProcess);
return true;
}
}
}
它似乎没有失败我可以通过 ida 看到(观看我尝试注入的 helloworld 程序)当我启动我的注入器时 LoadLibraryW 被触发(然后我可以看到注入的 dll 的路径,但它似乎没有触发什么
好像我错过了一些东西(比如我的 dll 中的入口点?)。
解决方案
一个普通的 C/C++ DLL 将有一个 DllMain,它在调用 LoadLibrary 时执行,然后传递到 switch 语句,通常我们将代码放在 DLL_PROCESS_ATTACH 案例中,该案例将在注入时执行。
这个等价物在 C#/CLR 中不存在,但您可以通过使用静态构造函数做一些棘手的事情来产生相同的效果。
创建一个类并初始化该类的一个对象,这将依次调用静态构造函数。像这样的东西:
class someClass
{
//Static constructor
static someClass()
{
Console.WriteLine("injected");
}
}
推荐阅读
- sql - 如何将行展平为列(字段)值
- python - 在熊猫中,如果一个字段中的日期与日期列表中的任何日期匹配,我如何标记数据框中的一行?
- java - 如何将 java 记录器输出 MQTT 重定向到特定 MQTT 代理上的主题
- c++ - 提升如何在graphviz中写入边缘的权重?
- javascript - Oracle Apex:模式对话框关闭时将触发的 DA?
- git - 执行任何 git 命令都会关闭 Ubuntu 中的终端窗口
- python - 熊猫:仅填充数字(int或float)列
- r - 使用 bupaR,我如何将流程和性能图中的计数和时间组合到一张图中?
- r - r 解析中的编织错误(文本=x,srcfile=src)
- python - 在 Python 中一起使用打字模块中的 sys.intern(string) 和 NewType?