源:从内存中加载DLL DELPHI版
原文 : http://www.2ccc.com/article.asp?articleid=5784
MemLibrary.pas
//从内存中加载DLL DELPHI版 unit MemLibrary;interfaceuses Windows;function memLoadLibrary(pLib: Pointer): DWord; function memGetProcAddress(dwLibHandle: DWord; pFunctionName: PChar): Pointer; stdcall; function memFreeLibrary(dwHandle: DWord): Boolean;implementationprocedure ChangeReloc(baseorgp, basedllp, relocp: pointer; size: cardinal); typeTRelocblock = recordvaddress: integer;size: integer;end;PRelocblock = ^TRelocblock; varmyreloc: PRelocblock;reloccount: integer;startp: ^word;i: cardinal;p: ^cardinal;dif: cardinal; beginmyreloc := relocp;dif := cardinal(basedllp)-cardinal(baseorgp);startp := pointer(cardinal(relocp)+8);while myreloc^.vaddress <> 0 dobeginreloccount := (myreloc^.size-8) div sizeof(word);for i := 0 to reloccount-1 dobeginif (startp^ xor $3000 < $1000) thenbeginp := pointer(myreloc^.vaddress+startp^ mod $3000+integer(basedllp));p^ := p^+dif;end;startp := pointer(cardinal(startp)+sizeof(word));end;myreloc := pointer(startp);startp := pointer(cardinal(startp)+8);end; end; procedure CreateImportTable(dllbasep, importp: pointer); stdcall; typetimportblock = recordCharacteristics: cardinal;TimeDateStamp: cardinal;ForwarderChain: cardinal;Name: pchar;FirstThunk: pointer;end;pimportblock = ^timportblock; varmyimport: pimportblock;thunksread, thunkswrite: ^pointer;dllname: pchar;dllh: thandle;old: cardinal; beginmyimport := importp;while (myimport^.FirstThunk <> nil) and (myimport^.Name <> nil) dobegindllname := pointer(integer(dllbasep)+integer(myimport^.name));dllh := LoadLibrary(dllname);thunksread := pointer(integer(myimport^.FirstThunk)+integer(dllbasep));thunkswrite := thunksread;if integer(myimport^.TimeDateStamp) = -1 thenthunksread := pointer(integer(myimport^.Characteristics)+integer(dllbasep));while (thunksread^ <> nil) dobeginif VirtualProtect(thunkswrite,4,PAGE_EXECUTE_READWRITE,old) thenbeginif (cardinal(thunksread^) and $80000000 <> 0) thenthunkswrite^ := GetProcAddress(dllh,pchar(cardinal(thunksread^) and $FFFF)) elsethunkswrite^ := GetProcAddress(dllh,pchar(integer(dllbasep)+integer(thunksread^)+2));VirtualProtect(thunkswrite,4,old,old);end;inc(thunksread,1);inc(thunkswrite,1);end;myimport := pointer(integer(myimport)+sizeof(timportblock));end; end;function memLoadLibrary(pLib: Pointer): DWord; var DllMain : function (dwHandle, dwReason, dwReserved: DWord): DWord; stdcall; IDH : PImageDosHeader; INH : PImageNtHeaders; SEC : PImageSectionHeader; dwSecCount : DWord; dwLen : DWord; dwmemsize : DWord; i : Integer; pAll : Pointer; begin Result := 0;IDH := pLib; if isBadReadPtr(IDH, SizeOf(TImageDosHeader)) or (IDH^.e_magic <> IMAGE_DOS_SIGNATURE) thenExit;INH := pointer(cardinal(pLib)+cardinal(IDH^._lfanew)); if isBadReadPtr(INH, SizeOf(TImageNtHeaders)) or (INH^.Signature <> IMAGE_NT_SIGNATURE) thenExit;// if (pReserved <> nil) then // dwLen := Length(pReserved)+1 // elsedwLen := 0;SEC := Pointer(Integer(INH)+SizeOf(TImageNtHeaders)); dwMemSize := INH^.OptionalHeader.SizeOfImage; if (dwMemSize = 0) then Exit;pAll := VirtualAlloc(nil,dwMemSize+dwLen,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (pAll = nil) then Exit;dwSecCount := INH^.FileHeader.NumberOfSections; CopyMemory(pAll,IDH,DWord(SEC)-DWord(IDH)+dwSecCount*SizeOf(TImageSectionHeader)); // CopyMemory(Pointer(DWord(pAll) + dwMemSize),pReserved,dwLen-1); CopyMemory(Pointer(DWord(pAll) + dwMemSize),nil,dwLen-1); for i := 0 to dwSecCount-1 do beginCopyMemory(Pointer(DWord(pAll)+SEC^.VirtualAddress),Pointer(DWord(pLib)+DWord(SEC^.PointerToRawData)),SEC^.SizeOfRawData);SEC := Pointer(Integer(SEC)+SizeOf(TImageSectionHeader)); end;if (INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0) thenChangeReloc(Pointer(INH^.OptionalHeader.ImageBase),pAll,Pointer(DWord(pAll)+INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); CreateImportTable(pAll, Pointer(DWord(pAll)+INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));@DllMain := Pointer(INH^.OptionalHeader.AddressOfEntryPoint+DWord(pAll)); // if (INH^.OptionalHeader.AddressOfEntryPoint <> 0) and (bDllMain) then if INH^.OptionalHeader.AddressOfEntryPoint <> 0 then begintry // if (pReserved <> nil) then // DllMain(DWord(pAll),DLL_PROCESS_ATTACH,DWord(pAll)+dwMemSize) // elseDllMain(DWord(pAll),DLL_PROCESS_ATTACH,0);exceptend; end; Result := DWord(pAll); end;function memFreeLibrary(dwHandle: DWord): Boolean; var IDH: PImageDosHeader; INH: PImageNTHeaders; begin Result := false; if (dwHandle = 0) thenExit;IDH := Pointer(dwHandle); if (IDH^.e_magic <> IMAGE_DOS_SIGNATURE) thenExit;INH := Pointer(DWord(IDH^._lfanew)+DWord(IDH)); if (INH^.Signature <> IMAGE_NT_SIGNATURE) thenExit;if VirtualFree(Pointer(dwHandle),INH^.OptionalHeader.SizeOfImage,MEM_DECOMMIT) thenResult := True; end;function memGetProcAddress(dwLibHandle: DWord; pFunctionName: PChar): Pointer; stdcall; var NtHeader : PImageNtHeaders; DosHeader : PImageDosHeader; DataDirectory : PImageDataDirectory; ExportDirectory : PImageExportDirectory; i : Integer; iExportOrdinal : Integer; ExportName : String; dwPosDot : DWord; dwNewmodule : DWord; pFirstExportName : Pointer; pFirstExportAddress: Pointer; pFirstExportOrdinal: Pointer; pExportAddr : PDWord; pExportNameNow : PDWord; pExportOrdinalNow : PWord; begin Result := nil; if pFunctionName = nil then Exit;DosHeader := Pointer(dwLibHandle); if isBadReadPtr(DosHeader,sizeof(TImageDosHeader)) or (DosHeader^.e_magic <> IMAGE_DOS_SIGNATURE) thenExit; {Wrong PE (DOS) Header}NtHeader := Pointer(DWord(DosHeader^._lfanew)+DWord(DosHeader)); if isBadReadPtr(NtHeader, sizeof(TImageNTHeaders)) or (NtHeader^.Signature <> IMAGE_NT_SIGNATURE) thenExit; {Wrong PW (NT) Header}DataDirectory := @NtHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (DataDirectory = nil) or (DataDirectory^.VirtualAddress = 0) thenExit; {Library has no exporttable}ExportDirectory := Pointer(DWord(DosHeader) + DWord(DataDirectory^.VirtualAddress)); if isBadReadPtr(ExportDirectory,SizeOf(TImageExportDirectory)) thenExit;pFirstExportName := Pointer(DWord(ExportDirectory^.AddressOfNames)+DWord(DosHeader)); pFirstExportOrdinal := Pointer(DWord(ExportDirectory^.AddressOfNameOrdinals)+DWord(DosHeader)); pFirstExportAddress := Pointer(DWord(ExportDirectory^.AddressOfFunctions)+DWord(DosHeader));if (integer(pFunctionName) > $FFFF) then {is FunctionName a PChar?} beginiExportOrdinal := -1; {if we dont find the correct ExportOrdinal}for i := 0 to ExportDirectory^.NumberOfNames-1 do {for each export do}beginpExportNameNow := Pointer(Integer(pFirstExportName)+SizeOf(Pointer)*i);if (not isBadReadPtr(pExportNameNow,SizeOf(DWord))) thenbeginExportName := PChar(pExportNameNow^+ DWord(DosHeader));if (ExportName = pFunctionName) then {is it the export we search? Calculate the ordinal.}beginpExportOrdinalNow := Pointer(Integer(pFirstExportOrdinal)+SizeOf(Word)*i);if (not isBadReadPtr(pExportOrdinalNow,SizeOf(Word))) theniExportOrdinal := pExportOrdinalNow^;end;end;end; end else{no PChar, calculate the ordinal directly}iExportOrdinal := DWord(pFunctionName)-DWord(ExportDirectory^.Base);if (iExportOrdinal < 0) or (iExportOrdinal > Integer(ExportDirectory^.NumberOfFunctions)) thenExit; {havent found the ordinal}pExportAddr := Pointer(iExportOrdinal*4+Integer(pFirstExportAddress)); if (isBadReadPtr(pExportAddr,SizeOf(DWord))) thenExit;{Is the Export outside the ExportSection? If not its NT spezific forwared function} if (pExportAddr^ < DWord(DataDirectory^.VirtualAddress)) or(pExportAddr^ > DWord(DataDirectory^.VirtualAddress+DataDirectory^.Size)) then beginif (pExportAddr^ <> 0) then {calculate export address}Result := Pointer(pExportAddr^+DWord(DosHeader)); end else begin {forwarded function (like kernel32.EnterCriticalSection -> NTDLL.RtlEnterCriticalSection)}ExportName := PChar(dwLibHandle+pExportAddr^);dwPosDot := Pos('.',ExportName);if (dwPosDot > 0) thenbegindwNewModule := GetModuleHandle(PChar(Copy(ExportName,1,dwPosDot-1)));if (dwNewModule = 0) thendwNewModule := LoadLibrary(PChar(Copy(ExportName,1,dwPosDot-1)));if (dwNewModule <> 0) thenresult := GetProcAddressX(dwNewModule,PChar(Copy(ExportName,dwPosDot+1,Length(ExportName))));end; end; end;end.