![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Получение адреса функции по таблице экспорта.
Riply © (2006-12-07 20:02:00)Здравствуйте !
Пытаюсь "замапить" Dll и получить адрес функции по ее имени.
Функцию найти удается, но ее адрес (вот негодяй) не хочет совпадать
с адресом, полученным при помощи GetProcAddress - GetModuleHandle.
Я понимаю, что они не обязаны совпадать, но иногда ведь должны :)
Что я делаю не так ? ( Надеюсь не все :).
type
PDWordArray = ^TDWordArray;
TDWordArray = array [0..$FFFFF] of DWord;
function Get_ExportProcAddres(const pMap: Pointer; const ProcName: string; var Addr: DWord): Boolean;
var
pExportDirectory: PImageExportDirectory;
pImSectHearder: PImageSectionHeader;
pNameRVAs: PDWordArray;
ImageName: string;
cbDirSize: DWord;
i: integer;
begin
Result:= False;
pExportDirectory := ImageDirectoryEntryToData(pMap,
False, IMAGE_DIRECTORY_ENTRY_EXPORT, cbDirSize);
if (pExportDirectory <> nil) then
begin
pImSectHearder := nil;
pNameRVAs:= ImageRvaToVa(ImageNtHeader(pMap), pMap,
DWord(pExportDirectory^.AddressOfNames), pImSectHearder);
for i := 0 to pExportDirectory^.NumberOfNames - 1 do
begin
pImSectHearder := nil;
ImageName := PChar(ImageRvaToVa(ImageNtHeader(pMap), pMap, pNameRVAs^[i], pImSectHearder));
if CompareText(ProcName, ImageName) = 0 then
begin
Result:= True;
Addr:= pNameRVAs^[i];
Break;
end;
end;
end;
end;
function TestFunctAddress(const pModName, pProcName: PChar): Boolean;
var
HFile, HMap: THandle;
Map: Pointer;
QSysInfo: Pointer;
cbAddr: DWord;
begin
Result := false;
HFile := CreateFileA(pModName, GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
Win32Check(HFile <> INVALID_HANDLE_VALUE);
try
HMap := CreateFileMappingA(HFile, nil, PAGE_READONLY, 0, 0, nil);
Win32Check(HMap <> 0);
try
Map := MapViewOfFile(HMap, FILE_MAP_READ, 0, 0, 0);
Win32Check(Assigned(Map));
try
QSysInfo := GetProcAddress(GetModuleHandle(pModName), pProcName);
if Assigned(QSysInfo) then
if Get_ExportProcAddres(Map, pProcName, cbAddr) then
begin
Result:= (cbAddr = DWord(QSysInfo) - GetModuleHandle(pModName));
ShowMessage(IntToStr(cbAddr) + #13#10 + IntToStr(DWord(QSysInfo) - GetModuleHandle(pModName)));
end;
finally
UnmapViewOfFile(Map);
end;
finally
CloseHandle(HMap);
end;
finally
CloseHandle(HFile);
end;
end;
И вызов : TestFunctAddress('C:\Windows\system32\ntdll.dll', 'NtQuerySystemInformation');
Riply (2006-12-08 15:48:00) [21]> [11] Сергей М. © (08.12.06 08:38)
>Поясни, зачем тебе понадобилось это самое "замапить" ..
>Тебе требуется перехватить вызов некоей ф-ции ?
С точностью до наоборот :)
Есть кем-то перехваченная функция.
А это попыка получить адрес настоящей.
Ну, хотя бы, не адрес а смещение, которое, в неперехваченом варианте,
равно GetProcAddress(GetModuleHandle(NtDll), NtQuerySysInfo) - GetModuleHandle(NtDll)
Сумбурно, но что делать :)
oxffff (2006-12-08 09:19:00) [22]
> Riply © (08.12.06 01:52) [10]
> >[9] oxffff © (08.12.06 00:52)
> >Тогда, что у вас не получается?
> Давай без дискриминации :)
Абсолютно без дискриминации.
Просто это у меня вызывает уважение.
Сергей М. (2006-12-08 08:38:00) [23]
> Riply
Поясни, зачем тебе понадобилось это самое "замапить" ..
Тебе требуется перехватить вызов некоей ф-ции ?
Riply (2006-12-08 01:52:00) [24]>[9] oxffff © (08.12.06 00:52)
>Тогда, что у вас не получается?
Давай без дискриминации :)
Суть вот в чем:
Игорь Шевченко приводил примерно такой код для определения перехвачена
функция или нет:
HFile := CreateFileA(DllPath, GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
try
HMap := CreateFileMappingA(HFile, nil, PAGE_READONLY, 0, 0, nil);
try
Map := MapViewOfFile(HMap, FILE_MAP_READ, 0, 0, 0);
try
Headers := RtlImageNtHeader(HMODULE(Map));
if Assigned(Headers) then
begin
Result := Headers.OptionalHeader.ImageBase <> GetModuleHandle(Lib_NtDll);
if not Result then
begin
QSysInfo := GetProcAddress(GetModuleHandle(Lib_NtDll), _NtQuerySysInfo);
if Assigned(QSysInfo) then
begin
Result:= (Cardinal(QSysInfo) <= Headers.OptionalHeader.ImageBase)
or (Cardinal(QSysInfo) > Headers.OptionalHeader.ImageBase + Headers.OptionalHeader.SizeOfCode);
if not Result then
Result := IsNtDllCodeHooked(DllPath, ULONG(QSysInfo) - Headers.OptionalHeader.ImageBase);
end else
Result := true;
end;
end;
finally
UnmapViewOfFile(Map);
end;
finally
CloseHandle(HMap);
end;
finally
CloseHandle(HFile);
end;
Так вот, интересует как можно вычислить смещение
ULONG(QSysInfo) - Headers.OptionalHeader.ImageBase
если мы не прошли условие:
(Cardinal(QSysInfo) <= Headers.OptionalHeader.ImageBase)
or (Cardinal(QSysInfo) > Headers.OptionalHeader.ImageBase + Headers.OptionalHeader.SizeOfCode);
Игорь посоветовал смотреть в сторону экспорта.
oxffff (2006-12-08 00:52:00) [25]А вы девушка?
Тогда, что у вас не получается?
oxffff (2006-12-08 00:51:00) [26]Слушай а ты не ошибся таблицами.
Почему таблица экспорта?
oxffff (2006-12-08 00:49:00) [27]Таблица OriginalFirstThunk во время работы программы не меняется.
Загрузчик заполняет таблицу по FirstThunk.
Поясни, что с чем ты сравниваешь и что не получается?
oxffff (2006-12-08 00:46:00) [28]Поясни какие у тебя проблемы.
В секции импорта 2 таблицы
одна это OriginalFirstThunk
Вторая FirstThunk
C какой ты сравниваешь?
И что ты вообще сравниваешь?
jack128 (2006-12-08 00:29:00) [29]собственно результаты, возвращаемые твой функций об этом и говорят.. Всё таки 32К - слишком маленький адрес...
jack128 (2006-12-08 00:26:00) [30]jack128 © (08.12.06 0:26) [3]
Я не спец, носудя по MSDN:
jack128 (2006-12-08 00:26:00) [31]Хем.. Я не спец, судя по MSDN:
The ImageRvaToVa function locates a relativevirtual address (RVA)
выделенное слово переводится, как относительный...
Riply (2006-12-07 21:23:00) [32]>[1] jack128 © (07.12.06 20:56)
>Один и тот же файл замапин два раза (один раз виндой, другой - тобой) но замапин по разным адресам..
А я сравниваю не адреса "мапов", а адреса функций, найденых в этих "мапах"
Кстати, в приведенном тобой примере, они отлично совпадают .
function TestAddress: Boolean;
const
pModName = 'C:\Windows\system32\ntdll.dll';
var
hFile, hMap1, hMap2: THandle;
Addr1, Addr2: Pointer;
fs: TFileStream;
Proc1, Proc2: DWord;
begin
Result:= False;
HFile := CreateFileA(pModName, GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
try
hMap1 := CreateFileMappingA(HFile, nil, PAGE_READONLY, 0, 0, nil);
hMap2 := CreateFileMappingA(HFile, nil, PAGE_READONLY, 0, 0, nil);
try
Addr1 := MapViewOfFile(HMap1, FILE_MAP_READ, 0, 0, 0);
Addr2 := MapViewOfFile(HMap2, FILE_MAP_READ, 0, 0, 0);
try
Get_ExportProcAddres(Addr1, 'NtQuerySystemInformation', Proc1);
Get_ExportProcAddres(Addr2, 'NtQuerySystemInformation', Proc2);
Result:= Proc1 = Proc2;
finally
UnmapViewOfFile(Addr1); UnmapViewOfFile(Addr2);
end;
finally
CloseHandle(hMap1); CloseHandle(hMap2)
end;
finally
CloseHandle(HFile);
end;
end;
P.S. Функцию Get_ExportProcAddres см. выше
jack128 (2006-12-07 20:56:00) [33]Riply © (07.12.06 20:02)
Я понимаю, что они не обязаны совпадать, но иногда ведь должны :)
Хм. А почему должны? Один и тот же файл замапин два раза (один раз виндой, другой - тобой) но замапин по разным адресам..
const
FileName = 'F:\p2p на E\download\Setup.exe';
var
hMap1, hMap2: THandle;
Addr1, Addr2: Pointer;
fs: TFileStream;
begin
fs := TFileStream.Create(FileName, fmOpenRead);
try
hMap1 := CreateFileMappingA(fs.Handle, nil, PAGE_READONLY, 0, 0, nil);
hMap2 := CreateFileMappingA(fs.Handle, nil, PAGE_READONLY, 0, 0, nil);
try
Addr1 := MapViewOfFile(HMap1, FILE_MAP_READ, 0, 0, 0);
Addr2 := MapViewOfFile(HMap2, FILE_MAP_READ, 0, 0, 0);
try
Assert(Addr1 = Addr2);
finally
UnmapViewOfFile(Addr1); UnmapViewOfFile(Addr2);
end;
finally
CloseHandle(hMap1); CloseHandle(hMap2)
end;
finally
fs.Free;
end;
end;