Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.11.11;
Скачать: CL | DM;

Вниз

Сканирование списков модулей, загруженных в АП тек.процесса   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.62 MB
Время: 0.022 c
1-33943
Dekanovich
2002-10-31 20:24
2002.11.11
Сериализация?


3-33889
AM
2002-10-22 13:43
2002.11.11
Как заставить НД не обманывать?


14-34251
Malder
2002-10-20 23:18
2002.11.11
Как я понимаю, UBPFD накрылась ?


1-34046
ton2
2002-10-30 18:29
2002.11.11
Помогите с ProcessMessagees!


14-34182
pomka
2002-10-21 17:43
2002.11.11
помогите!!!!!!HELP ME, PLIS!!!