Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > получить HINSTANCE процесса


Автор: jhonyxakep 27.9.2011, 13:04
Писал программку, которая перехватывает выполнение Dll функций на себя. Для перехвата требуется HINSTANCE процесса, само собой получить его внутри самой-же программы несложно, а вот как получить HINSTANCE другого приложения? Пробовал использовать GetWindowLong но она вроде возвращает только HINSTANCE окна, так что...

Автор: Snowy 27.9.2011, 14:07
Может я чего-то не так понял, но обычно для перехвата нужен HINSTANCE твоей dll.
Для чего тебе может потребоваться HINSTANCE чужого процесса - не представляю...

Автор: CodeMonkey 27.9.2011, 15:44
Не существует такой вещи как HINSTANCE процесса. У процесса есть ID (PID) и опционально - несколько открытых описателей (Handle).

HINSTANCE - это описатель исполняемого модуля. Коих в одном процессе загружено несколько. Как минимум - .exe и kernel32.

Автор: jhonyxakep 28.9.2011, 02:56
Хмм незнал.. Вот мне надо перехватывать обращение к одной из функций библиотеки BASS. Какой для этого надо HINSTANCE пихать? И где его взять?

Автор: CodeMonkey 28.9.2011, 03:03
Странный вопрос.

"Мне надо повесить картину - какую брать табуретку?"

Какая связь между A и Б? Может она есть, а может и нет. Как вы собираетесь ставить ловушку? И, главное, зачем вообще надо ставить ловушку на BASS?

Автор: jhonyxakep 28.9.2011, 07:22
Находил в тырьнете юнит небольшой... А может и большой, вообщем вот:
Код

unit intercep;

interface
uses windows,dialogs,SysUtils;
type
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                   }
e_lfanew: LongInt;                 { File address of new exe header   }
end;
TImageDosHeader = _IMAGE_DOS_HEADER;
//  {$EXTERNALSYM IMAGE_DOS_HEADER}
IMAGE_DOS_HEADER = _IMAGE_DOS_HEADER;

//***************************************
PImageDataDirectory = ^TImageDataDirectory;
_IMAGE_DATA_DIRECTORY = record
VirtualAddress: DWORD;
Size: DWORD;
end;
//  {$EXTERNALSYM _IMAGE_DATA_DIRECTORY} 
TImageDataDirectory = _IMAGE_DATA_DIRECTORY;
IMAGE_DATA_DIRECTORY = _IMAGE_DATA_DIRECTORY;
//  {$EXTERNALSYM IMAGE_DATA_DIRECTORY}
//*************
PImageOptionalHeader = ^TImageOptionalHeader;
_IMAGE_OPTIONAL_HEADER = packed record
{ Standard fields. }
Magic: Word;
MajorLinkerVersion: Byte;
MinorLinkerVersion: Byte;
SizeOfCode: DWORD;
SizeOfInitializedData: DWORD;
SizeOfUninitializedData: DWORD;
AddressOfEntryPoint: DWORD;
BaseOfCode: DWORD;
BaseOfData: DWORD;
{ NT additional fields. }
ImageBase: DWORD;
SectionAlignment: DWORD;
FileAlignment: DWORD;
MajorOperatingSystemVersion: Word;
MinorOperatingSystemVersion: Word;
MajorImageVersion: Word;
MinorImageVersion: Word;
MajorSubsystemVersion: Word;
MinorSubsystemVersion: Word;
Win32VersionValue: DWORD;
SizeOfImage: DWORD;
SizeOfHeaders: DWORD;
CheckSum: DWORD;
Subsystem: Word;
DllCharacteristics: Word;
SizeOfStackReserve: DWORD;
SizeOfStackCommit: DWORD;
SizeOfHeapReserve: DWORD;
SizeOfHeapCommit: DWORD;
LoaderFlags: DWORD;
NumberOfRvaAndSizes: DWORD;
DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
end;
// {$EXTERNALSYM _IMAGE_OPTIONAL_HEADER}
TImageOptionalHeader = _IMAGE_OPTIONAL_HEADER;
IMAGE_OPTIONAL_HEADER = _IMAGE_OPTIONAL_HEADER;
// {$EXTERNALSYM IMAGE_OPTIONAL_HEADER}


