W
wyd19790823
Unregistered / Unconfirmed
GUEST, unregistred user!
该程序的下载地址为;http://www.namipan.com/downfile/Test.rar/6ccec1b7a9dd8c2e73c3475cf6339ec55cb38580719a0000主程序代码如下:unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, EnumStuff;const MFileName: Pchar = 'MyShareData';type PShareData = ^TShareData; TShareData = record IsStartThread : Boolean; isBreak : Boolean; FileName : String[255]; Index : integer; CurrentItem : Integer; Total : Integer; MS : TMemoryStream; end; TForm1 = class(TForm) BitBtn1: TBitBtn; Label1: TLabel; edtExeFile: TEdit; procedure BitBtn2Click(Sender: TObject); procedure BitBtn1Click(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } function ReadFile(sFileName :String;Index,Total :Integer;Var MS :TMemoryStream):Boolean; function EnableDebugPriv : Boolean; function InjectDll(const DllFullPath : string;const dwRemoteProcessId : Cardinal): boolean; function UnInjectDll(const DllFullPath : string;const dwRemoteProcessId : Cardinal) : Boolean; public { Public declarations } end;var Form1: TForm1; GlobalData : PShareData; MapHandle: THandle;implementation{$R *.dfm}function TForm1.ReadFile(sFileName :String;Index,Total :Integer;Var MS :TMemoryStream):Boolean;var size: integer;begin size := sizeof(TShareData)+10240; //创建一个内存文档映射对象,MfileName保存的值就是该对象的名字。 mapHandle := CreateFileMapping(Dword(-1), nil, page_readWrite, 0, size, MFileName); if mapHandle = 0 then RaiseLastWin32Error; //把文档的视图映射到调用进程的地址空间,该函数的返回值就是该对象的首地址。注//意,这是调用进程的地址,两个应用程式调用该DLL,返回值是不相同的。 GlobalData := MapViewOfFile(mapHandle, File_map_all_Access, 0, 0, size); GlobalData^.FileName :=sFileName; GlobalData^.Index := 1; GlobalData^.Total := 1; While GlobalData^.Index>GlobalData^.CurrentItem do begin Application.ProcessMessages; GlobalData := MapViewOfFile(mapHandle, File_map_all_Access, 0, 0, size); end; GlobalData^.MS.Seek(0,soFromBeginning); MS.Clear; MS.CopyFrom(GlobalData^.MS,GlobalData^.MS.Size); Result :=True; if GlobalData = nil then begin CloseHandle(MapHandle); RaiseLastWin32Error; end;end;procedure TForm1.BitBtn2Click(Sender: TObject);Var MS :TMemoryStream;beginend;function TForm1.EnableDebugPriv : Boolean;var hToken : THANDLE; tp : TTokenPrivileges; rl : Cardinal;begin result := false; //打开进程令牌环 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken); //获得进程本地唯一ID if LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then begin tp.PrivilegeCount := 1; tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; //调整权限 result := AdjustTokenPrivileges(hToken, False, tp, sizeof(tp), nil, rl); end;end;function TForm1.InjectDll(const DllFullPath: string; const dwRemoteProcessId: Cardinal): boolean;var hRemoteProcess, hRemoteThread: THANDLE; pszLibFileRemote : Pointer; pszLibAFilename: PwideChar; pfnStartAddr : TFNThreadStartRoutine; memSize, WriteSize, lpThreadId : Cardinal;begin result := FALSE; // 调整权限,使程序可以访问其他进程的内存空间 if EnableDebugPriv then begin //打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限 hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId ); try // 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1); // 之所以要转换成 WideChar, 是因为当DLL位于有中文字符的路径下时不会出错 StringToWideChar(DllFullPath, pszLibAFilename, Length(DllFullPath) * 2 + 1); // 计算 pszLibAFilename 的长度,注意,是以字节为单元的长度 memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR); //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名空间 pszLibFileRemote := VirtualAllocEx( hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE); if Assigned(pszLibFileRemote) then begin //使用WriteProcessMemory函数将DLL的路径名写入到远程进程的内存空间 if WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, WriteSize) and (WriteSize = memSize) then begin lpThreadId := 0; // 计算LoadLibraryW的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'LoadLibraryW'); // 启动远程线程LoadLbraryW,通过远程线程调用创建新的线程 hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, lpThreadId); // 如果执行成功返回 True; if (hRemoteThread <> 0) then result := TRUE; // 释放句柄 CloseHandle(hRemoteThread); end; end; finally // 释放句柄 CloseHandle(hRemoteProcess); end; end; end;function TForm1.UnInjectDll(const DllFullPath: string; const dwRemoteProcessId: Cardinal): Boolean;var hRemoteProcess, hRemoteThread : THANDLE; pszLibFileRemote : pchar; pszLibAFilename: PwideChar; pfnStartAddr : TFNThreadStartRoutine; memSize, WriteSize, lpThreadId, dwHandle : Cardinal;begin result := FALSE; // 调整权限,使程序可以访问其他进程的内存空间 if EnableDebugPriv then begin //打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限 hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId ); try // 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1); // 之所以要转换成 WideChar, 是因为当DLL位于有中文字符的路径下时不会出错 StringToWideChar(DllFullPath, pszLibAFilename, Length(DllFullPath) * 2 + 1); // 计算 pszLibAFilename 的长度,注意,是以字节为单元的长度 memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR); //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名空间 pszLibFileRemote := VirtualAllocEx( hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE); if Assigned(pszLibFileRemote) then begin //使用WriteProcessMemory函数将DLL的路径名写入到远程进程的内存空间 if WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, WriteSize) and (WriteSize = memSize) then begin // 计算GetModuleHandleW的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'GetModuleHandleW'); //使目标进程调用GetModuleHandleW,获得DLL在目标进程中的句柄 hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, lpThreadId); // 等待GetModuleHandle运行完毕 WaitForSingleObject(hRemoteThread,INFINITE); // 获得GetModuleHandle的返回值,存在dwHandle变量中 GetExitCodeThread(hRemoteThread, dwHandle); // 计算FreeLibrary的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'FreeLibrary'); // 使目标进程调用FreeLibrary,卸载DLL hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, Pointer(dwHandle), 0, lpThreadId); // 等待FreeLibrary卸载完毕 WaitForSingleObject( hRemoteThread, INFINITE ); // 如果执行成功返回 True; if hRemoteProcess<>0 then result := TRUE; // 释放目标进程中申请的空间 VirtualFreeEx(hRemoteProcess, pszLibFileRemote, Length(DllFullPath)+1, MEM_DECOMMIT); // 释放句柄 CloseHandle(hRemoteThread); end; end; finally // 释放句柄 CloseHandle(hRemoteProcess); end; end;end;procedure TForm1.BitBtn1Click(Sender: TObject);Var Process : TProcessList; InjectOk :Boolean; i, InjectId:Integer; MS :TMemoryStream; MaunalStart,ProcessExist :Boolean; Label StartProgram;begin try ProcessExist :=False; MaunalStart :=False; InjectOk :=False; //首先枚举所有进程,看要注入的目标进程是否存在,如果不存在,则手动启动。 StartProgram: Process := GetProcessList; for I := Low(Process) to High(Process) do if LowerCase(Process.name) = LowerCase(ExtractFileName(edtExeFile.Text)) then begin InjectOk :=InjectDll(ExtractFilePath(ParamStr(0))+'MyDLL.dll', Process.pid); InjectID := Process.pid; ProcessExist :=True; end; if ProcessExist=False then begin if MaunalStart=False then begin WinExec(Pchar(edtExeFile.Text),SW_HIDE); //启动进程代码 MaunalStart :=True; Goto StartProgram; end else begin Application.MessageBox('目标进程不能启动!',Pchar(Caption),MB_IconError+MB_Ok); Exit; end; end; Sleep(500); if InjectOk then begin try MS :=TMemoryStream.Create; if ReadFile(ExtractFilePath(ParamStr(0))+'abc.txt',1,1,MS) then begin MS.SaveToFile('E:/MyFile.Dat'); showmessage('Success'); end; finally MS.Free; end; end; finally if InjectOk then UnInjectDll(ExtractFilePath(ParamStr(0))+'MyDLL.dll',InjectID); end;end;procedure TForm1.FormShow(Sender: TObject);begin //edtExeFile.Text :=Application.ExeName;end;end.MyDll.dll文件代码如下:library Project1;uses shareMem, dialogs, windows, SysUtils, Classes, RWShareData in 'RWShareData.pas', MyType in 'MyType.pas';Var MyThread: TRWDataThread;procedure GetShareData(var AShareData: PShareData);stdcall;begin AShareData := GlobalData;end;procedure OpenThisData; begin Size := Sizeof(TShareData)+10240; //创建一个内存文档映射对象,MfileName保存的值就是该对象的名字。 mapHandle := CreateFileMapping(Dword(-1), nil, Page_ReadWrite, 0, Size, MFileName); if mapHandle = 0 then RaiseLastWin32Error; //把文档的视图映射到调用进程的地址空间,该函数的返回值就是该对象的首地址。 //注意,这是调用进程的地址,两个应用程式调用该DLL,返回值是不相同的。 GlobalData := MapViewOfFile(mapHandle, File_Map_All_Access, 0, 0, Size); if GlobalData = nil then begin CloseHandle(MapHandle); RaiseLastWin32Error; end else begin if GlobalData^.IsStartThread=False then begin MyThread := TRWDataThread.Create(True); GlobalData^.IsStartThread :=True; MyThread.Resume; end; end;end;//DLL从进程中分离出来时,应该释放相应的空间procedure CloseThisData;begin unmapViewOfFile(GlobalData); closeHandle(MapHandle);end;procedure DllEntryPoint(dwReason: DWord);begin case dwReason of Dll_Process_Attach: begin OpenThisData; //调用DLL时传入的参数,由系统自动传入 end; Dll_Process_Detach: CloseThisData; //释放DLL时传入的参数,系统自动传入。 end;end;{$R *.res}exports GetShareData; //外部应用程式调用的就是这个过程。 begin DllProc := @DllEntryPoint; //该变量是个全局变量,由他来指定DLL的入口及出 //口函数。 DllEntryPoint(Dll_Process_Attach);end.我的目的是,主程序(Project2.exe)把MyDll.dll注入程序,再传递文件名进去,MyDll.dll读取文件,读取成功后,以TMemoryStream的形式返回给主程序.