dll注入完整成功测试源码
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, tlhelp32;
{type
TProcessEntry32 = record
dwSize: DWORD; //大小
cntUsage: DWORD;
th32ProcessID: DWORD; //线程的pid
th32DefaultHeapID: DWORD;
th32ModuleID: DWORD;
cntThreads: DWORD; //线程数
th32ParentProcessID: DWORD; //父线程
pcPriClassBase: integer;
dwFlags: DWORD;
szExeFile: array[0..MAX_PATH - 1] of char; //进程名称
end; } ///说明某个 进程 TProcessEntry32 结构
type
TtoDllFrm = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
toDllFrm: TtoDllFrm;
implementation
{$R *.DFM}
procedure FindAProcess (const AFilename: string; const PathMatch: Boolean; var ProcessID: DWORD); //自定义一个查找a进程的过程,获得pid
var
lppe: TProcessEntry32; // 该进程的结构
SsHandle: Thandle; // 该进程的句柄
FoundAProc, FoundOK: boolean; //是否找到
begin
ProcessID :=0; //初始pid数值
SsHandle := CreateToolHelp32SnapShot(TH32CS_SnapProcess, 0);
//创建进程快照 即进程的瞬时列表表单 TH32CS_SnapProcess,0 表示进程列表
//返回 进程列表的句柄
lppe.dwSize := SizeOf(TProcessEntry32);
//在调用Process32First API之前,需要初始化lppe记录的大小,
郁闷测试几个小时 ,没有初始白忙活 近一天,始终找不到错误
FoundAProc := Process32First(Sshandle, lppe);
//将进程列表的第一个进程信息读入ppe记录中,并判断是否读入成功.
while FoundAProc do //读入成功,进行下面处理
begin
if PathMatch then
FoundOK := AnsiStricomp(lppe.szExefile, PChar(AFilename)) = 0
// AnsiStricomp 返回2字符串类型的比较结果 相同时返回0
else
FoundOK := AnsiStricomp(PChar(ExtractFilename(lppe.szExefile)), PChar(ExtractFilename(AFilename))) = 0;
//比较获得的参数和返回的 ExtractFilename(lppe.szExefile) 值 看是否为 0.
if FoundOK then
begin
ProcessID := lppe.th32ProcessID;
break; //找到后,退出循环
end;
FoundAProc := Process32Next(SsHandle, lppe);
///否则 继续找 直到找到
end;
CloseHandle(SsHandle); // 释放句柄
end;
/
function EnabledDebugPrivilege(const bEnabled: Boolean): Boolean;
//关于提高线程访问权限的提权 并不是什么进程都可以访问
//访问不了 那是权限不够 就提权吧
//这一部分 我也没有弄懂,注释以后在++
var
hToken: THandle;
tp: TOKEN_PRIVILEGES;
a: DWORD;
const
SE_DEBUG_NAME = 'SeDebugPrivilege'; //最高权限
begin
Result := False;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken))
//第一参数是要修改访问权限的进程句柄
//第二个参数指定你要进行的操作类型,要修改令牌我们要指定第二个参数为TOKEN_ADJUST_PRIVILEGES
//第三个参数就是返回的访问令牌指针
then
begin
tp.PrivilegeCount := 1;
LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid);
//返回特权名LUID
//修改进程的权限,在此处为修改本进程成为具有退出系统的权限
//第一个参数是系统的名称,如果是本地系统只要指明为NULL就可以了,
//第三个参数就是返回LUID的指针,第二个参数就是指明了权限的名称,
if bEnabled then
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
tp.Privileges[0].Attributes := 0;
a := 0;
AdjustTokenPrivileges(hToken, False, tp, SizeOf(tp), nil, a);
//第一个参数是访问令牌的句柄;
//第二个参数决定是进行权限修改还是除能(Disable)所有权限
//第三个参数指明要修改的权限
//第四个参数是结构PreviousState的长度,如果PreviousState为空,该参数应为NULL
//第五参数也是一个指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息,可空
Result := GetLastError = ERROR_SUCCESS;
CloseHandle(hToken);
end;
end;
function AttachToProcess(const HostFile, GuestFile: string; const PID: DWORD = 0): DWORD; //自定义注入函数
var
hRemoteProcess: THandle; //远程线程句秉
dwRemoteProcessId: DWORD; //远程线程pid
cb: DWORD;
pszLibFileRemote: Pointer; //一个指针 指向远程dll的地址
iReturnCode: Boolean; //返回值作判断用
TempVar: DWORD;
pfnStartAddr: TFNThreadStartRoutine; //lib函数地址
pszLibAFilename: PwideChar; //一个指向文件名
begin
Result := 0;
EnabledDebugPrivilege(True); //提权
Getmem(pszLibAFilename, Length(GuestFile) * 2 + 1);
//申请内存 内存的大小由Length(GuestFile) * 2 + 1 决定
StringToWideChar(GuestFile, pszLibAFilename, Length(GuestFile) * 2 + 1);
if PID > 0 then
dwRemoteProcessID := PID
else
FindAProcess(HostFile, False, dwRemoteProcessID);
hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + {允许远程创建线程}
PROCESS_VM_OPERATION + {允许远程VM操作}
PROCESS_VM_WRITE, {允许远程VM写}
FALSE, dwRemoteProcessId);
cb := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, cb, MEM_COMMIT, PAGE_READWRITE));
//申请内存,并指向内寸地址 并付值
TempVar := 0;
iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, cb, TempVar);
//写入成功,将返回一个不为0-de 值
if iReturnCode then
begin
pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
//GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址
//GetModuleHandle函数可以返回此句柄
TempVar := 0;
Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
//新生成的线程分配的线程Id 即TempVar
end;
Freemem(pszLibAFilename);
end;
procedure TtoDllFrm.Button1Click(Sender: TObject);
begin
AttachToProcess('Explorer.exe', extractfilepath(paramstr(0))+'Project2.dll');
//其中Project2.dll是想要注入到Explorer.EXE的进程,Explorer.exe也可以是别的进程.
end;
end.