PImageNtHeaders = ^TImageNtHeaders;
_IMAGE_NT_HEADERS = packed record
Signature: DWORD;
FileHeader: TImageFileHeader;
OptionalHeader: TImageOptionalHeader;
end;
// {$EXTERNALSYM _IMAGE_NT_HEADERS}
TImageNtHeaders = _IMAGE_NT_HEADERS;
IMAGE_NT_HEADERS = _IMAGE_NT_HEADERS;
// {$EXTERNALSYM IMAGE_NT_HEADERS}

PImage_import_by_name = ^TImage_import_by_mame;
_IMAGE_IMPORT_BY_NAME=packed record
Hint:Word;
Name:Byte;
end;
TImage_import_by_mame =_IMAGE_IMPORT_BY_NAME;


_u1=packed record
case Integer of
0: (ForwarderString:PByte);
1: (Functionn:PDWORD);
2: (Ordinal: DWORD);
3: (AddressOfData:PImage_import_by_name);
end;
PImageThunkData=^TImageThunkData;
_IMAGE_THUNK_DATA=packed record
u1:_u1;
end;
TImageThunkData=_IMAGE_THUNK_DATA;
IMAGE_THUNK_DATA=_IMAGE_THUNK_DATA;
_temp_charcteristics=record
case Integer of
0:(Characteristics:DWORD); // 0 for terminating null import descriptor
1:(OriginalFirstThunk:PImageThunkData);// RVA to original unbound IAT
end;

PImageImportDescriptor=^TImageImportDescriptor;
_IMAGE_IMPORT_DESCRIPTOR = packed record
t:_temp_charcteristics;
TimeDateStamp:DWord;                  // 0 if not bound, -1 if bound, and real date\time stamp
//     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) 
// O.W. date/time stamp of DLL bound to (Old BIND)

ForwarderChain:DWORD;                 // -1 if no forwarders
Name:DWORD;
FirstThunk:PImageThunkData; 
// RVA to IAT (if bound this IAT has actual addresses)
end; TImageImportDescriptor=_IMAGE_IMPORT_DESCRIPTOR;
IMAGE_IMPORT_DESCRIPTOR=_IMAGE_IMPORT_DESCRIPTOR;
PPointer=^Pointer;
function InterceptDllCall(
hLocalModule:HModule;
c_szDllName:Pchar;
c_szApiName:PChar;
pApiNew:Pointer;
p_pApiOrg:PPointer;
pApiToChange:Pointer):Boolean;
implementation
function MakePtr(base:Dword;Offset:DWORD):Pointer;
begin
Result:=Pointer(Base+Offset);
end;
function InterceptDllCall(
hLocalModule:HModule;
c_szDllName:Pchar;
c_szApiName:PChar;
pApiNew:Pointer;
p_pApiOrg:PPointer;
pApiToChange:Pointer):Boolean;

var pDosHeader:PImageDosHeader;
pNtHeader:PImageNtHeaders;
PImportDesc:PImageImportDescriptor;
dwProtect:DWORD;
dwNewProtect:DWORD;
dwAddressToInterCept:DWORD;
pThunk:PImageThunkData;
begin
pDosHeader:=PImageDosHeader(hLocalModule);
Result:=False;
if (pApiToChange<>nil) then
dwAddressToIntercept:=DWORD(pApiToChange)
else
dwAddressToIntercept:=Dword(
GetProcAddress(GetModuleHandle(c_szDllName),c_szApiName));

if IsBadReadPtr(Pointer(hLocalModule),sizeof(PImageNtHeaders)) then Exit;

if pDosHeader.e_magic<>IMAGE_DOS_SIGNATURE then exit;
pNtHeader:=PImageNtHeaders(MakePtr(DWord(pDOSHeader),DWord(pDOSHeader.e_lfanew)));
if pNTHeader.signature<>IMAGE_NT_SIGNATURE then exit;
pImportDesc:=PImageImportDescriptor(
MakePtr(hLocalModule,
pNtHeader.OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));

if (PImportDesc=PImageImportDescriptor(pNtHeader))  then exit;

