一. delphi远程注入Dll文件
- 首先,您必须找到已经在内存中运行的应用程序(EXE)的PID。以下函数将通过名称获得PID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function PIDbyName(ProcessName: PWideChar): DWORD;
var
ProcessSnap: Int64;
ProcessEntry32: TProcessEntry32;
begin
Result := 0;
ProcessSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if ProcessSnap <> INVALID_HANDLE_VALUE then
begin
ProcessEntry32.dwSize := SizeOf(TPROCESSENTRY32);
if Process32First(ProcessSnap, ProcessEntry32) then
repeat
if lstrcmpi(ProcessEntry32.szExeFile, ProcessName) = 0 then
begin
Result := ProcessEntry32.th32ProcessID;
CloseHandle(ProcessSnap);
exit;
end;
until not Process32Next(ProcessSnap, ProcessEntry32);
Result := 0;
CloseHandle(ProcessSnap);
end;
end; - 这是32/64位应用程序的DLL注入函数 Source是DLL,Target是EXE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30function InjectDLL(Source, Target : PWideChar) : boolean;
var
dwThreadID: Cardinal;
hProc, hThread: THandle;
BytesToWrite, BytesWritten: SIZE_T;
pRemoteBuffer, pLoadLibrary: Pointer;
begin
hProc := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, False, PIDbyName(Target));
if hProc = 0 then exit(false);
try
BytesToWrite := SizeOf(WideChar) * (Length(Source) + 1);
pRemoteBuffer := VirtualAllocEx(hProc, nil, BytesToWrite, MEM_COMMIT,PAGE_READWRITE);
if pRemoteBuffer = nil then exit(false);
try
if not WriteProcessMemory(hProc, pRemoteBuffer, Source, BytesToWrite, BytesWritten) then exit(false);
pLoadLibrary := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryW');
hThread := CreateRemoteThread(hProc, nil, 0, pLoadLibrary, pRemoteBuffer, 0, dwThreadID);
try
WaitForSingleObject(hThread, INFINITE);
finally
Result := true;
CloseHandle(hThread);
end;
finally
VirtualFreeEx(hProc, pRemoteBuffer, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProc);
end;
end; - 简单的DLL用法:InjectDLL(‘testDLL.dll’, ‘yourapplication.exe’)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25library testDLL;
uses
System.SysUtils,
System.Classes,
Winapi.Windows;
procedure DLLEntryPoint(dwReason: DWord);
var
DLLHandle : DWORD;
begin
case dwReason of
DLL_PROCESS_ATTACH:
MessageBox(DLLHandle, 'Process Attach', 'Info', mb_Ok);
DLL_PROCESS_DETACH:
MessageBox(DLLHandle, 'Process Detach', 'Info', mb_Ok);
end;
end;
begin
DllProc := @DLLEntryPoint;
DllEntryPoint(DLL_PROCESS_ATTACH);
end.二. delphi远程直接注入代码执行(非DLL插入是代码注入)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94//-------------------------注入代码的函数----------------------------
{参数说明:
InHWND:被注入的窗口句柄
Func:注入的函数的指针
Param:参数的指针
ParamSize:参数的大小
}
procedure InjectFunc(InHWND: HWND; Func: Pointer; Param: Pointer; ParamSize: DWORD);
var
hProcess_N: THandle;
ThreadAdd, ParamAdd: Pointer;
hThread: THandle;
ThreadID: DWORD;
lpNumberOfBytes:DWORD;
begin
GetWindowThreadProcessId(InHWND, @ThreadID); //获得窗口ID
hProcess_N := OpenProcess(PROCESS_ALL_ACCESS, False, ThreadID);//打开被注入的进程
ThreadAdd := VirtualAllocEx(hProcess_N, nil, 4096, MEM_COMMIT, PAGE_READWRITE); //申请写入代码空间
WriteProcessMemory(hProcess_N, ThreadAdd, Func, 4096, lpNumberOfBytes); //写入函数地址
ParamAdd := VirtualAllocEx(hProcess_N, nil, ParamSize, MEM_COMMIT, PAGE_READWRITE); //申请写入代码参数空间
WriteProcessMemory(hProcess_N, ParamAdd, Param, ParamSize, lpNumberOfBytes); //写入参数地址
hThread := CreateRemoteThread(hProcess_N, nil, 0, ThreadAdd, ParamAdd, 0, lpNumberOfBytes); //创建远程线程
ResumeThread(hThread); //直接运行线程
CloseHandle(hThread); //关闭线程
VirtualFreeEx(hProcess_N, ThreadAdd, 4096, MEM_RELEASE);
VirtualFreeEx(hProcess_N, ParamAdd, ParamSize, MEM_RELEASE); //释放申请的地址
CloseHandle(hProcess_N); //关闭打开的句柄
end;
//-----------------------------定义一个参数类型-----------------------
type
TPickCallParam = packed record
ax, ay: single;
end;
PPickCallParam = ^TPickCallParam; //指向结构的指针(C中叫这种方式的数据应该叫结构体吧)
procedure runCall(p:PPickCallParam);stdcall; // 走路call
var
addres,addres1,addres2:pointer;
x,y:single;
begin
addres:=pointer($0045ec00);
addres1:=pointer($00462620);
addres2:=pointer($0045f000);
x:=p^.ax; //目的地X坐标
y:=p^.ay; //目的地Y坐标
asm
pushad
mov eax, dword ptr [$8f207c]
mov eax, dword ptr [eax+$1C]
mov esi, dword ptr [eax+$20]
mov ecx, dword ptr [esi+$ba0]
push 1
call addres
mov edi, eax
lea eax, dword ptr [esp+$18]
push eax
push 0
mov ecx, edi
call addres1
push 0
push 1
push edi
mov ecx, dword ptr [esi+$ba0]
push 1
call addres2
mov eax, dword ptr [$8f207c]
mov eax, dword ptr [eax+$1C]
mov eax, dword ptr [eax+$20]
mov eax, dword ptr [eax+$ba0]
mov eax, dword ptr [eax+$30]
mov ecx, dword ptr [eax+4]
mov eax, x
mov [ecx+$20], eax
mov eax, y
mov [ecx+$28], eax
popad
end;
END;
procedure TForm1.Button1Click(Sender: TObject);//在控件中做个按钮 测试
var
CallParam:TPickCallParam;
begin;
getmem(pname,33);
myhwnd := FindWindow(nil,'Element Client');{查找窗口句柄}
GetWindowThreadProcessId(myhwnd, aproc); {得到窗口ID}
phnd := OpenProcess(PROCESS_VM_READ , False, aproc);{以完全访问权限打开进程句柄}
if (phnd<>0 ) then
begin
CallParam.ax:= 1860.0; //给注入代码函数赋值
CallParam.ay:=120.0; //给注入代码函数赋值
InjectFunc(myhWnd,@runCall,@CallParam,SizeOf(CallParam)); //运行注入代码函数
sleep(100);
CloseHandle(PHND) //关闭进程
end;
end;三. 远程代码或DLL注入x86/x64/Win2k/win7~Win8.1 64位全可用(最重要的隆重登场)
上面的一和二远程注入,在win7 64位系统下,不能成功注入service服务程序,下面代码实现在64位系统,可以注入系统进程,服务进程等!看关键函数NtCreateThreadEx,而在win7 64位下的注入问题http://forum.sources.ru/index.php?showtopic=313636有相应讨论1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116program Inject;
uses
Winapi.Windows;
Type
NtCreateThreadExProc = Function(Var hThread:THandle; Access:DWORD; Attributes:Pointer; hProcess:THandle; pStart:Pointer; pParameter:Pointer; Suspended:BOOL; StackSize, u1, u2:DWORD; Unknown:Pointer):DWORD; stdcall;
Function CheckOs():Boolean;
Var
lpVersionInformation :TOSVersionInfoW;
begin
Result := False;
if GetVersionExW(lpVersionInformation) then
begin
if lpVersionInformation.dwPlatformId = VER_PLATFORM_WIN32_NT Then
begin
if (lpVersionInformation.dwMajorVersion < 6) then
begin
Result := True;
end;
end;
end;
end;
Function EnableDebugPrivilege():Boolean;
Var
hToKen :THandle;
TokenPri :TTokenPrivileges;
begin
Result := False;
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES, hToKen)) Then
begin
TokenPri.PrivilegeCount := 1;
If LookupPrivilegeValueW(Nil, 'SeDebugPrivilege', TokenPri.Privileges[0].Luid) Then
begin
TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(hToken, False, TokenPri, SizeOf(TTokenPrivileges), Nil, PDWORD(Nil)^);
end Else Writeln('LookupPrivilege Error');
CloseHandle(hToKen);
end;
end;
Function RemoteThread(hProcess:THandle; pThreadProc:Pointer; pRemote:Pointer):THandle;
Label NtCreate, Create;
Var
pFunc :Pointer;
hThread :THandle;
begin
hThread := 0;
if Not CheckOs() then //根据系统版本来选择使用的API
begin
NtCreate:
pFunc := GetProcAddress(LoadLibraryW('ntdll.dll'), 'NtCreateThreadEx');
if pFunc = Nil then Goto Create;
NtCreateThreadExProc(pFunc)(hThread, $1FFFFF, Nil, hProcess, pThreadProc, pRemote, False, 0, 0, 0, Nil);
if hThread = 0 then Goto Create;
end Else
begin
Create:
hThread := CreateRemoteThread(hProcess, Nil, 0, pThreadProc, pRemote, 0, PDWORD(Nil)^);
end;
Writeln('RemoteThread Ok!');
Result := hThread;
end;
Function InjectDll2Pid(szPath:PWideChar; uPID:DWORD):Boolean;
Var
hProcess :THandle;
hThread :THandle;
szRemote :PWideChar;
uSize :SIZE_T;
uWrite :SIZE_T;
pStartAddr:Pointer;
begin
Result := False;
if EnableDebugPrivilege then
begin //先提升下进程的权限
hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, uPID);
if hProcess > 0 then
begin
uSize := lstrlenW(szPath) * 2 + 4;
szRemote := VirtualAllocEx(hProcess, Nil, uSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if WriteProcessMemory(hProcess, szRemote, szPath, uSize, uWrite) And (uWrite = uSize) then
begin
pStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'LoadLibraryW');
hThread := RemoteThread(hProcess, pStartAddr, szRemote);
Result := hThread <> 0;
CloseHandle(hThread);
end Else
begin
Writeln('WriteMemory Error');
end;
end;
end;
end;
Function StrToInt(S: String): Integer;
Var
E: Integer;
Begin
Val(S, Result, E);
End;
begin
InjectDll2Pid(PWideChar(ParamStr(2)), StrToInt(ParamStr(1)));
end.NtCreateThreadEx注入注意事项:
64位的进程,只能使用64位的dll注入,注入程序本身也必须编译为64位程序,32位的进程,只能使用32位的dll注入,注入程序本身编译为32位程序,不然会注入不成功!比如你把程序编译为32程序,想在win7 64位下往services.exe注入,是不会成功的,services.exe在win7 64位下是64位程序!