这样的问题讨论很多了,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;

解决方案 »

  1.   

    这堆代码看的我眼花......不过为什么不把“要执行的代码”写在dll的入口函数中呢?
    比如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.
      

  2.   

    注意啊,我那段代码可以在任意系统进程里面执行自己的DLL,只要知道进程映像名称或者PID就可以,而不是要在哪一个DLL里面执行我的函数...