在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
线程注入实例:
我们知道在NT及以上操作系统提供了一个函数VirtualAllocEx,利用这个函数我们可以在其它进程中申请一块内存,其定义如下: function VirtualAllocEx( //在其它进程中申请一块内存 hProcess: THandle;// hProcess为要申请内存的进程的句柄 lpAddress: Pointer;// lPAddress为地址指针,指向需要分配的某地址范围内的页面的起始地址,可以设为nil,由系统确定分配空间的地址. dwSize:dword; //分配内存区域的大小. flAllocationType: DWORD; //flAllocationType为分配类型,在这儿我们设为MEM_COMMIT. flProtect: DWORD//flProtect为新分配内存的存取保护类型,可设为PAGE_EXECUTE_READWRITE来定义其为可执行可读写. ): Pointer; stdcall;//函数执行成功后,将会返回所分配页面的基址.
其中,可以用如下方法得到指定的窗口所属的进程的进程句柄. Function GetProcessHandle: THandle; var
GetWindowThreadProcessId(WndHandle, PID);//以完全访问权限打开进程句柄 Result := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
unit unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; const WM_HOOKED = WM_USER + 3221; //Hook安装成功的消息 type TThreadProVarList = record //变量列表 SendMessage: DWORD; ExitProcess: DWORD; ExitThread: DWORD; //上面用来保存API真实地址 WndHandle: DWORD; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private ThreadAdd: Pointer;//在目标进程中申请的内存地址 PID, PHandle: DWORD; //目标窗口进程ID,句柄和线程ID ThreadHandle, ThreadID: Thandle; //新的远程线程的ID和句柄 procedure WMHOOKED(var Msg: TMessage);message WM_HOOKED; public // Public declarations end; var Form1: TForm1; implementation //$R *.dfm procedure ThreadPro; var VarList: TThreadProVarList; begin asm
mov VarList.SendMessage, eax mov eax, $FFFFFFFF //这个$FFFFFFFF是在上一个偏移位置加8 mov VarList.WndHandle, eax mov eax, $FFFFFFFF mov VarList.ExitProcess, eax mov eax, $FFFFFFFF mov VarList.ExitThread, eax push 0 push 0 push 4245 //4245就是自定义的WM_HOOKED push VarList.WndHandle call VarList.SendMessage push 0 call VarList.ExitThread end; end; procedure TForm1.Button1Click(Sender: TObject); var WndHandle, TmpHandle: THandle;//要注入线程的窗口句柄和临时存放的句柄. DllModule, SendPro, WriteCount: DWORD; ExitPro, ExitTPro: DWORD; begin WndHandle := FindWindow(nil, '记事本');//先查找到要注入远程线程的窗口 GetWindowThreadProcessId(WndHandle, PID);//得到其进程和线程ID PHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);//以完全访问权限打开进程句柄 ThreadAdd := VirtualAllocEx(PHandle, nil, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//在目标进程中分配内存 WriteProcessMemory(PHandle, ThreadAdd, @ThreadPro, 4096, WriteCount);//把自定义函数写入到目标进程中 ThreadHandle := createRemoteThread(PHandle, nil, 0, ThreadAdd, nil, create_SUSPENDED, ThreadID);//以挂起方式建立远端线程,以便修改 DllModule := LoadLibrary('User32.dll');//得到API真实的地址 SendPro := DWORD(GetProcAddress(DllModule, 'SendMessageW')); DllModule := LoadLibrary('Kernel32.dll'); ExitPro := DWORD(GetProcAddress(DllModule, 'ExitProcess')); ExitTPro := DWORD(GetProcAddress(DllModule, 'ExitThread')); //把API真实地址和数据写入到在目标进程中的函数中 TmpHandle := Self.Handle; WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+7), @SendPro, SizeOf(DWORD), WriteCount); WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+15), @TmpHandle, SizeOf(DWORD), WriteCount); WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+23), @ExitPro, SizeOf(DWORD), WriteCount); WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+31), @ExitTPro, SizeOf(DWORD), WriteCount); ResumeThread(ThreadHandle);//开始运行远端线程 CloseHandle(ThreadHandle);// end; procedure TForm1.Button2Click(Sender: TObject); begin VirtualFreeEx(PHandle, ThreadAdd, 4096, MEM_DECOMMIT);//释放在目标进程中分配的内存 CloseHandle(PHandle);//关闭不用的句柄 end; procedure TForm1.WMHOOKED(var Msg: TMessage); begin MessageBox(self.Handle, '建立远端线程成功', '!!!', MB_OK); end; end.{---END---}
mov eax, $FFFFFFFF mov VarList.ExitProcess, eax 的指今,并用WriteProcessMemory写入新变量的值就可以了. 如果是在var中申请变量的话,到函数第一条指今的偏移地址会改变,源程序也要相应改变,可以利用CPU窗口来查看。 注意: 此方法不适用于9x系统. 在线程函数中调用VCL函数也会有问题,因为指向的是自己的进程中的函数地址. 如果使用Pchar类型的字串的话,必须先用VirtualAllocEx函数申请内存,再用WriteProcessMemory写字串到目标进程中并保存下来字串地址,再按传送API地址的方法传送给线程函数就可以使用了. 最后记得使用VirtualFreeEx函数来释放在目标进程中分配的内存. 利用VirtualAllocEx函数还可以实现不需要DLL文件的HOOK技术等. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论