Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 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.01 c
3-33861
comp
2002-10-21 13:22
2002.11.11
Порядковый номер


1-34019
MCFire
2002-11-02 16:17
2002.11.11
Как узнать создана ли форма?


3-33895
Shrek
2002-10-22 18:55
2002.11.11
AutoCalc


1-34090
vixic
2002-10-31 10:41
2002.11.11
Определение типа объекта!


1-34002
Anar
2002-10-30 16:31
2002.11.11
Скрыть заголовок формы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский