首页  编辑  

进程注入:在其他进程空间加载DLL

Tags: /超级猛料/DLL.动态链接库/   Date Created:
进程注入:在其他进程空间加载DLL
{-----------------------------------------------------------------------------
Unit Name:  RemoteInjection
Author:     Jason Eric Pierce
Purpose:    To cause another application to load a DLL on demand
Date:       7/24/2004
License:    The code in this library is public domain.  It may be included
            in any program, commercial or otherwise, free of charge.
References: "Three Ways to Inject Your Code into Another Process" by Robert Kuster
            "API hooking revealed" by Ivo Ivanov
Requires:   This library uses CreateRemoteThread, which only exists on NT or
            greater.  For Windows 9x, you would need to use a system-wide
            hook.  The benefit to CreateRemoteThread is that it can be used
            to target loading into a specific process only, rather than having
            your DLL loading into the memory of every application.
            Only applications that link to kernel32.dll can use this method.
            However, only really hairy system-level applications don't link
            to it.
Notes:      Much of the code in this unit was translated into Delphi from the
            excellent article by Robert Kuster.  This was found at:
            http://www.codeproject.com/threads/winspy.asp?df=100&forumid=16291&exp=0&select=858734
Usage:      Call LoadLibraryIntoProcess with the full path to the DLL you
            want to load and any window handle from the process you want to
            hook into.  It will return a handle to the loaded module which
            you should save if you want to be able to unload the DLL
            later.  You do not need to close this handle manually.
            When you are ready to unload the library, pass the handle to
            UnloadLibraryFromProcess.
Uses:       Forcing an application to load your DLL can be very useful if you
            want to subclass a window in that application.  This allows you
            to monitor the Windows messages being processed by that window and
            use them to alter its look or behavior.  For example, you could
            watch for any WM_PAINT messages to a certain window and follow it
            with your own painting.  For more information, read the articles
            provided in the References section.
-----------------------------------------------------------------------------}
unit RemoteInjection;

interface

uses
 Windows;

function LoadLibraryIntoProcess(LibPathAndName: string; TargetWnd: HWND): THandle;
function UnloadLibraryFromProcess(LibraryHandle: THandle; TargetWnd: HWND): Boolean;

implementation

function GetProcessHandle(Wnd: THandle): THandle;
var
 processId: THandle;
begin
 Result := 0;
 if Wnd <> 0 then
 begin
   GetWindowThreadProcessID(Wnd, @processId);
   if processId <> 0 then
     Result := OpenProcess(PROCESS_ALL_ACCESS, False, processId);
 end;
end;

function LoadLibraryIntoProcess(LibPathAndName: string; TargetWnd: HWND): THandle;
var
 hThread: THandle;
 dummy: THandle;
 pLibRemote: Pointer;   // The address (in the remote process) where
                        // LibPathAndName will be copied to
 lpNumberOfBytesWritten: DWORD;
 hProcess: THandle;
begin
 Result := 0;
 
 hProcess := GetProcessHandle(TargetWnd);
 if hProcess <> 0 then
   try
     lpNumberOfBytesWritten := 0;
     // 1. Allocate memory in the remote process for LibPathAndName
     // 2. Write LibPathAndName to the allocated memory
     pLibRemote := VirtualAllocEx(hProcess, nil, Length(LibPathAndName) + 1,
                                    MEM_COMMIT, PAGE_READWRITE);
     try
       if pLibRemote = nil then
         Exit;
       WriteProcessMemory(hProcess, pLibRemote, PChar(LibPathAndName),
                             Length(LibPathAndName) + 1, // get the null too
                             lpNumberOfBytesWritten);
       // Load the dll into the remote process
       // (via CreateRemoteThread & LoadLibrary)
       hThread := CreateRemoteThread(hProcess, nil, 0,
           GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryA'),
           pLibRemote, 0, dummy);
       if hThread <> 0 then
         try
           WaitForSingleObject(hThread, INFINITE);
           // Get handle of the loaded module
           if not GetExitCodeThread(hThread, Result) then
             Result := 0;
         finally
           // Clean up
           CloseHandle(hThread);
         end;
     finally
       VirtualFreeEx(hProcess, pLibRemote, Length(LibPathAndName) + 1,
           MEM_RELEASE);
     end;
   finally
     CloseHandle(hProcess);
   end;
end;

function UnloadLibraryFromProcess(LibraryHandle: THandle; TargetWnd: HWND): Boolean;
var
 hThread: THandle;
 hProcess: THandle;
begin
 Result := False;
 hProcess := GetProcessHandle(TargetWnd);
 if hProcess <> 0 then
 try
   if LibraryHandle <> 0 then
     if CreateRemoteThread(hProcess, nil, 0,
         GetProcAddress(GetModuleHandle('Kernel32'), 'FreeLibrary'),
         Pointer(LibraryHandle), 0, hThread) <> 0 then
     begin
       WaitForSingleObject(hThread, INFINITE);
       Result := True;
     end;
 finally
   CloseHandle(hThread);
 end;
end;

end.