小雨哥,内存中调用DLL,等你有时间的时候用D7试下,这个贴等你答(100)

  • 主题发起人 主题发起人 hying95
  • 开始时间 开始时间
H

hying95

Unregistered / Unconfirmed
GUEST, unregistred user!
用D7编译的DLL作成RES文件只有83KB,用D2010编译的DLL,做成RES文件有292KB,用2010作的DLL才能在D7中用,用D7编译的DLL做成的RES编译会错 g_dll_module:Cardinal;implementation{$R *.dfm}{$R CSdll.res}//用D7和D2010这个文件相差很大。var ShowDemo : function (Number: integer): integer; stdcall = nil;/// 1)这个函数把res资源里的dll加载到程序里function LoadDLLFromResource(const ResourceName: String): Cardinal;var ms: TMemoryStream; rs: TResourceStream;begin ms := TMemoryStream.Create; try rs := TResourceStream.Create(HInstance, ResourceName, 'CDATA'); try ms.CopyFrom(rs, 0); ms.Position := 0; finally rs.Free; end; Result := LoadPE(ms.Memory, ms.Size); finally ms.Free; end;end;/// 2)这个函数把这个dll里的函数取出来function GetAddrFromMemoryDll(dll_module:Cardinal; const Name: string):Pointer;begin try Result := GetProcAddressPE(dll_module, PAnsiChar(Name)); /// 这个函数最好改个名,容易与 Windows 的同名函数混淆,所以我特地前面加了三个XXX_ except Result := nil; end;end;procedure TForm1.btn1Click(Sender: TObject);var Number: integer;begin Number := 0; g_dll_module := LoadDLLFromResource('CSDLL'); if g_dll_module <> 0 then begin @ShowDemo := GetAddrFromMemoryDll(g_dll_module, 'Addtwo'); if @ShowDemo <> nil then Number := ShowDemo(100); FreePE(g_dll_module); end; Caption := IntToStr(Number);end;
 
我有个问题,为什么非要研究内存调用DLL呢?我这有一个源码好像可以用。从网上找的。我的Sqlite.dll就是用它封装的。并且支持Asp的压缩过的。
 
to dorry 因为没有搞定,心中总放不下.你要不要看下,原贴在下面。还有一点问题,不知你能否解决,我不会http://www.delphibbs.com/delphibbs/dispq.asp?lid=3986748能否把你的代码贴上看下
 
