DELPHI代码,直截注入别的进程,之后直截运行在别的进程中的代码!


本文整理自网络,侵删。

  

DELPHI代码,直截注入别的进程,之后直截运行在别的进程中的代码!
效果是弹出一个确认框!

本方法不能在98系统下使用!

function createRemoteThread(hProcess: THandle; lpThreadAttributes: Pointer;
dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer;
dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;


第一个参数:目标行程 ID
第二个参数:指定 SD (security descriptor), nil 表示使用预设 SD
第三个参数:堆叠大小, 0 表示使用目标行程预设堆叠大小
第四个参数:开始执行函数的位址
第五个参数:喂进上面函数参数的位址
第六个参数:旗标设定
第七个参数:回传成功后产生的 Thread ID

接着来说明一下,使用流程吧..

1. 取得目标 Process ID (用 FindWindow+GetWindowProcessID or createToolhelp32Snapshot)
2. OpenProcess 并设定 PROCESS_ALL_ACCESS (懒,用这最方便)
3. 使用 VirtualAllocEx 在目标行程内要求两块可执行可读写的空间,一块放函数,另一块放参数
4. 使用 WriteProcessMemory 将函数和参数写进刚刚要求的两块空间
5. 准备完毕,createRemoteThread
6. WaitForSingleObject (等待 Thread 结束)
7. VirtualFreeEx 释放刚刚要求的两块位址

需小心的地方:
1. 别使用 VCL, 连 string 也不能用.
2. 在目标行程执行的程式,无法直接使用 API, 需由 LoadLibraryA & GetProcAddress 来动态载入 dll 来使用 API。但是所有 kernel32.dll 的函数可直接使用, 因为每个行程必定会载入这个 dll, 所以可由本地行程先找好 LoadLibraryA & GetProcAddress 的函数位址,然后塞进参数内
3. 在目标行程执行的程式,如果用到字串的话,要小心! 不可直接用, 需将要使用的字串先写入到参数中
4. 很想用 VCL 的话,目非行程执行的程式就直接载入一个用 delphi 写的 dll 吧 XD

最后,以一个例子当结尾
简单在指定的 Process 秀出一个 MessageBox..
使用了 FindWindow+GetWindowProcessId 取得目标 Process Id

1. 要在目标行程内执行的程式


procedure myMessageBegin(param: PParam); stdcall;
type
   LoadLibraryFunc = function(lib: PChar): DWORD; stdcall;
   GetProcAddressFunc = function(lib: DWORD; name: PChar): DWORD; stdcall;
   MessageBoxFunc = function(handle: DWORD; msg, title: PChar; flag: DWORD): DWORD; stdcall;
var
   myLoad: LoadLibraryFunc;
   myGetProc: GetProcAddressFunc;
   myMsg: MessageBoxFunc;
   hlib: DWORD;
begin
   myLoad := LoadLibraryFunc(param^.fLoadLibrary);
   myGetProc := GetProcAddressFunc(param^.fGetProcAddress);
   hlib := myLoad(@param^.sUser[0]);
   myMsg := MessageBoxFunc(myGetProc(hlib, @param^.sMessage[0]));
   myMsg(0, @param^.sUser[0], @param^.sMessage[0], MB_OK);
end;


看的出来,写的相当迂回 @@

2. 注入函数的参数型别定义


   //要呼叫 MessageBox, 需先 LoadLibrary User32.dll
   //然后再用 GetProcAddress 取得 MessageBox 位址
   //所以需要以下栏位
   // PS: 因为系统 DLL 函数位址在每个行程都一样,
   // 加上每个程行必定含入 kernel32.dll, 所以可以放心先取得
   // LoadLibrary & GetProcAddress 的位址
   PParam = ^TParam;
   TParam = packed record
     fLoadLibrary: DWORD;
     fGetProcAddress: DWORD;
     sUser: array[0..10] of Char;
     sMessage: array[0..11] of Char;
   end;


3. 注入的程式


procedure TForm1.btnInjectClick(Sender: TObject);
var
   hwin, pid: DWORD;
   hprocess: DWORD;
   param: TParam;
   pparam, pfunc: Pointer;
   hlib: DWORD;
   hthread: DWORD;
   s: string;
   v: DWORD;
   iSize: DWORD;
begin
   // 寻找指定视窗
   hwin := FindWindow(nil, PChar(edtName.Text));
   if hwin = 0 then begin
     MessageBox(self.Handle, '找不到指定的视窗!', '讯息', MB_OK or MB_ICONWARNING);
     Exit;
   end;
   // 取得该视窗所属的 Process Id
   GetWindowThreadProcessId(hwin, pid);
   if pid = 0 then begin
     MessageBox(self.Handle, '找不到行程ID', '讯息', MB_OK or MB_ICONWARNING);
     Exit;
   end;
   // 开启这个行程,权限设为 ALL
   hprocess := OpenProcess(PROCESS_ALL_ACCESS, False, pid);
   if hprocess = 0 then begin
     MessageBox(self.Handle, '无法开启行程', '讯息', MB_OK or MB_ICONWARNING);
     Exit;
   end;
   // 在目标行程内要求参数记忆体
   pparam := VirtualAllocEx(hprocess, nil, SizeOf(param), MEM_COMMIT, PAGE_READWRITE);
   if pparam = nil then begin
     MessageBox(self.Handle, '要求参数记忆体失败', '讯息', MB_OK or MB_ICONWARNING);
     CloseHandle(hprocess);
     Exit;
   end;
   // 在目标行程内要求函数记忆体
   // 这里定义一个 myMessageEnd 空函数来判断 myMessageBegin 大小
   iSize := DWORD(@myMessageEnd)-DWORD(@myMessageBegin)+1;
   pfunc := VirtualAllocEx(hprocess, nil, iSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   if pfunc = nil then begin
     MessageBox(self.Handle, '要求函数记忆体失败', '讯息', MB_OK or MB_ICONWARNING);
     CloseHandle(hprocess);
     Exit; 
   end;
   // 初始化参数
   FillChar(param, SizeOf(param), 0);
   hlib := GetModuleHandle('Kernel32.dll');
   param.fLoadLibrary := DWORD(GetProcAddress(hlib, 'LoadLibraryA'));
   param.fGetProcAddress := DWORD(GetProcAddress(hlib, 'GetProcAddress'));
   s := 'user32.dll';
   Move(s[1], param.sUser[0], Length(s));
   s := 'MessageBoxA';
   Move(s[1], param.sMessage[0], Length(s));
   // 写入参数
   WriteProcessMemory(hprocess, pparam, @param, SizeOf(param), v);
   // 写入函数
   WriteProcessMemory(hprocess, pfunc, @myMessageBegin, iSize, v);
   // 准备完毕,跑吧!!
   hthread := createRemoteThread(hprocess, nil, 0, pfunc, pparam, 0, v);
   // 等!
   WaitForSingleObject(hthread, INFINITE);
   // 释放刚刚要求的记忆体
   VirtualFreeEx(hprocess, pfunc, iSize, MEM_DECOMMIT);
   VirtualFreeEx(hprocess, pparam, SizeOf(param), MEM_DECOMMIT);
   // 收尾
   CloseHandle(hprocess);
end;


相关阅读 >>

Delphi 选择文件夹对话框 (有新建文件夹按钮)修正版

Delphi 删除字符串重复的符号只保留一个

Delphi 批量生成 a到z 字母

Delphi 获取局域网所有ip

Delphi xe5 unicodestring的由来

Delphi webbrowser1 网页提交按钮执行点击事件

Delphi向imagelist中加入png类型的资源图片

Delphi输入汉字自动产生拼音简码

Delphi汉字与多字节编码的转换

Delphi radiogroup 组件基本用法

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...