这样的问题讨论很多了,98下很容易实现,2000下要提高本地进程的优先级才可以,看看下面的代码,测试的时候我的DLL可以运行,不过马上就会弹出内存错误,请高手分析一下...
Const
THREADSIZE : DWord=1024*4;//暂定线程体大小为4K,实际上没这么大
type
PmyLoadLibrary=function (lpLibFileName: PChar): HMODULE; stdcall;
type
PmyFreeLibrary=function (hLibModule: HMODULE): BOOL; stdcall;
type
PmyGetProcAddress=function (hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
type
TmShowForm = Procedure (aTopHandle:THandle) ;stdCall;
type
TmyProc = procedure (aData:Pointer);stdcall;
type
PRemoteData=record
pHookDllName:array[0..50] of char;
pProcName : array[0..20] of char;
TopHandle : THandle;
myFreeLibrary: PmyFreeLibrary;
myLoadLibrary: PmyLoadLibrary;
myGetProcAddress : PmyGetProcAddress;
end;//在宿主进程里面执行自己DLL里面的函数
procedure Exe_myDll(pID: DWord; DllFileName,
ProcName: string);
procedure backProc(aData:Pointer);stdcall;
var
myLoadLibrary: PmyLoadLibrary;
myGetProcAddress : PmyGetProcAddress;
aShowForm : TmShowForm;
aHandle : integer; begin
myLoadLibrary := PmyLoadLibrary(PRemoteData(aData^).myLoadLibrary);
myGetProcAddress := PmyGetProcAddress(PRemoteData(aData^).myGetProcAddress);
aHandle := myLoadLibrary(PRemoteData(aData^).pHookDllName);
@aShowForm := myGetProcAddress(aHandle,PRemoteData(aData^).pProcName);
aShowForm(PRemoteData(aData^).TopHandle);
PRemoteData(aData^).myFreeLibrary(aHandle);
end;
var
byte_write : DWord;
pRemoteThread,aRemoteData:Pointer;
hWNd,hThread,hUser32 : THandle;
i :Dword;
aData : PRemoteData;
begin
//首先要提升本地进程的权限
EnableDebugPriv;(具体实现没写,哪都有)
//根据pID获得指定进程的句柄,并设其权限为PROCESS_ALL_ACCESS,
hWnd := OpenProcess(PROCESS_ALL_ACCESS,FALSE,PId);
if(hWnd=0) then
begin
ShowMessage('OpenProcess Error');
Exit;
end;
//为宿主进程主线程分配虚拟内存,并指定权限为可读写,成功后返回读写基地址
pRemoteThread :=VirtualAllocEx(hWnd,nil,THREADSIZE,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);//申请
if(pRemoteThread=nil) then
begin
ShowMessage('VirtualAllocEx Error');
exit;
end;
i := 0;
//写入进程
if not WriteProcessMemory(hWnd,pRemoteThread,@backProc,THREADSIZE,i) then
begin
ShowMessage('WriteProcessMemory Error');
Exit;
end;
//对aData赋值
ZeroMemory(@aData,sizeof(aData));
hUser32 := LoadLibrary(PChar('Kernel32.dll'));
@aData.myFreeLibrary := GetProcAddress(hUser32,PChar('FreeLibrary'));
@aData.myGetProcAddress := GetProcAddress(hUser32,PChar('GetProcAddress'));
@aData.myLoadLibrary := GetProcAddress(hUser32,PChar('LoadLibraryA'));
FreeLibrary(hUser32);
//得到要加载的DLL的文件名和要执行的DLL里的函数
StrCopy(@aData.pHookDllName,PChar(DllFileName));
StrCopy(@aData.pProcName,PChar(ProcName));
aData.TopHandle := GetTopWindow(0);
//在远程进程的内存地址空间分配PRemoteData大小的缓冲区用来加载我们的信息
aRemoteData := VirtualAllocEx(hWnd,nil,sizeof(aData),MEM_COMMIT,PAGE_READWRITE);//注意申请空间时的页面属性
if(aRemoteData=nil) then
begin
ShowMessage('aRemoteData is Nil');
Exit;
end;
//写入我们的数据
if not WriteProcessMemory(hWnd ,aRemoteData,@aData,sizeof(aData),i) then
begin
ShowMessage('WriteProcessMemory aData Error');
Exit;
end;
//启动远程线程,通过远程线程调用我们的DLL,@TmyProc是LoadLibary的入口地址
hThread := CreateRemoteThread(hWnd ,nil,0,@TmyProc(pRemoteThread),aRemoteData,0,byte_write);
if hThread <> 0 then
begin
showmessage('启动!');
end
else
ShowMessage('FM_Monitor加载失败!');
end;
Const
THREADSIZE : DWord=1024*4;//暂定线程体大小为4K,实际上没这么大
type
PmyLoadLibrary=function (lpLibFileName: PChar): HMODULE; stdcall;
type
PmyFreeLibrary=function (hLibModule: HMODULE): BOOL; stdcall;
type
PmyGetProcAddress=function (hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
type
TmShowForm = Procedure (aTopHandle:THandle) ;stdCall;
type
TmyProc = procedure (aData:Pointer);stdcall;
type
PRemoteData=record
pHookDllName:array[0..50] of char;
pProcName : array[0..20] of char;
TopHandle : THandle;
myFreeLibrary: PmyFreeLibrary;
myLoadLibrary: PmyLoadLibrary;
myGetProcAddress : PmyGetProcAddress;
end;//在宿主进程里面执行自己DLL里面的函数
procedure Exe_myDll(pID: DWord; DllFileName,
ProcName: string);
procedure backProc(aData:Pointer);stdcall;
var
myLoadLibrary: PmyLoadLibrary;
myGetProcAddress : PmyGetProcAddress;
aShowForm : TmShowForm;
aHandle : integer; begin
myLoadLibrary := PmyLoadLibrary(PRemoteData(aData^).myLoadLibrary);
myGetProcAddress := PmyGetProcAddress(PRemoteData(aData^).myGetProcAddress);
aHandle := myLoadLibrary(PRemoteData(aData^).pHookDllName);
@aShowForm := myGetProcAddress(aHandle,PRemoteData(aData^).pProcName);
aShowForm(PRemoteData(aData^).TopHandle);
PRemoteData(aData^).myFreeLibrary(aHandle);
end;
var
byte_write : DWord;
pRemoteThread,aRemoteData:Pointer;
hWNd,hThread,hUser32 : THandle;
i :Dword;
aData : PRemoteData;
begin
//首先要提升本地进程的权限
EnableDebugPriv;(具体实现没写,哪都有)
//根据pID获得指定进程的句柄,并设其权限为PROCESS_ALL_ACCESS,
hWnd := OpenProcess(PROCESS_ALL_ACCESS,FALSE,PId);
if(hWnd=0) then
begin
ShowMessage('OpenProcess Error');
Exit;
end;
//为宿主进程主线程分配虚拟内存,并指定权限为可读写,成功后返回读写基地址
pRemoteThread :=VirtualAllocEx(hWnd,nil,THREADSIZE,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);//申请
if(pRemoteThread=nil) then
begin
ShowMessage('VirtualAllocEx Error');
exit;
end;
i := 0;
//写入进程
if not WriteProcessMemory(hWnd,pRemoteThread,@backProc,THREADSIZE,i) then
begin
ShowMessage('WriteProcessMemory Error');
Exit;
end;
//对aData赋值
ZeroMemory(@aData,sizeof(aData));
hUser32 := LoadLibrary(PChar('Kernel32.dll'));
@aData.myFreeLibrary := GetProcAddress(hUser32,PChar('FreeLibrary'));
@aData.myGetProcAddress := GetProcAddress(hUser32,PChar('GetProcAddress'));
@aData.myLoadLibrary := GetProcAddress(hUser32,PChar('LoadLibraryA'));
FreeLibrary(hUser32);
//得到要加载的DLL的文件名和要执行的DLL里的函数
StrCopy(@aData.pHookDllName,PChar(DllFileName));
StrCopy(@aData.pProcName,PChar(ProcName));
aData.TopHandle := GetTopWindow(0);
//在远程进程的内存地址空间分配PRemoteData大小的缓冲区用来加载我们的信息
aRemoteData := VirtualAllocEx(hWnd,nil,sizeof(aData),MEM_COMMIT,PAGE_READWRITE);//注意申请空间时的页面属性
if(aRemoteData=nil) then
begin
ShowMessage('aRemoteData is Nil');
Exit;
end;
//写入我们的数据
if not WriteProcessMemory(hWnd ,aRemoteData,@aData,sizeof(aData),i) then
begin
ShowMessage('WriteProcessMemory aData Error');
Exit;
end;
//启动远程线程,通过远程线程调用我们的DLL,@TmyProc是LoadLibary的入口地址
hThread := CreateRemoteThread(hWnd ,nil,0,@TmyProc(pRemoteThread),aRemoteData,0,byte_write);
if hThread <> 0 then
begin
showmessage('启动!');
end
else
ShowMessage('FM_Monitor加载失败!');
end;
比如procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
ShowMessage('DLL_PROCESS_ATTACH');
HookCreateProcess;//执行你的函数;
end;
DLL_PROCESS_DETACH: ShowMessage('DLL_PROCESS_DETACH');
DLL_THREAD_ATTACH: ShowMessage('DLL_THREAD_ATTACH');
DLL_THREAD_DETACH: ShowMessage('DLL_THREAD_DETACH');
end;
end;
begin
DllProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.