-
Приветствую! Есть функция:
procedure ListDLLExports(FileName: String);
type
TDWordArray = array [0..$FFFFF] of DWORD;
var
Name: String;
i, dirsize: Cardinal;
imageinfo: LoadedImage;
pNameRVAs: ^TDWordArray;
pDummy: PImageSectionHeader;
pExportDirectory: PImageExportDirectory;
begin
if MapAndLoad(PChar(FileName), nil, @imageinfo, True, True) then
begin
try
pExportDirectory := ImageDirectoryEntryToData(imageinfo.MappedAddress,
False,
IMAGE_DIRECTORY_ENTRY_EXPORT,
dirsize);
if (pExportDirectory <> nil) then
begin
pNameRVAs := ImageRvaToVa(imageinfo.FileHeader, imageinfo.MappedAddress,
DWORD(pExportDirectory^.AddressOfNames),
pDummy);
for i := 0 to pExportDirectory^.NumberOfNames - 1 do
begin
Name := PChar(ImageRvaToVa(imageinfo.FileHeader,
imageinfo.MappedAddress,
pNameRVAs^[i], pDummy));
Show(Name);
end;
end;
finally
UnMapAndLoad(@imageinfo);
end;
end;
end;
Показывает список экспортируемых функций у длл. Хочу переписать ее в таком виде: function ListDLLExports(FileName, ProcName: String): Pointer; Чтобы результат ее выполнения был такой же как у GetProcAddress. Подскажите пожалуйста как это сделать :)
-
Основная сложность: Не знаю откуда вытащить адресс функции. Предполагаю что из этой структуры: PImageExportDirectory = ^TImageExportDirectory;
_IMAGE_EXPORT_DIRECTORY = packed record
Characteristics: DWord;
TimeDateStamp: DWord;
MajorVersion: Word;
MinorVersion: Word;
Name: DWord;
Base: DWord;
NumberOfFunctions: DWord;
NumberOfNames: DWord;
AddressOfFunctions: ^PDWORD;
AddressOfNames: ^PDWORD;
AddressOfNameOrdinals: ^PWord;
end; Подскажите пожалуйста :)
-
program Project1;
uses
Windows,
SysUtils;
var
FuncName: AnsiString;
pNtHeaders: PImageNtHeaders;
ExportAddr: TImageDataDirectory = (VirtualAddress: 0; Size: 0);
ImageBase: DWORD;
IED: PImageExportDirectory;
I: Integer;
FuntionAddr: DWORD;
NamesCursor: PDWORD;
OrdinalCursor: PWORD;
Ordinal: DWORD;
begin
ImageBase := GetModuleHandle('NTDLL.DLL');
if PWORD(ImageBase)^ = IMAGE_DOS_SIGNATURE then
begin
pNtHeaders := Pointer(ImageBase + DWORD(PImageDosHeader(ImageBase)^._lfanew)
);
ExportAddr.VirtualAddress := 0;
ExportAddr.Size := 0;
if (pNtHeaders^.Signature = IMAGE_NT_SIGNATURE) and
(pNtHeaders^.FileHeader.Machine = IMAGE_FILE_MACHINE_I386) then
begin
ExportAddr := pNtHeaders.OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT];
if ExportAddr.VirtualAddress <> 0 then
Inc(ExportAddr.VirtualAddress, ImageBase)
else
ExportAddr.Size := 0;
end;
end;
if (ImageBase = 0) or (ExportAddr.VirtualAddress = 0) then
Exit;
IED := PImageExportDirectory(ExportAddr.VirtualAddress);
I := 1;
NamesCursor := Pointer(ImageBase + DWORD(IED^.AddressOfNames));
OrdinalCursor := Pointer(ImageBase + DWORD(IED^.AddressOfNameOrdinals));
while I < Integer(IED^.NumberOfNames) do
begin
FuncName := PAnsiChar(ImageBase + PDWORD(NamesCursor)^);
Ordinal := OrdinalCursor^ + IED^.Base;
FuntionAddr := ImageBase + DWORD(IED^.AddressOfFunctions);
FuntionAddr := ImageBase + PDWORD(FuntionAddr + (Ordinal - 1) * 4)^;
Writeln(FuncName, ' proc addr: 0x', IntToHex(FuntionAddr, 8));
Inc(I);
Inc(NamesCursor);
Inc(OrdinalCursor);
end;
Readln;
end.
-
uses ImageHlp, PsAPI;
function _GetKernel32BaseAddress(ProcessHandle: THandle): Integer;
const
MM_USER_PROBE_ADDRESS = $7FFF0000;
var
Address: THandle;
Buffer: TMemoryBasicInformation;
Length: DWORD;
FileName: array [0 .. MAX_PATH - 1] of WideChar;
LoadLibraryBaseAddress: Integer;
begin
Result := 0;
Address := 0;
Length := Sizeof(TMemoryBasicInformation);
if VirtualQueryEx(ProcessHandle, Pointer(Address), Buffer, Length) = Length then
begin
while Address < MM_USER_PROBE_ADDRESS do
begin
if VirtualQueryEx(ProcessHandle, Pointer(Address), Buffer, Length) = Length then
begin
Inc(Address, Buffer.RegionSize);
if GetMappedFileNameW(ProcessHandle, Buffer.BaseAddress, @FileName[0], MAX_PATH) > 0 then
begin
if LowerCase(ExtractFileName(FileName)) = 'kernel32.dll' then
begin
Result := Integer(Buffer.BaseAddress);
Break;
end;
end;
end;
end;
end;
end;
function _GetLoadLibraryWAddress: Integer;
type
TDWordArray = array [0 .. $FFFFF] of DWORD;
var
i: Cardinal;
ImageInfo: LoadedImage;
ImageExportDirectory: PImageExportDirectory;
ImageDirectorySize: ULONG;
LastRvaSection: PImageSectionHeader;
RvaAddressOfNames, RvaAddressOfFunctions: ^TDWordArray;
RvaAddressOfNameOrdinals: ^TWordArray;
LabraryName: string;
Ordinal: Word;
begin
Result := 0;
if MapAndLoad('C:\WINDOWS\system32\kernel32.dll', nil, @ImageInfo, True, True) then
begin
try
ImageExportDirectory := ImageDirectoryEntryToData(ImageInfo.MappedAddress, False, IMAGE_DIRECTORY_ENTRY_EXPORT, ImageDirectorySize);
if (ImageExportDirectory <> nil) then
begin
RvaAddressOfNames := ImageRvaToVa(ImageInfo.FileHeader, ImageInfo.MappedAddress, DWORD(ImageExportDirectory^.AddressOfNames), LastRvaSection);
RvaAddressOfNameOrdinals := ImageRvaToVa(ImageInfo.FileHeader, ImageInfo.MappedAddress, DWORD(ImageExportDirectory^.AddressOfNameOrdinals), LastRvaSection);
RvaAddressOfFunctions := ImageRvaToVa(ImageInfo.FileHeader, ImageInfo.MappedAddress, DWORD(ImageExportDirectory^.AddressOfFunctions), LastRvaSection);
for i := 0 to ImageExportDirectory^.NumberOfNames - 1 do
begin
LabraryName := PChar(ImageRvaToVa(ImageInfo.FileHeader, ImageInfo.MappedAddress, RvaAddressOfNames^[i], LastRvaSection));
if LowerCase(LabraryName) = 'loadlibraryw' then
begin
Result := (RvaAddressOfFunctions^[i]);
Break;
end;
end;
end;
finally
UnMapAndLoad(@ImageInfo);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ProcessHandle: THandle;
Address: Integer;
begin
ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, True, GetCurrentProcessId);
Address := _GetLoadLibraryWAddress;
if Address > 0 then
Caption := IntToHex(_GetKernel32BaseAddress(ProcessHandle) + Address, 0);
Caption := Caption + ' / ' + IntToHex(Integer(GetModuleHandleW('kernel32.dll')) + Address, 0);
Caption := Caption + ' / ' + IntToHex(Integer(GetProcAddress(GetModuleHandleW('kernel32.dll'), 'LoadLibraryW')), 0);
if ProcessHandle <> 0 then
CloseHandle(ProcessHandle);
end;
-
Спасибо за помощь, все работает прекрасно! :)
-
Еще один вопрос, по поводу кода от Rouse_ Как переделать код с учетом: Однако полученный адрес м.б. ссылкой на имя функции из другой dll (forwarded экспорт), поэтому нужно еще проверить - если полученный адрес лежит за пределами таблицы экспорта, то это реальный адрес экспортируемой функции, если же внутри, то это указатель на составное имя - например, в kernel32 адрес ф-ии HeapAlloc даст ссылку не на саму ф-ю, а на строку "ntdll.RtlAllocateHeap"
-
> например, в kernel32 адрес ф-ии HeapAlloc даст ссылку не > на саму ф-ю, а на строку "ntdll.RtlAllocateHeap"
Хм, да - не учел я этот момент: program Project1;
uses
Windows,
SysUtils;
var
FuncName: AnsiString;
pNtHeaders: PImageNtHeaders;
ExportAddr: TImageDataDirectory = (VirtualAddress: 0; Size: 0);
ImageBase: DWORD;
IED: PImageExportDirectory;
IID: DWORD;
I: Integer;
FuntionAddr: DWORD;
NamesCursor: PDWORD;
OrdinalCursor: PWORD;
Ordinal: DWORD;
begin
ImageBase := GetModuleHandle('kernel32.DLL');
if ImageBase < HINSTANCE_ERROR then Exit;
IID := 0;
if PWORD(ImageBase)^ = IMAGE_DOS_SIGNATURE then
begin
pNtHeaders := Pointer(ImageBase + DWORD(PImageDosHeader(ImageBase)^._lfanew));
ExportAddr.VirtualAddress := 0;
ExportAddr.Size := 0;
if (pNtHeaders^.Signature = IMAGE_NT_SIGNATURE) and
(pNtHeaders^.FileHeader.Machine = IMAGE_FILE_MACHINE_I386) then
begin
ExportAddr := pNtHeaders.OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT];
IID :=
pNtHeaders.OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + ImageBase;
if ExportAddr.VirtualAddress <> 0 then
Inc(ExportAddr.VirtualAddress, ImageBase);
end;
end;
if ExportAddr.VirtualAddress = 0 then Exit;
IED := PImageExportDirectory(ExportAddr.VirtualAddress);
I := 1;
NamesCursor := Pointer(ImageBase + DWORD(IED^.AddressOfNames));
OrdinalCursor := Pointer(ImageBase + DWORD(IED^.AddressOfNameOrdinals));
while I < Integer(IED^.NumberOfNames) do
begin
FuncName := PAnsiChar(ImageBase + PDWORD(NamesCursor)^);
Ordinal := OrdinalCursor^ + IED^.Base;
FuntionAddr := ImageBase + DWORD(IED^.AddressOfFunctions);
FuntionAddr := ImageBase + PDWORD(FuntionAddr + (Ordinal - 1) * 4)^;
if (FuntionAddr > ExportAddr.VirtualAddress) and (FuntionAddr <= IID) then
Writeln(FuncName, ' forwarded -> ', PAnsiChar(FuntionAddr))
else
Writeln(FuncName, ' proc addr: 0x', IntToHex(FuntionAddr, 8));
Inc(I);
Inc(NamesCursor);
Inc(OrdinalCursor);
end;
Readln;
end.
-
Спасибо! :) Кстати, вот еще один из вариантов решений, возможно кому то будет полезно:
function GetAddr(szDll, szFunc: PChar): Pointer;
var
s: String;
NamesCursor: PDWORD;
OrdinalCursor: PWORD;
IED: PImageExportDirectory;
pNtHeaders: PImageNtHeaders;
ExportAddr: TImageDataDirectory;
i, j, Ordinal, FuntionAddr, ImageBase: Dword;
begin
Result := nil;
ZeroMemory(@ExportAddr, SizeOf(ExportAddr));
ImageBase := GetModuleHandle(szDll);
if PWORD(ImageBase)^ = IMAGE_DOS_SIGNATURE then
begin
pNtHeaders := Pointer(ImageBase + DWORD(PImageDosHeader(ImageBase)^._lfanew));
if (pNtHeaders^.Signature = IMAGE_NT_SIGNATURE) and
(pNtHeaders^.FileHeader.Machine = IMAGE_FILE_MACHINE_I386) then
begin
ExportAddr := pNtHeaders.OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT];
if ExportAddr.VirtualAddress <> 0 then
Inc(ExportAddr.VirtualAddress, ImageBase)
else ExportAddr.Size := 0;
end;
end;
if (ImageBase = 0) or (ExportAddr.VirtualAddress = 0) then Exit;
IED := PImageExportDirectory(ExportAddr.VirtualAddress);
i := 1;
NamesCursor := Pointer(ImageBase + DWORD(IED^.AddressOfNames));
OrdinalCursor := Pointer(ImageBase + DWORD(IED^.AddressOfNameOrdinals));
while i < Dword(IED^.NumberOfNames) do
begin
Ordinal := OrdinalCursor^ + IED^.Base;
FuntionAddr := ImageBase + DWORD(IED^.AddressOfFunctions);
FuntionAddr := ImageBase + PDWORD(FuntionAddr + (Ordinal - 1) * 4)^;
if lstrcmpi(szFunc, PAnsiChar(ImageBase + PDWORD(NamesCursor)^)) = 0 then
begin
if (FuntionAddr > ExportAddr.VirtualAddress) and
(FuntionAddr < ExportAddr.VirtualAddress + ExportAddr.Size) then
begin
s := PAnsiChar(FuntionAddr); j := Pos('.', s);
if j > 0 then
begin
s[j] := #0; Result := GetAddr(@s[1], @s[j + 1]); end;
end
else Result := Pointer(FuntionAddr);
Break; end;
Inc(i);
Inc(NamesCursor);
Inc(OrdinalCursor);
end;
end;
|