代码如下:dll内存调用全部源码。unit uDzMemDLL;{此单元来自网上,忘记了作者,感谢原作者。由Dorry整理}interfaceuses Windows,SysUtils,Classes,SyncObjs,StrUtils;function LoadDllFromResource(ResName:string;ResType:String): DWORD;function _FreeLibrary(dwHandle: DWord): Boolean;function _GetProcAddress(dwLibHandle: DWord; pFunctionName: PChar): Pointer; stdcall;implementation{ memory Load dll }procedure ChangeReloc(baseorgp, basedllp, relocp: pointer; size: cardinal);type TRelocblock = record vaddress: integer; size: integer; end; PRelocblock = ^TRelocblock;var myreloc: PRelocblock; reloccount: integer; startp: ^word; i: cardinal; p: ^cardinal; dif: cardinal;begin myreloc := relocp; dif := cardinal(basedllp)-cardinal(baseorgp); startp := pointer(cardinal(relocp)+8); while myreloc^.vaddress <> 0 do begin reloccount := (myreloc^.size-8) div sizeof(word); for i := 0 to reloccount-1 do begin if (startp^ xor $3000 < $1000) then begin p := 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;type timportblock = record Characteristics: cardinal; TimeDateStamp: cardinal; ForwarderChain: cardinal; Name: pchar; FirstThunk: pointer; end; pimportblock = ^timportblock;var myimport: pimportblock; thunksread, thunkswrite: ^pointer; dllname: pchar; dllh: thandle; old: cardinal;begin myimport := importp; while (myimport^.FirstThunk <> nil) and (myimport^.Name <> nil) do begin dllname := pointer(integer(dllbasep)+integer(myimport^.name)); dllh := LoadLibrary(dllname); thunksread := pointer(integer(myimport^.FirstThunk)+integer(dllbasep)); thunkswrite := thunksread; if integer(myimport^.TimeDateStamp) = -1 then thunksread := pointer(integer(myimport^.Characteristics)+integer(dllbasep)); while (thunksread^ <> nil) do begin if VirtualProtect(thunkswrite,4,PAGE_EXECUTE_READWRITE,old) then begin if (cardinal(thunksread^) and $80000000 <> 0) then thunkswrite^ := GetProcAddress(dllh,pchar(cardinal(thunksread^) and $FFFF)) else thunkswrite^ := 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) then Exit; INH := pointer(cardinal(pLib)+cardinal(IDH^._lfanew)); if isBadReadPtr(INH, SizeOf(TImageNtHeaders)) or (INH^.Signature <> IMAGE_NT_SIGNATURE) then Exit;// if (pReserved <> nil) then// dwLen := Length(pReserved)+1// else dwLen := 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 begin CopyMemory(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) then ChangeReloc(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 begin try// if (pReserved <> nil) then// DllMain(DWord(pAll),DLL_PROCESS_ATTACH,DWord(pAll)+dwMemSize)// else DllMain(DWord(pAll),DLL_PROCESS_ATTACH,0); except end; end; Result := DWord(pAll);end;function _FreeLibrary(dwHandle: DWord): Boolean;var IDH: PImageDosHeader; INH: PImageNTHeaders;begin Result := false; if (dwHandle = 0) then Exit; IDH := Pointer(dwHandle); if (IDH^.e_magic <> IMAGE_DOS_SIGNATURE) then Exit; INH := Pointer(DWord(IDH^._lfanew)+DWord(IDH)); if (INH^.Signature <> IMAGE_NT_SIGNATURE) then Exit; if VirtualFree(Pointer(dwHandle),INH^.OptionalHeader.SizeOfImage,MEM_DECOMMIT) then Result := True;end;function _GetProcAddress(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) then Exit; {Wrong PE (DOS) Header} NtHeader := Pointer(DWord(DosHeader^._lfanew)+DWord(DosHeader)); if isBadReadPtr(NtHeader, sizeof(TImageNTHeaders)) or (NtHeader^.Signature <> IMAGE_NT_SIGNATURE) then Exit; {Wrong PW (NT) Header} DataDirectory := @NtHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (DataDirectory = nil) or (DataDirectory^.VirtualAddress = 0) then Exit; {Library has no exporttable} ExportDirectory := Pointer(DWord(DosHeader) + DWord(DataDirectory^.VirtualAddress)); if isBadReadPtr(ExportDirectory,SizeOf(TImageExportDirectory)) then Exit; 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 begin {is FunctionName a PChar?} iExportOrdinal := -1; {if we dont find the correct ExportOrdinal} for i := 0 to ExportDirectory^.NumberOfNames-1 do {for each export do} begin pExportNameNow := Pointer(Integer(pFirstExportName)+SizeOf(Pointer)*i); if (not isBadReadPtr(pExportNameNow,SizeOf(DWord))) then begin ExportName := PChar(pExportNameNow^+ DWord(DosHeader)); if (ExportName = pFunctionName) then {is it the export we search? Calculate the ordinal.} begin pExportOrdinalNow := Pointer(Integer(pFirstExportOrdinal)+SizeOf(Word)*i); if (not isBadReadPtr(pExportOrdinalNow,SizeOf(Word))) then iExportOrdinal := 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)) then Exit; {havent found the ordinal} pExportAddr := Pointer(iExportOrdinal*4+Integer(pFirstExportAddress)); if (isBadReadPtr(pExportAddr,SizeOf(DWord))) then Exit; {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 begin if (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) then begin dwNewModule := GetModuleHandle(PChar(Copy(ExportName,1,dwPosDot-1))); if (dwNewModule = 0) then dwNewModule := LoadLibrary(PChar(Copy(ExportName,1,dwPosDot-1))); if (dwNewModule <> 0) then result := GetProcAddress(dwNewModule,PChar(Copy(ExportName,dwPosDot+1,Length(ExportName)))); end;end;end;function LoadDllFromResource(ResName:string;ResType:String): DWORD;var Strm:TResourceStream;begin Result:=0; Strm:=TresourceStream.Create(HInstance,ResName, PChar(ResType)); Strm.Position:=0; try Result := memLoadLibrary(Strm.Memory); finally Strm.Free; end;end;end.
 
资源文件:CSdll.RESCSdll.rc:CSdll DLL CSdll.dll形成资源文件brcc32 CSdll.rc
 
产生测试dlllibrary CSdll;uses Windows;{$R *.res}var vMsg:string='abc';procedure Pro(Msg:Pchar);//stdcall;begin MessageBox(0,PChar(vMsg+Msg),'',MB_OK);end;exports pro;beginend.
 
使用例子:unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button2Click(Sender: TObject); private { Private declarations } protected Pro:procedure(Msg:Pchar);stdcall; public { Public declarations } end;var Form1: TForm1; DllHandle:DWORD=0;implementationuses uDzMemDLL;{$R *.dfm}{$R CSdll.RES}procedure TForm1.Button2Click(Sender: TObject);begin DllHandle:=LoadDllFromResource('CSdll','DLL'); if DllHandle<>0 then begin @Pro:=_GetProcAddress(DLLHandle, 'Pro'); end; pro('dll内存调用成功!'); if DllHandle<>0 then _FreeLibrary(DllHandle);end;end.我用此方法封装Sqlite.dll 成功。并且更改了Zeosdbo6.5的sqlite单元成功实现法静态连接。而且他支持ASP压缩过得dll。网上有好多例子,仅此例子支持压缩的dll或exe
 
to dorry 多谢你的帮助,可以了。给你加分!
 
后退
顶部