unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, TLHelp32, ComCtrls; type TForm1 = class(TForm) Button1: TButton; ListView1: TListView; Button2: TButton; Button3: TButton; OpenDialog1: TOpenDialog; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean); private { Private declarations } public { Public declarations } end; var Form1: TForm1; hProcess:THandle; Procedure GetProcess(); function LoadLibraryA(lpLibFileName: PAnsiChar): HMODULE; stdcall; external kernel32 name 'LoadLibraryA'; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject);begin GetProcess; end; Procedure GetProcess(); var hSnapshot:THandle; pe32:TProcessEntry32; item:TListItem; count:Integer; begin count:=1; hSnapshot:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if hSnapshot=0 then begin Form1.Caption:='创建进程快照失败!'; Abort(); end else begin Form1.Caption:='创建进程快照成功!'; end; pe32.dwSize:=SizeOf(PROCESSENTRY32); if not Process32First(hSnapshot,pe32) then begin Form1.Caption:='获取第'+IntToStr(count)+'个进程失败!'; end else begin Form1.Caption:='获取第'+IntToStr(count)+'个进程成功!'; end; Form1.ListView1.Clear; repeat count:=count+1; Form1.Caption:='获取第'+IntToStr(count)+'个进程成功!'; item:=Form1.ListView1.Items.Add; item.Caption:=IntToStr(pe32.th32ProcessID); item.SubItems.Add(pe32.szExeFile); item.SubItems.Add(IntToStr(pe32.pcPriClassBase)); item.SubItems.Add(IntToStr(pe32.th32ParentProcessID)); until not Process32Next(hSnapshot,pe32); Form1.Caption:='成功获取'+IntToStr(count)+'个进程!'; end; procedure TForm1.Button2Click(Sender: TObject); begin ShowMessage('程序名称:DLL注入'+#13+ '版本:1.0.0.0'+#13+ '日期:2010-10-5'+#13+ '作者:江湖一键客'+#13+ '业务联系QQ:82530662'); end; procedure TForm1.Button3Click(Sender: TObject); var lpBaseAddress:Pointer; flProtect: DWORD; lNOBW: DWORD; fileName:String; len:Integer; wFlag:Bool; pLoadLibrary:FARPROC; lpThreadId:DWORD; hThread:THandle; begin if OpenDialog1.Execute then begin fileName:=OpenDialog1.FileName; len:=Length(fileName)+1; end else begin Abort(); end; lpBaseAddress:=VirtualAllocEx(hProcess,nil,Len,MEM_COMMIT,PAGE_READWRITE); if lpBaseAddress=nil then begin Form1.Caption:='分配虚拟内存失败!'; Abort(); end; Form1.Caption:='分配虚拟内存成功'; wFlag:=WriteProcessMemory(hProcess,lpBaseAddress,pchar(@fileName[1]),len,lNOBW); if (not wFlag) and (lNOBW<>len) then begin Form1.Caption:='写入内存失败!'; VirtualFreeEx(hProcess, lpBaseAddress,len,MEM_COMMIT); CloseHandle(hProcess); Abort(); end; Form1.Caption:='写入内存成功!'; pLoadLibrary:=GetProcAddress(GetModuleHandle('kernel32.dll'),'LoadLibraryA'); if pLoadLibrary=nil then begin Form1.Caption:='获取输出库函数地址失败!'; Abort(); end; Form1.Caption:='获取输出库函数地址成功!'; hThread:=CreateRemoteThread(hProcess,nil,0,pLoadLibrary, lpBaseAddress,0,lpThreadId); if hThread=0 then begin Form1.Caption:='创建远程线程失败!'; end; Form1.Caption:='创建远程线程成功!'; WaitForSingleObject(hThread,INFINITE); VirtualFreeEx(hProcess, lpBaseAddress,len,MEM_COMMIT); CloseHandle(hThread); CloseHandle(hProcess); end; procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean); var dwProcessId:DWORD; begin dwProcessId:=StrToInt(Trim(item.Caption)); hProcess:=OpenProcess(PROCESS_ALL_ACCESS ,False, dwProcessId); if hProcess=0 then begin Form1.Caption:='打开进程失败!'; CloseHandle(hProcess); Abort(); end; Form1.Caption:='打开进程成功!'; end; end.
{下面是所用到的函数的详细说明:
{function VirtualAllocEx(hProcess: THandle; lpAddress: Pointer;
dwSize, flAllocationType: DWORD; flProtect: DWORD):
Pointer; stdcall;
{VirtualAllocEx 函数的作用是在指定进程的虚拟空间保留或提交内存区域,
{ 除非指定MEM_RESET参数,否则将该内存区域置0。
{参数说明:
{hProcess: 申请内存所在的进程句柄。
{lpAddress:保留页面的内存地址;一般用nil自动分配 。
{dwSize:欲分配的内存大小,字节单位;注意实际分 配的内存大小是页内存大小的整数倍
{flAllocationType:可取下面表1的值
{flProtect: 可取下面表2的值
{表1:}
{MEM_COMMIT: 为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
{MEM_PHYSICAL : 分配物理内存(仅用于地址窗口扩展内存)
{MEM_RESERVE: 保留进程的虚拟地址空间,而不分配任何物理存储。
{ 保留页面可通过继续调用VirtualAlloc()而被占用
{MEM_RESET : 指明在内存中由参数lpAddress和dwSize指定的数据无效
{MEM_TOP_DOWN: 在尽可能高的地址上分配内存(Windows 98忽略此标志)
{MEM_WRITE_WATCH:必须与MEM_RESERVE一起指定,使系统跟踪那些被写入
{ 分配区域的页面(仅针对Windows 98)
{表2:}
{PAGE_READONLY: 该区域为只读。如果应用程序试图访问区域中的页的时候,
{ 将会被拒绝访问PAGE_READWRITE 区域可被应用程序读写
{PAGE_EXECUTE: 区域包含可被系统执行的代码。试图读写该区域的操作将被拒绝。
{PAGE_EXECUTE_READ : 区域包含可执行代码,应用程序可以读该区域。
{PAGE_EXECUTE_READWRITE: 区域包含可执行代码,应用程序可以读写该区域。
{PAGE_GUARD: 区域第一次被访问时进入一个STATUS_GUARD_PAGE异常,
{ 这个标志要和其他保护标志合并使用,表明区域被第一次访问的权限
{PAGE_NOACCESS: 任何访问该区域的操作将被拒绝
{PAGE_NOCACHE: RAM中的页映射到该区域时将不会被微处理器缓存(cached)
{********************************优伤的分隔线******************************
{function OpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL;
dwProcessId: DWORD): THandle; stdcall;}
{OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄。
{参数说明:}
{dwDesiredAccess是访问进程的权限。见下面表3
{bInheritHandle 是句柄是否继承进程属性。
{dwProcessId 是进程ID。
{表3}
{PROCESS_ALL_ACCESS 所有能获得的权限
{PROCESS_CREATE_PROCESS 需要创建一个进程
{PROCESS_CREATE_THREAD 需要创建一个线程
{PROCESS_DUP_HANDLE 重复使用DuplicateHandle句柄
{PROCESS_QUERY_INFORMATION 获得进程信息的权限,如它的退出代码、优先级
{PROCESS_QUERY_LIMITED_INFORMATION 获得某些信息的权限,如果获得了
{ PROCESS_QUERY_INFORMATION,
{也拥有PROCESS_QUERY_LIMITED_INFORMATION权限
{PROCESS_SET_INFORMATION 设置某些信息的权限,如进程优先级69
{PROCESS_SET_QUOTA 设置内存限制的权限,
使用SetProcessWorkingSetSize
{PROCESS_SUSPEND_RESUME 暂停或恢复进程的权限
{PROCESS_TERMINATE 终止一个进程的权限,使用TerminateProcess
{PROCESS_VM_OPERATION 操作进程内存空间的权限
(可用VirtualProtectEx和WriteProcessMemory)
{PROCESS_VM_READ 读取进程内存空间的权限,可使用ReadProcessMemory
{PROCESS_VM_WRITE 读取进程内存空间的权限,可使用WriteProcessMemory
{SYNCHRONIZE 等待进程终止
{********************************性感的分隔线******************************
{function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): THandle;
{CreateToolhelp32Snapshot函数功能:函数为指定的进程、进程使用的堆[HEAP]、
{模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。
{参数1说明:dwFlags
{TH32CS_INHERIT 声明快照句柄是可继承的。
{TH32CS_SNAPALL 在快照中包含系统中所有的进程和线程。
{TH32CS_SNAPHEAPLIST 在快照中包含在th32ProcessID中指定的进程的所有的堆。
{TH32CS_SNAPMODULE 在快照中包含在th32ProcessID中指定的进程的所有的模块。
{TH32CS_SNAPPROCESS 在快照中包含系统中所有的进程。
{TH32CS_SNAPTHREAD 在快照中包含系统中所有的线程。
{参数2说明:th32ProcessID
{指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了
{TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE后才有效,在其他情况下该参数被忽略,
{所有的进程都会被快照。
{返回值:
{调用成功,返回快照的句柄,调用失败,返回0。
{********************************优美的分隔线******************************
{PROCESSENTRY32结构}
{tagPROCESSENTRY32 = packed record
dwSize: DWORD; 结构的大小
cntUsage: DWORD; 此进程的引用计数
th32ProcessID: DWORD; 进程ID
th32DefaultHeapID: DWORD; 进程默认堆
th32ModuleID: DWORD; 进程模块IDThis
cntThreads: DWORD; 此进程开启的线程计数
th32ParentProcessID: DWORD; 父进程的ID
pcPriClassBase: Longint; 线程优先权
dwFlags: DWORD;
szExeFile: array[0..MAX_PATH - 1] of Char; 进程全名
end;
{********************************优美的分隔线******************************
{function Process32First(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;
{Process32First 是一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()
{获得当前运行进程的快照后,我们可以利用process32First函数来获得第一个进程的句柄
{参数1说明:hSnapshot
{CreateToolhelp32Snapshot获取进程快照的句柄
{参数2说明:lppe
{TProcessEntry32创建的结构体
{返回值:
{调用成功,返回True,调用失败,返回False。
{********************************优美的分隔线******************************
{function Process32Next(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;
{Process32Next是一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()
{获得当前运行进程的快照后,我们可以利用Process32Next函数来获得下一个进程的句柄
{参数1说明:hSnapshot
{CreateToolhelp32Snapshot获取进程快照的句柄
{参数2说明:lppe
{TProcessEntry32创建的结构体
{返回值:
{调用成功,返回True,调用失败,返回False。
{********************************优美的分隔线******************************
{function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer;
lpBuffer: Pointer;nSize:DWORD; var lpNumberOfBytesWritten: DWORD):BOOL;stdcall;
{WriteProcessMemory是一个写内存函数
{参数说明:
{hProcess: 进程的句柄
{lpBaseAddress: 写入进程的位置(地址)
{lpBuffer: 数据当前存放地址
{nSize: 数据的长度
{lpNumberOfBytesWritten:实际数据的长度
{********************************优美的分隔线******************************
{function LoadLibrary(lpLibFileName: PChar): HMODULE; stdcall;
{LoadLibrary函数载入指定的动态链接库,并将它映射到当前进程使用的地址空间。一旦
{载入,即可访问库内保存的资源。
{参数说明:
{lpLibFileName:指定要载入的动态链接库的名称。
{返回值:
{成功则返回库模块的句柄,零表示失败。
{********************************优美的分隔线******************************
{function CreateRemoteThread(hProcess: THandle;
lpThreadAttributes: Pointer;
dwStackSize: DWORD;
lpStartAddress: TFNThreadStartRoutine;
lpParameter: Pointer;
dwCreationFlags: DWORD;
var lpThreadId: DWORD): THandle; stdcall;
{CreateRemoteThread函数在远程进程中创建线程
{参数说明:
{hProcess:进程句柄
{lpThreadAttributes:线程安全描述字,指向SECURITY_ATTRIBUTES结构的指针
{dwStackSize:线程栈大小,以字节表示
{lpStartAddress:一个LPTHREAD_START_ROUTINE类型的指针,指向在远程进程中执行的函数地址}
{lpParameter:传入参数
{dwCreationFlags:创建线程的其它标志
{lpThreadId:线程身份标志,如果为NULL,则不返回
{返回值:
{成功返回新线程句柄,失败返回nil。
{********************************优美的分隔线******************************
{function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD):
DWORD; stdcall;}
{WaitForSingleObject函数用来检测hHandle事件的信号状态,
{当函数的执行时间超过dwMilliseconds就返回,
{但如果参数dwMilliseconds为INFINITE时函数将直到相应时间
{事件变成有信号状态才返回,否则就一直等待下去,
{直到WaitForSingleObject有返回值才执行后面的代码。
{参数说明:
{hHandle:同步对象的句柄
{dwMilliseconds:超时间隔,单位为毫秒,为INFINITE时超时是无限的
{********************************优美的分隔线******************************
{function GetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
{GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。
{参数说明:
{hModule:DLL模块句柄
{lpProcName:函数名
{返回值:
{如果函数调用成功,返回值是DLL中的输出函数地址。 如果函数调用失败,返回值是nil
{********************************优美的分隔线******************************
{function GetModuleHandle(lpModuleName: PChar): HMODULE; stdcall;
{GetModuleHandle函数获取一个应用程序或动态链接库的模块句柄
{参数说明:
{lpModuleName:模块名,这通常是与模块的文件名相同的一个名字
{返回值:
{如执行成功成功,则返回模块句柄