while(pImportDesc.Name>0)do
begin
pThunk:=PImageThunkData(MakePtr(DWord(hLocalModule),
Dword(pImportDesc.FirstThunk)));
while(pThunk.u1.Functionn<>nil) do
begin
if DWord(pThunk.u1.Functionn)=dwAddressToIntercept then
begin
if not IsBadWritePtr(Pointer(@pThunk.u1.Functionn),sizeof(DWORD)) then
begin
if (p_pApiOrg<>nil) then
p_pApiOrg^:=Pointer(pThunk.u1.Functionn);
pThunk.u1.Functionn:=pApiNew;
Result:=True;
end
else
begin
if VirtualProtect(Pointer(
        @pThunk.u1.Functionn),sizeof(DWORD),PAGE_EXECUTE_READWRITE,@dwProtect) then
begin
if (p_pApiOrg<>nil) then p_pApiOrg^:=Pointer(pThunk.u1.Functionn);
pThunk.u1.Functionn:=PDWORD(pApiNew);
Result:=True;
dwNewProtect:=dwProtect;
VirtualProtect(Pointer(
        @pThunk.u1.Functionn),sizeof(DWORD),dwNewProtect,@dwProtect);
end;
end;
end;
Inc(PThunk);
end;
Inc(pImportDEsc);
end;
end;

end.


Особо не разбирался что тут. Функция InterceptDllCall позволяет ставить что-то типа хука на это дело.

Вот я и пытался начать хотябы с мессадж бокса 
Код

  InterceptDllCall(GetWindowLong(FindWindow(nil,'Testapp'),GWL_HINSTANCE),'user32.dll','MessageBoxA',Pointer(@MyMessageBox),PPointer(@myProc),nil);


Если передавать первым параметром hInstance своего приложения, то у меня успешно вызывается функция MyMessageBox, иначе вообще глухо.


Цитата(CodeMonkey @  28.9.2011,  03:03 Найти цитируемый пост)
И, главное, зачем вообще надо ставить ловушку на BASS?



Хочу расширить возможности одного приложения.

Автор: bems 28.9.2011, 07:43
Конкретно эта функция хочет HMODULE дллки в твоём процессе.
То есть давай ей результат вызова LoadLibrary/GetModuleHandle

Автор: jhonyxakep 28.9.2011, 09:12
Ээм, но мне надо перехватывать все это дело из другого процесса...

Автор: bems 28.9.2011, 09:37
Эта функция действует сугубо в текущем процессе. Если нужно в чужом, ты можешь инжектить туда длл и вызывать функу уже в контексте чужого процесса

Автор: jhonyxakep 28.9.2011, 10:54
Дауж, не самый приятный путь. Ладно, буду пробовать. Есть ссылочки на РТФМ по этой теме?

Автор: bems 28.9.2011, 11:23
http://forum.vingrad.ru/act-Search/CODE/show/searchid-00ae4f6163b5838e9f30c3562316fd62/search_in-posts/result_type/topics/flag/search/highlite/inject/index.html

Автор: jhonyxakep 28.9.2011, 11:58
Всетаки под ссылками я имел в виду полноценные мануалы  smile  В любом случае спасибо.

Автор: CodeMonkey 28.9.2011, 15:39
function InterceptDllCall(
hLocalModule:HModule; // <- функции в каком модуле хучить. Если exe - то MainInstance или GetModuleHandle(nil). Если это DLL, то GetModuleHandle('MyDll.dll')
c_szDllName:Pchar;  // <- функцию какой DLL хучить
c_szApiName:PChar; // <- какую функцию хучить
pApiNew:Pointer; // <- указатель на перехватчик
p_pApiOrg:PPointer; // <- указатель на процедурный тип - тут вернут указатель на оригинальную функцию
pApiToChange:Pointer) // <- можно ставить nil
:Boolean; //<- True - OK, False - Fail

Обратите внимание, тут не указывается идентификатор процесса, т.е. функция работает в текущем процессе.

Цитата
Ээм, но мне надо перехватывать все это дело из другого процесса... 


http://www.transl-gunsmoker.ru/2009/08/blog-post_04.html

Цитата
под ссылками я имел в виду полноценные мануалы


http://wm-help.net/books-online/book/59464/59464-16.html#h22.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)