闲着没事整理了一下DLL的N种注入方法,对学习外挂的朋友,应该有用!
第一种方法:
利用 CreateRemoteThread 远程建立线程的方式注入DLL.
首先,我们要提升自己的权限,因为远程注入必不可免的要访问到目
进程的内存空间,如果没有足够的系统权限,将无法作任何事.下
面是这个函数是用来提升我们想要的权限用的.
function EnableDebugPriv : Boolean;
var
  hToken : THANDLE;
  tp : TTokenPrivileges;
  rl : Cardinal;
begin
waitforsingleobject函数  result := false;
  //打开进程令牌环
  OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
  //获得进程本地唯一ID
  if LookupPrivilegeValue(nil, 'SeDebugPrivilege',
tp.Privileges[0].Luid) then
  begin
    tp.PrivilegeCount := 1;
    tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    //调整权限
    result := AdjustTokenPrivileges(hToken, False, tp,
sizeof(tp), nil, rl);
  end;
end;
关于 OpenProcessToken() 和 AdjustTokenPrivileges() 两个 API
的简单介绍:
OpenProcessToken():获得进程访问令牌的句柄.
  function OpenProcessToken(
    ProcessHandle: THandle; //要修改访问权限的进程句柄
    DesiredAccess: DWORD; //指定你要进行的操作类型
    var TokenHandle: THandle
  ): BOOL; //返回的访问令牌指针
AdjustTokenPrivileges() :调整进程的权限.
  function AdjustTokenPrivileges(
    TokenHandle: THandle;  // 访问令牌的句柄
    DisableAllPrivileges: BOOL; // 决定是进行权限修改还是除
能(Disable)所有权限
    const NewState: TTokenPrivileges;  // 指明要修改的权限,
是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数
据组的每个项指明了权限的类型和要进行的操作;
    BufferLength: DWORD;  //结构PreviousState的长度,如果
PreviousState为空,该参数应为 0
    var PreviousState: TTokenPrivileges; // 指向
TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息
    var ReturnLength: DWORD //实际PreviousState结构返回的大
  ) : BOOL;
远程注入DLL其实是通过 CreateRemoteThread 建立一个远程线程调
用 LoadLibrary 函数来加载我们指定的DLL,可是如何能让远程线程
知道我要加载DLL呢,要知道在Win32系统下,每个进程都拥有自己的
4G虚拟地址空间,各个进程之间都是相互独立的。所我们需要在远程
进程的内存空间里申请一块内存空间,写入我们的需要注入的 DLL
的路径. 需要用到的 API 函数有:
OpenProcess():打开目标进程,得到目标进程的操作权限,详细参
看MSDN
  function OpenProcess(
    dwDesiredAccess: DWORD;  // 希望获得的访问权限
    bInheritHandle: BOOL;  // 指明是否希望所获得的句柄可以继
    dwProcessId: DWORD // 要访问的进程ID
  ): THandle;
VirtualAllocEx():用于在目标进程内存空间中申请内存空间以写入
DLL的文件名
  function VirtualAllocEx(
    hProcess: THandle;  // 申请内存所在的进程句柄
    lpAddress: Pointer;  // 保留页面的内存地址;一般用nil自
动分配
    dwSize,  // 欲分配的内存大小,字节单位;注意实际分 配的
内存大小是页内存大小的整数倍
    flAllocationType: DWORD;
    flProtect: DWORD
  ): Pointer;
WriteProcessMemory():往申请到的空间中写入DLL的文件名
  function WriteProcessMemory(
    hProcess: THandle;  //要写入内存数据的目标进程句柄
    const lpBaseAddress: Pointer; //要写入的目标进程的内存指
针, 需以 VirtualAllocEx() 来申请
    lpBuffer: Pointer; //要写入的数据
    nSize: DWORD; //写入数据的大小
    var lpNumberOfBytesWritten: DWORD //实际写入的大小
  ): BOOL;
然后就可以调用 CreateRemoteThread 建立远程线程调用
LoadLibrary 函数来加载我们指定的DLL.
CreateRemoteThread() //在一个远程进程中建立线程
  function CreateRemoteThread(
    hProcess: THandle;  //远程进程的句柄
    lpThreadAttributes: Pointer; //线程安全描述字,指向
SECURITY_ATTRIBUTES结构的指针
    dwStackSize: DWORD;  //线程栈大小,以字节表示
    lpStartAddress: TFNThreadStartRoutine;  // 一个
TFNThreadStartRoutine类型的指针,指向在远程进程中执行的函数
地址
    lpParameter: Pointer; //传入参数的指针
    dwCreationFlags: DWORD;  //创建线程的其它标志
    var lpThreadId: DWORD //线程身份标志,如果为0, 则不返回
  ): THandle;
整个远程注入DLL的具体实现代码如下:
function InjectDll(const DllFullPath : string; const
dwRemoteProcessId : Cardinal): boolean;
var
  hRemoteProcess, hRemoteThread: THANDLE;
  pszLibFileRemote : Pointer;
  pszLibAFilename: PwideChar;
  pfnStartAddr : TFNThreadStartRoutine;
  memSize, WriteSize, lpThreadId : Cardinal;
begin
  result := FALSE;
  // 调整权限,使程序可以访问其他进程的内存空间
  if EnableDebugPriv then
  begin
    //打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限
    hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE,
dwRemoteProcessId );
    try
      // 为注入的dll文件路径分配内存大小,由于为WideChar,故要
乘2
      GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1);
      // 之所以要转换成 WideChar, 是因为当DLL位于有中文字符
的路径下时不会出错
      StringToWideChar(DllFullPath, pszLibAFilename, Length
(DllFullPath) * 2 + 1);
      // 计算 pszLibAFilename 的长度,注意,是以字节为单元的
长度
      memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof
(WCHAR);
      //使用VirtualAllocEx函数在远程进程的内存地址空间分配
DLL文件名空间
      pszLibFileRemote := VirtualAllocEx( hRemoteProcess,
nil, memSize, MEM_COMMIT, PAGE_READWRITE);
      if Assigned(pszLibFileRemote) then
      begin
        //使用WriteProcessMemory函数将DLL的路径名写入到远程
进程的内存空间
        if WriteProcessMemory(hRemoteProcess,
pszLibFileRemote, pszLibAFilename, memSize, WriteSize) and
(WriteSize = memSize) then