This method does not apply to 9X systems. We know that in NT and above provide a function VirtualAlaLalkEx, we can apply for a memory in other processes, which defines the following Function Virtualalocex (HProcess: Thandle; LPADDress: Pointer; DWSIZE, FLallocationType: DWORD; flprotect: DWORD: POINTER; stdcall; where HProcess is the handle of the process to apply for memory, you can use the following method to get the process handle of the process to which the specified window belongs .Function getProcessHandle: Thandle; var WndHandle, Pid: thanle Begin WndHandle: = FINDWINDOW (NIL, 'Window Name "; {Get it processes and thread id} getWindowThreadProcessid (WndHandle, PID); {Open process handle with full access} Result: = OpenProcess (Process_All_Access, false, pid) ;
LPADDRESS is the address pointer, pointing to the start address of the page that needs to be assigned, can be set to nil, determine the address of the allocation space by the system. Dwsize is the size of the memory area. FlalocationType is allocated, here we set up For MEM_COMMIT.FLPROTECT for the access protection type of the newly allocated memory, it can be set to Page_Execute_ReadWrite to define it to perform readable and writable. After the function is executed, the base address of the assigned page will be returned.
After successfully apply for memory, we can use the WriteProcessMemory function to write the code of the thread function in your own process to the target process, then call the CreateRemTHREAD function to create a remote thread. The definition and parameter type is similar to CreateThread.
It seems that everything seems to be OK, in fact, there is still a trouble problem. If the API function is called in the remote thread, the call error will appear, because when the API is called, the compiler does not generate instructions that directly call the API. Instead, write the address corresponding to the corresponding API when the process is loaded, and the CALL command calls the true API function according to this address, but the corresponding API address placed in each process is not the same, so we have to find themselves. Out of the real address of the API (with loadLibrary and getprocaddress), you can write it to the target process. However, this is not easy, because the variables are required in the thread function, it is necessary to relocate the variable for the function base. The displacement of the site is very troublesome. After esculating the second class to study Delphi's CPU window, I finally found a way to expand. It is the use of structural variables.
Let's take a look at the example below. UNIT UNIT1;
Interface
Uses Windows, Messages, Sysutils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Stdctrls;
Const WM_HOOKED = WM_USER 3221; {Hook Installation Successful Message}
Type tthreadProvarlist = Record {Variable List} SendMessage: DWORD; EXITPROCESS: DWORD; EXITTHREAD: DWORD; {Top Used to Save API Real Address} WNDHANDLE: DWORD;
TForm1 = class (TForm) Button1: TButton; Button2: TButton; procedure Button1Click (Sender: TObject); procedure Button2Click (Sender: TObject); private {memory address filed in the target process} ThreadAdd: Pointer; PID, PHandle: DWORD ; {target window process ID, handle and thread ID} ThreadHandle, ThreadID: Thandle; {new remote thread ID and handle} 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 eax, $ FFFFFFFF {$ FFFFFFFF is offset to 7} mov VarList.SendMessage, eax mov eax, $ FFFFFFFF {$ FFFFFFFF this is to add an offset in position 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 is WM_HOOKED custom} push VarList.WndHandle call VarList.SendMessage Push 0 Call varlist.exitthread end;
procedure TForm1.Button1Click (Sender: TObject); var {injected window handle to the thread and temporary storage handle} WndHandle, TmpHandle: THandle; DllModule, SendPro, WriteCount: DWORD; ExitPro, ExitTPro: DWORD; begin {First to find Inject the window of the remote thread} WNDHANDLE: = FINDWINDOW (NIL, 'Notepad'); {gets its process and thread id} getWindowThreadProcessId (WndHandle, PID); {Open process handle in full access} Phandle: = OpenProcess (Process_all_Access, false, PID); {allocate memory in the target process} ThreadAdd: = VirtualAllocEx (pHandle, nil, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE); {-defined function written into the target process} WriteProcessMemory (pHandle, ThreadAdd, @ThreadPro, 4096, WriteCount); {Establish a remote thread in a hang to modify} threadHandle: = CreateRemoteThread (Phandle, NIL, 0, Threadadd, nil, create_suspended, threadid); {Get API true address} DllModule: = loadingLibrary ( 'User32.dll'); SendPro: = DWORD (GetProcAddress (DllModule, 'SendMessageW')); DllModule: = LoadLibrary ( 'Kernel32.dll'); ExitPro: = DWORD (GetProcAddress (DllModule, 'ExitProcess')); ExitTPro : = DWORD (GetProcadDress (DLLModule, 'ExitThread'); {write API real address and data to functions in the target process} TMPHANDLE: = SEL f.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); {Start running remote thread} ResumeThread (threadHandle); CloseHandle (ThreadHandle);
procedure TForm1.Button2Click (Sender: TObject); begin {release the memory allocated in the target process} VirtualFreeEx (PHandle, ThreadAdd, 4096, MEM_DECOMMIT); {close unused handle} CloseHandle (PHandle); end; procedure TForm1.WMHOOKED ( Var msg: tMessage); Begin MessageBox (self.handle, 'Establishing remote thread success', '!!!', mb_ok);
End.
To add a variable in the thread function, add it in the TTHREADPROVARLIST type, then add a normality similar to MOV Eax, $ fffffff, Eax, and write the value of the new variable with WriteProcessMemory. If the application variable is applied in the VAR, the offset address to the function will change, and the source program must also change accordingly, you can use the CPU window to view. If you have better variables, the method is also available please tell me. Note that there will be problems in the thread function, because pointing to the function address in your own process. If you use a PCHAR type string, you must apply for memory with the VirtualaLalkEx function, then use the WriteProcessMemory write string to the target. In the process, you can save the string address, and then press the method of transmitting the API address to transmit to the thread function. Finally, remember to use the VirtualFreeEx function to release the memory allocated in the target process.
Using the VirtualaLalkEx function, you can also realize HOOK technology that does not require a DLL file. Interested friends can try their own.