Форум: "Система";
Текущий архив: 2002.11.11;
Скачать: [xml.tar.bz2];
ВнизСканирование списков модулей, загруженных в АП тек.процесса Найти похожие ветки
← →
Digitman (2002-09-03 12:34) [0]К сожалению, информация о нижеследующем слишком разрозненна, неполна и противоречива.
Исх.данные :
Вот структуры для доступа к неким спискам, ассоциированным с процессом :
PListEntry = ^TListEntry;
TListEntry = packed record
FLink: PListEntry;
BLink: PListEntry;
end;
PModuleHeader = ^TModuleHeader;
TModuleHeader = packed record
dw00: DWord;
dw04: DWord;
list1,
list2,
list3: TListEntry;
end;
PProcessModuleInfo = ^TProcessModuleInfo;
TProcessModuleInfo = packed record
RecordSize: DWord;
ModuleHeader: TModuleHeader;
end;
PProcessEnvironmentBlock = ^TProcessEnvironmentBlock;
TProcessEnvironmentBlock = packed record
.....
ProcessHinstance: THandle;
ModuleInfo: PProcessModuleInfo;
Unknown2: DWord;
DefaultHeap: THandle;
.....
end;
Здесь TListEntry - управляющий заголовок элемента некоего двунаправленного списка.
Собственно элемент списка, видимо, следует сразу за заголовком (?) и формат его может быть произвольным, в зависимости от контекста.
Вопрос :
1. Назначение списков TModuleHeader.list1(,2,3)
2. Полная структура элемента списка (какого конкретно из 3-х ?), перечисляющего модули, загруженные в АП процесса, PEB которого рассматривается. В дан.случае интересен лишь handle (image base) каждого модуля.
← →
Игорь Шевченко (2002-09-03 12:59) [1]День добрый, Digitman ©,
Если для NT-систем, то, может и могу чем-то помочь, если задача будет более подробна.
С уважением,
← →
Digitman (2002-09-03 13:30) [2]<Игорь Шевченко>
Добрый день !
Да , пока интересна только NT-платформа.
Задача проста :
получить хэндлы всех PE-модулей, загруженных в АП тек.процесса, для некоторой последующей модификации таблицы импорта каждого из них.
toolhelp32 snapshot отпадает - работает не в динамике.
адрес ProcessEnvironmentBlock вычисляется элементарно, равно как и ProcessModuleInfo вместе с ModuleHeader.
в рез-те вынужденной трассировки NtGetModuleFileName() на данный момент мне известно следующее :
- список модулей ведется системой в TListEntry.List1.
- по смещению $18 от начала заголовка элемента списка якобы находится искомое значение хэндла
- блокировка/разблокировка работы сист.загрузчика на момент сканирования списка достигается управлением крит.секцией, ссылка на хэндл которой находится по смещению $A0 (поле TProcessEnvironmentBlock.LoaderLock типа PCriticalSection)
Хотелось бы таки поиметь наиболее правдоподобное и детальное описание структур элементов каждого из вышеупомянутых списков : Коберниченко и Шрайбер либо врут безбожно либо очепяток - море. Да и описание интересующих меня структур отсутствует у обоих авторов напрочь. Нет их, к сожалению, и на http://Sysinternals.com
← →
Игорь Шевченко (2002-09-03 14:18) [3]Гэри Неббет, справочник по базовым функциям NT/Windows 2000 (Native API reference)
RtlQueryProcessDebugInformation с параметром PDI_MODULES
С уважением,
← →
Digitman (2002-09-03 14:31) [4]Нет у меня, к сож., этого букваря под рукой сейчас.
И - опять же - imho, не в динамике работать будет эта ф-ция. Вернет мне статический снимок списка на момент запроса. А при модификации список может измениться. Можно, конечно, блокировать загрузчик перед вызовом ф-ции и после модификации модулей из полученного списка, но это тоже через зад получится ...
← →
Игорь Шевченко (2002-09-03 14:45) [5]Эти смещения не меняются в зависимости от версии ОС ? :-)
Кстати, минуту, ntdll гляну :-)))
← →
paul_shmakov (2002-09-03 15:24) [6]могу такой вариант предложить - мне он нравится больше всего
#include <windows.h>
#include <tchar.h>
#include <iostream>
#ifdef UNICODE
#define _tcout std::wcout
#else
#define _tcout std::cout
#endif
int main(void)
{
TCHAR szModuleName[MAX_PATH];
HMODULE hMod = NULL;
PBYTE pb = NULL;
MEMORY_BASIC_INFORMATION mbi;
while(VirtualQuery(pb, &mbi, sizeof(mbi)) == sizeof(mbi))
{
if(mbi.State == MEM_FREE)
mbi.AllocationBase = mbi.BaseAddress;
if((mbi.AllocationBase == mbi.BaseAddress) && (NULL != mbi.AllocationBase))
{
hMod = static_cast<HMODULE>(mbi.AllocationBase);
if(GetModuleFileName(hMod, szModuleName,
sizeof(szModuleName) / sizeof(szModuleName[0])) > 0)
{
_tcout << hMod << _T(" ") << szModuleName << _T("\n");
}
}
pb += mbi.RegionSize;
}
return 0;
}
← →
Digitman (2002-09-03 16:06) [7]>paul_shmakov
Тогда уж так :
var
hModule: THandle;
mbi: TMemoryBasicInformation;
pRegion: PChar;
begin
pRegion := nil;
while VirtualQuery(pRegion, mbi, sizeof(mbi)) = sizeof(mbi) do
begin
if mbi.State = MEM_FREE then
mbi.AllocationBase := mbi.BaseAddress;
if (mbi.AllocationBase = mbi.BaseAddress) and Assigned(mbi.AllocationBase) then
begin
hModule := THandle(mbi.AllocationBase);
if mbi.Type_9 = MEM_IMAGE then
showmessage(inttohex(hModule, 8));
end;
Inc(pRegion, mbi.RegionSize);
end;
Только вот в момент перечисления системный загрузчик никак не блокирован( .. и состояние AП в части загруженных PE-образов вполне может измениться
← →
Digitman (2002-09-03 16:32) [8]Два варианта для сравнения :
1. От <paul_shmakov>
var
hModule: THandle;
mbi: TMemoryBasicInformation;
pRegion: PChar;
cName: array[0..256] of char;
...
pRegion := nil;
while VirtualQuery(pRegion, mbi, sizeof(mbi)) = sizeof(mbi) do
begin
if mbi.State = MEM_FREE then
mbi.AllocationBase := mbi.BaseAddress;
if (mbi.AllocationBase = mbi.BaseAddress) and Assigned(mbi.AllocationBase) then
begin
hModule := THandle(mbi.AllocationBase);
if mbi.Type_9 = MEM_IMAGE then
begin
GetModuleFileName(hModule, @cName, 255);
ShowMessage(inttohex(hModule, 8) + " : " + string(cName));
end;
end;
Inc(pRegion, mbi.RegionSize);
end;
2. От <Digitman> (быстрее работающий, но - "корявый" без нормальных деклараций структур)
var
pNextModuleInfo: PListEntry;
peb: PPeb;
mh: PModuleHeader;
pmi: PProcessModuleInfo;
hModule: THandle;
...
asm
mov eax, fs:[$18]
mov eax, [eax + $30]
mov [peb], eax
end;
pmi := peb.ModuleInfo;
mh := @pmi.ModuleHeader;
pNextModuleInfo := mh.LoadedModuleList.FLink;
while pNextModuleInfo <> @pmi.ModuleHeader.LoadedModuleList do
begin
hModule:= PInteger(DWord(pNextModuleInfo) + $18)^;
showmessage(inttohex(hModule, 8));
pNextModuleInfo := pNextModuleInfo.FLink;
end;
Ни один вариант не учитывает то, что в момент енумерации системный загрузчик продолжает работать ! И его оч.желательно блокировать. И желательно - с использованием PEB.LoaderLock- поля. Что, в принципе, не вызывает проблем при наличии деклараций PEB-структуры для нескольких платформ ...
Какие еще будут варианты ?
← →
Digitman (2002-09-03 17:01) [9]минимально необходимые фрагменты деклараций к варианту 2 :
PListEntry = ^TListEntry;
TListEntry = packed record
FLink: PListEntry;
BLink: PListEntry;
end;
PModuleHeader = ^TModuleHeader;
TModuleHeader = packed record
dw00: Pointer;
dw04: Pointer;
LoadedModuleList, list2, list3: TListEntry; // что за списки 2 и 3 ? пока неясно
end;
PProcessModuleInfo = ^TProcessModuleInfo;
TProcessModuleInfo = packed record
Size: DWord;
ModuleHeader: TModuleHeader;
end;
PPeb = ^TPeb;
TPeb = packed record
AllocSize: Pointer;
Unknown1: Pointer;
ProcessHinstance: Pointer;
ModuleInfo: PProcessModuleInfo;
Unknown2: Pointer;
DefaultHeap: Pointer;
end;
← →
paul_shmakov (2002-09-03 17:29) [10]2 Digitman:
"Ни один вариант не учитывает то, что в момент енумерации системный загрузчик продолжает работать ! И его оч.желательно блокировать."
если не секрет - зачем блокировать загрузчик? хотя в вашем варианте данные в peb действительно могут измениться, что вызовет av. кто знает..
в моем блокировать ничего не надо.
← →
paul_shmakov (2002-09-03 17:34) [11]2 Digitman:
кстати, вы добавили "if mbi.Type_9 = MEM_IMAGE then" к моему коду. изначально этой проверки не было, т.к., если я не ошибаюсь, win9x/me не поддерживают этот флаг в MEMORY_BASIC_INFORMATION.
поэтому без этой проверки код должен работать везде, а с ней - только на nt/2k/xp.
← →
Digitman (2002-09-03 18:23) [12]>paul_shmakov
> зачем блокировать загрузчик?
Блокировка нужна для исключения ситуации, когда в момент работы с таблицей импорта очередного модуля из получаемого списка этот модуль будет выгружен другим потоком. Исключение, видимо, можно сделать только для ситуации работы енумератора в контексте исполнения DLLProc любого из модулей процесса (имеется ввиду - библиотечные модули) - DLLProc исполняется в крит.секции и загрузчик будет ждать ее освобождения.
> в моем блокировать ничего не надо
А толку-то собственно от енумератора ? Мне ж не просто перечислить хэндлы модулей требуется - для каждого полученного хэндла возможно потребуется модификация таблицы импорта. А в момент модификации незаблокированная система загрузки/выгрузки запросто может выгрузить модуль в другом кодовом потоке или список претертип изменения из-за загрузки нового модуля (и я его упущу из рассмотрения)
MEM_IMAGE меня вполне устраивает, т.к. речь идет в первую очередь об NT-платформах. Другой вопрос, что енумератор должен работать предельно быстро (вместе с подразумеваемым кодом сканирования и возможной модификации import table очер.модуля), В твоем же варианте - как он ни красив на первый взгляд - будет масса "холостых" циклов из-за фильтрации модулей вызовом GetModuleFileName(), каждый из которых "лезет" в PEB и занимается символьным копированием, и далеко не каждый из которых вернет достоверный факт того, что очередной регион есть очередной искомый мной PE-образ.
Собственно, в теле GetModuleFileName() и работает то, что я пытаюсь представить своим вариантом, так что получается не очень хорошо и эффективно, imho.. Так что пока вот теряюсь я в выборе решения..
← →
paul_shmakov (2002-09-03 20:43) [13]"Блокировка нужна для исключения ситуации, когда в момент работы с таблицей импорта очередного модуля из получаемого списка этот модуль будет выгружен другим потоком. Исключение, видимо, можно сделать только для ситуации работы енумератора в контексте исполнения DLLProc любого из модулей процесса (имеется ввиду - библиотечные модули) - DLLProc исполняется в крит.секции и загрузчик будет ждать ее освобождения."
как вариант можно увеличивать счетчик пользователей модуля тем или иным способом на время работы, а потом уменьшать. например, если это dll:
LoadLibrary()
try
// работаем с импортом модуля
finally
FreeLibrary();
end;
что-то вроде этого.
"В твоем же варианте - как он ни красив на первый взгляд - будет масса "холостых" циклов из-за фильтрации модулей вызовом GetModuleFileName(), каждый из которых "лезет" в PEB и занимается символьным копированием, и далеко не каждый из которых вернет достоверный факт того, что очередной регион есть очередной искомый мной PE-образ."
все верно - вариант тормозной. но я его использую по причине его работы везде - мне win9x тоже важны :(
поэтому приходится жертвовать производительностью.
если только nt, то конечно стоит поискать более производительные варианты.
но копать имхо нужно именно в сторону инкремента/декремена reference count модулей на время работы с ними.
← →
Digitman (2002-09-04 08:12) [14]>paul_shmakov
Благодарю за идею. Буду взвешивать все "за" и "против"
← →
Игорь Шевченко (2002-09-04 09:55) [15]Пример только для NT. Проверялся на WinNT 4.0, WinXP Pro
Часть 1:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, NtPEB;
type
TfMain = class(TForm)
ListView: TListView;
CloseButton: TButton;
procedure FormCreate(Sender: TObject);
procedure CloseButtonClick(Sender: TObject);
private
FLoaderLock : Pointer;
FCurrentPeb : PPEB;
procedure BuildModulesList;
procedure DisplayModule (ModuleEntry : PLDR_DATA_TABLE_ENTRY);
procedure LockLoader();
procedure UnlockLoader();
end;
var
fMain: TfMain;
implementation
uses
NTDll, HSNtUtils;
{$R *.dfm}
procedure TfMain.BuildModulesList;
var
LdrData : PPEB_LDR_DATA;
pModule : PLDR_DATA_TABLE_ENTRY;
pLoadOrderList : PPLIST_ENTRY;
begin
LockLoader();
try
LdrData := FCurrentPEB^.Ldr;
pLoadOrderList := @(LdrData^.InLoadOrderModuleList);
pModule := PLDR_DATA_TABLE_ENTRY(pLoadOrderList^);
while (PPLIST_ENTRY(pModule) <> pLoadOrderList) do begin
DisplayModule(pModule);
pModule := PLDR_DATA_TABLE_ENTRY(pModule^.InLoadOrderLinks.Flink);
end;
finally
UnlockLoader();
end;
end;
procedure TfMain.DisplayModule (ModuleEntry : PLDR_DATA_TABLE_ENTRY);
var
LI : TListItem;
begin
LI := ListView.Items.Add();
LI.Caption := Format("%.8x", [Integer(ModuleEntry^.DllBase)]);
LI.SubItems.Add(Format("%.8x", [ModuleEntry^.SizeOfImage]));
LI.SubItems.Add(HSUnicodeStringToAnsiString(ModuleEntry^.FullDllName));
end;
procedure TfMain.LockLoader();
begin
// if HSCanLockLoader() then
// NTDLL.LdrLockLoaderLock(1, 0, @LoaderLock)
// else
// NTDLL.RtlEnterCriticalSection(CurrentPEB.LoaderLock);
end;
procedure TfMain.UnlockLoader();
begin
// if HSCanLockLoader() then
// NTDLL.LdrUnlockLoaderLock(1, LoaderLock)
// else
// NTDLL.RtlLeaveCriticalSection(CurrentPEB.LoaderLock);
end;
procedure TfMain.FormCreate(Sender: TObject);
begin
FCurrentPEB := PPEB(NTDLL.RtlGetCurrentPEB());
BuildModulesList();
end;
procedure TfMain.CloseButtonClick(Sender: TObject);
begin
Close();
end;
end.
← →
Игорь Шевченко (2002-09-04 09:56) [16]Часть 2:
unit NtPEB;
interface
uses
Windows, NtDll; { для типа Unicode_string }
type
Uint4B = Cardinal;
Uint2B = Word;
UChar = Byte;
Ptr32 = Pointer;
PLIST_ENTRY = ^TLIST_ENTRY;
TLIST_ENTRY = packed record
Flink : PLIST_ENTRY;
Blink : PLIST_ENTRY;
end;
PPLIST_ENTRY = ^PLIST_ENTRY;
TPEB_LDR_DATA = packed record
Length : Uint4B;
Initialized : UChar;
AlignmentBytes : array[1..3] of Byte;
SsHandle : Ptr32;
{ Список элементов TLDR_DATA_TABLE_ENTRY }
InLoadOrderModuleList : PLIST_ENTRY;
InMemoryOrderModuleList : PLIST_ENTRY; { Неизвестный список }
InInitializationOrderModuleList : PLIST_ENTRY; { Неизвестный список }
EntryInProgress : Ptr32;
end;
PPEB_LDR_DATA = ^TPEB_LDR_DATA;
TLDR_DATA_TABLE_ENTRY = packed record
InLoadOrderLinks : TLIST_ENTRY;
InMemoryOrderLinks : TLIST_ENTRY;
InInitializationOrderLinks : TLIST_ENTRY;
DllBase : Ptr32;
EntryPoint : Ptr32;
SizeOfImage : Uint4B;
FullDllName : TUNICODE_STRING;
BaseDllName : TUNICODE_STRING;
Flags : Uint4B;
LoadCount : Uint2B;
TlsIndex : Uint2B;
HashLinks : TLIST_ENTRY;
SectionPointer : Ptr32;
CheckSum : Uint4B;
TimeDateStamp : Uint4B;
LoadedImports : Ptr32;
EntryPointActivationContext : Ptr32; { Может, только в XP }
end;
PLDR_DATA_TABLE_ENTRY = ^TLDR_DATA_TABLE_ENTRY;
{ Текущий каталог }
type
TCURDIR = packed record
DosPath : TUNICODE_STRING;
Handle : Ptr32;
end;
{ User Process Parameters - пользовательские параметры процесса }
type
TRTL_USER_PROCESS_PARAMETERS = packed record
MaximumLength : Uint4B;
Length : Uint4B;
Flags : Uint4B;
DebugFlags : Uint4B;
ConsoleHandle : Ptr32;
ConsoleFlags : Uint4B;
StandardInput : Ptr32;
StandardOutput : Ptr32;
StandardError : Ptr32;
CurrentDirectory : TCURDIR;
DllPath : TUNICODE_STRING;
ImagePathName : TUNICODE_STRING;
CommandLine : TUNICODE_STRING;
Environment : Ptr32;
StartingX : Uint4B;
StartingY : Uint4B;
CountX : Uint4B;
CountY : Uint4B;
CountCharsX : Uint4B;
CountCharsY : Uint4B;
FillAttribute : Uint4B;
WindowFlags : Uint4B;
ShowWindowFlags : Uint4B;
WindowTitle : TUNICODE_STRING;
DesktopInfo : TUNICODE_STRING;
ShellInfo : TUNICODE_STRING;
RuntimeData : TUNICODE_STRING;
// +0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR
end;
PRTL_USER_PROCESS_PARAMETERS = ^TRTL_USER_PROCESS_PARAMETERS;
{ Process Environment Block - блок окружения процесса }
type
TPEB = packed record
InheritedAddressSpace : UChar;
ReadImageFileExecOptions : UChar;
BeingDebugged : UChar;
SpareBool : UChar;
Mutant : Ptr32;
ImageBaseAddress : Ptr32;
Ldr : PPEB_LDR_DATA; { Данные загрузчика }
ProcessParameters : PRTL_USER_PROCESS_PARAMETERS { _RTL_USER_PROCESS_PARAMETERS };
SubSystemData : Ptr32;
ProcessHeap : Ptr32;
FastPebLock : Ptr32; { _RTL_CRITICAL_SECTION }
FastPebLockRoutine : Ptr32;
FastPebUnlockRoutine : Ptr32;
EnvironmentUpdateCount : Uint4B;
KernelCallbackTable : Ptr32;
SystemReserved : Uint4B;
ExecuteOptions : Uint4B; {Pos 0, 2 Bits, SpareBits : Pos 2, 30 Bits }
FreeList : Ptr32; { _PEB_FREE_BLOCK }
TlsExpansionCounter : Uint4B;
TlsBitmap : Ptr32;
TlsBitmapBits : array[0..1] of Uint4B;
ReadOnlySharedMemoryBase : Ptr32;
ReadOnlySharedMemoryHeap : Ptr32;
ReadOnlyStaticServerData : Ptr32;
AnsiCodePageData : Ptr32;
OemCodePageData : Ptr32;
UnicodeCaseTableData : Ptr32;
NumberOfProcessors : Uint4B;
NtGlobalFlag : Uint4B;
CriticalSectionTimeout : TLARGEINTEGER;
HeapSegmentReserve : Uint4B;
HeapSegmentCommit : Uint4B;
HeapDeCommitTotalFreeThreshold : Uint4B;
HeapDeCommitFreeBlockThreshold : Uint4B;
NumberOfHeaps : Uint4B;
MaximumNumberOfHeaps : Uint4B;
ProcessHeaps : Ptr32;
GdiSharedHandleTable : Ptr32;
ProcessStarterHelper : Ptr32;
GdiDCAttributeList : Uint4B;
LoaderLock : Ptr32;
OSMajorVersion : Uint4B;
OSMinorVersion : Uint4B;
OSBuildNumber : Uint2B;
OSCSDVersion : Uint2B;
OSPlatformId : Uint4B;
ImageSubsystem : Uint4B;
ImageSubsystemMajorVersion : Uint4B;
ImageSubsystemMinorVersion : Uint4B;
ImageProcessAffinityMask : Uint4B;
{ Остальные данные опущены }
end;
PPEB = ^TPEB;
implementation
end.
← →
Игорь Шевченко (2002-09-04 09:58) [17]Часть 3:
unit HsNtUtils;
interface
uses
NtDll;
function HSUnicodeStringToAnsiString (usString : TUNICODE_STRING) : AnsiString;
implementation
function HSUnicodeStringToAnsiString (usString : TUNICODE_STRING) : AnsiString;
begin
Result := WideCharLenToString(usString.Buffer,
usString.Length DIV SizeOf(WideChar));
end;
end.
В дополнение:
Закомментрированные части в unit"е main показаны, как идея и не реализованы.
Функция HSCanLockLoader должна проверять, есть ли в NTDLL.DLL фукнции с именами LdrLockLoaderLock и LdrUnlockLoaderLock.
С уважением,
← →
Digitman (2002-09-04 11:13) [18]>paul_shmakov
>Игорь Шевченко
Благодарю за помощь. Все встало на свои места.
P.S.
Проверка показала, что приведенные декларации структур актуальны и для W2k . По кр.мере , в части полей, которые используются механизмом загрузки/выгрузки/блокировки.
← →
Игорь Шевченко (2002-09-04 11:23) [19]Digitman © (04.09.02 11:13)
Я знаю, что в WinXP и в WinNT4 блокировка осуществляется по-разному. В NT через RtlEnterCriticalSection (@PEB^.LoaderLock),
а в WinXP через вызов функции LdrLockLoaderLock.
С уважением,
← →
Digitman (2002-09-04 11:51) [20]>Игорь Шевченко
Не могу, к сож., проверить это - нет под рукой XP.
А ты можешь у себя посмотреть значение поля PEB.LoaderLock в XP ?
Если там таки что-то похожее на хэндл крит.секции, думаю, можно предположить, что LdrLockLoaderLock() просто инкапсулирует функц-ть той же [Rtl]EnterCriticalSection() и в конечном итоге все же использует это поле
← →
paul_shmakov (2002-09-04 13:56) [21]
TPEB
...
FastPebLock : Ptr32; { _RTL_CRITICAL_SECTION }
FastPebLockRoutine : Ptr32;
FastPebUnlockRoutine : Ptr32;
...
интересно, это не то самое?
← →
paul_shmakov (2002-09-04 14:38) [22]у меня (w2k) эти поля указывают на RtlEnterCriticalSection и RtlLeaveCriticalSection, а FastPebLock - критическая секция.
вот программа для определения на других операционках (чтобы руками не проверять):
// locktest.dpr
program locktest;
{$APPTYPE CONSOLE}
uses Windows, SysUtils;
type
PPeb = ^TPeb;
TPeb = packed record
AllocSize: Pointer;
Unknown1: Pointer;
ProcessHinstance: Pointer;
ModuleInfo: Pointer;
ProcessParameters: Pointer;
SubSystemData: Pointer;
ProcessHeap: Pointer;
FastPebLock: Pointer;
FastPebLockRoutine: Pointer;
FastPebUnlockRoutine: Pointer;
end;
procedure PrintPointer(const Text: string; P: Pointer);
begin
WriteLn(Text + " " + IntToHex(Integer(P), 8));
end;
var
Peb: PPeb;
RtlEnterCriticalSection: Pointer;
RtlLeaveCriticalSection: Pointer;
begin
asm
mov eax, fs:[$30]
mov [Peb], eax
end;
RtlEnterCriticalSection := Pointer(GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlEnterCriticalSection"));
RtlLeaveCriticalSection := Pointer(GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlLeaveCriticalSection"));
PrintPointer("Peb.FastPebLockRoutine:", Peb.FastPebLockRoutine);
PrintPointer("RtlEnterCriticalSection:", RtlEnterCriticalSection);
PrintPointer("Peb.FastPebUnlockRoutine:", Peb.FastPebUnlockRoutine);
PrintPointer("RtlLeaveCriticalSection:", RtlLeaveCriticalSection);
end.
← →
paul_shmakov (2002-09-04 14:56) [23]да, еще добавьте к предыдущей программе следующий код для проверки, что Peb.FastPebLock является TTRLCriticalSection;
TPEB
...
ProcessHeap: Pointer;
FastPebLock: PRTLCriticalSection;
FastPebLockRoutine: Pointer;
...
// а это в самый конец
PrintPointer("Peb.FastPebLock.DebugInfo:", Pointer(Peb.FastPebLock.DebugInfo));
PrintPointer("Peb.FastPebLock.LockCount:", Pointer(Peb.FastPebLock.LockCount));
PrintPointer("Peb.FastPebLock.RecursionCount:", Pointer(Peb.FastPebLock.RecursionCount));
PrintPointer("Peb.FastPebLock.OwningThread:", Pointer(Peb.FastPebLock.OwningThread));
PrintPointer("Peb.FastPebLock.LockSemaphore:", Pointer(Peb.FastPebLock.LockSemaphore));
end.
у меня выдает:
Peb.FastPebLockRoutine: 77F81B42
RtlEnterCriticalSection: 77F81B42
Peb.FastPebUnlockRoutine: 77F81B73
RtlLeaveCriticalSection: 77F81B73
Peb.FastPebLock.DebugInfo: 77FCEA80
Peb.FastPebLock.LockCount: FFFFFFFF
Peb.FastPebLock.RecursionCount: 00000000
Peb.FastPebLock.OwningThread: 00000000
Peb.FastPebLock.LockSemaphore: 00000000
из значений полей Peb.FastPebLock видно, что Peb.FastPebLock - это действительно critical section.
поэтому можно попробовать в примере Игоря:
procedure TfMain.LockLoader();
begin
CurrentPEB.FastPebLockRoutine(CurrentPEB.FastPebLock);
end;
procedure TfMain.UnlockLoader();
begin
CurrentPEB.FastPebUnlockRoutine(CurrentPEB.FastPebLock);
end;
← →
Ученик (2002-09-04 15:03) [24]Windows XP
Peb.FastPebLockRoutine: 77F7E21F
RtlEnterCriticalSection: 77F7E21F
Peb.FastPebUnlockRoutine: 77F7E300
RtlLeaveCriticalSection: 77F7E300
Peb.FastPebLock.DebugInfo: 77FC52A0
Peb.FastPebLock.LockCount: FFFFFFFF
Peb.FastPebLock.RecursionCount: 00000000
Peb.FastPebLock.OwningThread: 00000000
Peb.FastPebLock.LockSemaphore: 00000000
← →
Ученик (2002-09-04 15:09) [25]NT 4.0
Peb.FastPebLockRoutine: 77F67500
RtlEnterCriticalSection: 77F67500
Peb.FastPebUnlockRoutine: 77F675D0
RtlLeaveCriticalSection: 77F675D0
Peb.FastPebLock.DebugInfo: 77FA7620
Peb.FastPebLock.LockCount: FFFFFFFF
Peb.FastPebLock.RecursionCount: 00000000
Peb.FastPebLock.OwningThread: 00000000
Peb.FastPebLock.LockSemaphore: 00000000
← →
Игорь Шевченко (2002-09-04 15:22) [26]paul_shmakov © (04.09.02 14:56)
Ученик © (04.09.02 15:09)
Это разные локи. PebLock блокирует доступ к PEB,
а LoaderLock блокирует доступ к PEB^.Ldr.
В разных ОС реализовано по-разному
← →
paul_shmakov (2002-09-04 16:12) [27]2 Игорь Шевченко:
"Это разные локи. PebLock блокирует доступ к PEB,
а LoaderLock блокирует доступ к PEB^.Ldr.
В разных ОС реализовано по-разному"
обидно, если так. а то все очень красиво получается.
а это точно? может все же PebLock блокирует все, включая PEB^.Ldr?
2 Ученик:
спасибо за проверку!
← →
Digitman (2002-09-04 16:19) [28]думаю, что и PEB.LoaderLock - тоже крит.секция
← →
Ученик (2002-09-04 16:22) [29]>paul_shmakov © (04.09.02 16:12)
Не, это не просто так :-)
Нужна помощь, есть идентификатор Thread-а, в принципе есть TEB,
необходимо выяснить откуда этот Thread (не процесс, а модуль -EXE, DLL), киньте название какой-нибудь структуры или функции, дальше, наверно, сам найду.
← →
Игорь Шевченко (2002-09-04 16:38) [30]Ученик © (04.09.02 16:22)
Все модули - это свойство процесса, а не потока. Так что модуль, загруженный одним потоком не должен ничем отличаться от модуля, загруженного другим потоком (IMHO).
Для определения EXE по процессу есть пример в кладовке EnumFunctions - функция HSGetWindowCommandLine - имя EXE"шника, создавшего процесс.
С уважением,
← →
Ученик (2002-09-04 16:51) [31]>>Игорь Шевченко © (04.09.02 16:38)
Мне нужна информация именно о модуле (скорее DLL), так как название EXE я уже получил через информацию о процессе, задача о Hook-ах установленных в системе.
← →
Digitman (2002-09-04 17:11) [32]>Ученик
Для текущего процесса :
- берешь любой адрес из диапазона адресов, занимаемых телом ThreadFunc;
- выполняешь для него FindHInstance() - получаешь хэндл PE-модуля в АП процесса;
- по хэндлу ищешь любым удобным способом (тот же GetModuleFileName) имя файла модуля
← →
Ученик (2002-09-04 19:18) [33]>Digitman © (04.09.02 17:11)
Спасибо, попробую
← →
Игорь Шевченко (2002-09-05 13:07) [34]В дополнение.
В unit"е NtPEB (Игорь Шевченко © (04.09.02 09:56))
в описание структуры TPEB после поля
NtGlobalFlag : Uint4B;
должно быть добавлено поле
Reserved : Uint4B;
← →
Digitman (2002-09-05 13:46) [35]Вот теперь все сходится !)
RtlEnterCriticalSection/RtlLeaveCriticalSection успешно работают и с полем LoaderLock и с полем FastPebLock.
По кр.мере - W2k, NT, XP
← →
Ученик (2002-09-05 17:45) [36]>Digitman © (04.09.02 17:11)
Спасибо, все работает, только хотелось бы избавиться от использования PSAPI (GetModuleFileNameEx), не подскажете на какую структуру мы получаем адрес после FindHInstance ?
← →
Digitman (2002-09-05 18:09) [37]>Ученик
FindhInstance() возвращает хэндл модуля, являющийся по сути базовым линейным адресом начала образа PE-модуля, загруженного в ВАП процесса.
Образ PE-модуля начинается с DOS-заголовка :
PImageDosHeader = ^TImageDosHeader;
{EXTERNALSYM _IMAGE_DOS_HEADER}
_IMAGE_DOS_HEADER = packed record { DOS .EXE header }
e_magic: Word; { Magic number }
e_cblp: Word; { Bytes on last page of file }
e_cp: Word; { Pages in file }
e_crlc: Word; { Relocations }
e_cparhdr: Word; { Size of header in paragraphs }
e_minalloc: Word; { Minimum extra paragraphs needed }
e_maxalloc: Word; { Maximum extra paragraphs needed }
e_ss: Word; { Initial (relative) SS value }
e_sp: Word; { Initial SP value }
e_csum: Word; { Checksum }
e_ip: Word; { Initial IP value }
e_cs: Word; { Initial (relative) CS value }
e_lfarlc: Word; { File address of relocation table }
e_ovno: Word; { Overlay number }
e_res: array [0..3] of Word; { Reserved words }
e_oemid: Word; { OEM identifier (for e_oeminfo) }
e_oeminfo: Word; { OEM information; e_oemid specific}
e_res2: array [0..9] of Word; { Reserved words }
_lfanew: LongInt; { File address of new exe header }
end;
TImageDosHeader = _IMAGE_DOS_HEADER;
{$EXTERNALSYM IMAGE_DOS_HEADER}
IMAGE_DOS_HEADER = _IMAGE_DOS_HEADER;
взято из Windows.pas
← →
Ученик (2002-09-06 08:54) [38]>Digitman © (05.09.02 18:09)
Спасибо, но это к сожалению, не помогло, остановился на GetModuleFileNameEx, другие варианты оказались слишком громоздкими (тоже самое делает GetModuleFileNameEx)
>All
Небольшие добавления (исправления)
_PEB_LDR_DATA = packed record
Length : Cardinal;
Initialized : LongBool;
SsHandle : THandle;
InLoadOrderModuleList : TListEntry;
InMemoryOrderModuleList : TListEntry;
InInitializationOrderModuleList: TListEntry;
end;
TPebLdrData = _PEB_LDR_DATA;
Не знаю как описано в оригинале, но это вроде элементы списка InitializationOrderModuleList
TModuleEntry = packed record
ListEntry : TListEntry;
DllBase : Ptr32;
EntryPoint : Ptr32;
SizeOfImage: Ptr32;
ImageName : TUNICODE_STRING;
end;
PModuleEntry = ^TModuleEntry;
InMemoryOrderModuleList указывает на элементы TLDR_DATA_TABLE_ENTRY
← →
Digitman (2002-09-06 09:09) [39]>Ученик
Я что-то не совсем понял твою задачу.
Еще раз объясни толково - как она пересекается с той, что я описал при инициации ветки ?
← →
Ученик (2002-09-06 09:17) [40]>Digitman © (06.09.02 09:09)
Когда я влез в эту ветку, она честно говоря не пересекалась, потом выяснилось, что они пересекается на реализации GetModuleFileNameEx, там идет сканирование модулей загруженных в процесс и сравнение HInstance с TLDR_DATA_TABLE_ENTRY.DllBase
Страницы: 1 2 вся ветка
Форум: "Система";
Текущий архив: 2002.11.11;
Скачать: [xml.tar.bz2];
Память: 0.6 MB
Время: 0.009 c