Написал dll которая хуками внедряется во все GUI процессы. Делаю подмену в таблице импорта адресов перехватываемых функций. Все работает - получается и установить и снять хук. Но, хук не срабатывает например в программах запакованных UPX. В этом случае мне кажеться нужно перехватывать GetProcAdress и подсовывать нужные адреса. Но собственно вопрос: как снять такой хук? или придется держать dll в памяти процесса до тех пор пока он не закроется?
Так ведь вроде всезде пишут что именять сами функции жутко ненадежно и т.п. Если например приложении многопоточное. Да и замедляет работу такой перехват. А перехватывать мне нужно во всей системе (скрытие файлов под win9x)
Где пишут? Я не предлагаю каждый раз восстанавливать оригинальные байты, а спереть несколько команд. Ой-ой, сколько функциё перехватываем. Я пробовал перехватывать вообще всё что кем-либо экспортируется одновременно, и то работало. Хотя и притормаживало. P.S. Может я что-то не знаю т.к. под 9х только в игрушки играл.
Да это нужно делать. Могу дать длл на делфе, которая перехватывает подключение новых модулей,GetProccessAdr и др. Проблемы также могуть возникать с программами, написаными на делфи (и не только). Так там используется несолько секций импорта, а функция правки импорта из книги Джеффри Рихтера(которая чаще сего приводится в примерах)патчит только первую секцию. В моём примере это исправлено. Также нужно учитывать, что если процесс успел сохранить адреса настоящих функций до перехвата, то он может вызывать настоящие функции - это основная проблема перехвата методом правки таблиц импорта.
Раскопал я тот код. Тут установка и снятие, перехват функции RegisterHotKey. Думаю разберёшься.(пьяные маты в коментах вырезаны) Код (Text): unit Unit1; interface uses Windows,TlHelp32; var hSnapShot: THandle; me32: MODULEENTRY32; adr_RegisterHotKey:pointer; adr_LoadLibraryA:pointer; adr_LoadLibraryW:pointer; adr_LoadLibraryExA:pointer; adr_LoadLibraryExW:pointer; adr_FreeLibrary:pointer; adr_FreeLibraryAndExitThread:pointer; adr_GetProcAddress:pointer; f:TextFile; procedure ReplaceAllFuncInModule(Instance:HMODULE;Unhook:Boolean); function MyRegisterHotKey(hWnd:LongWord;id:integer;fsModifiers:Cardinal;vk:Cardinal):LongBool;stdcall; procedure MyFreeLibraryAndExitThread(hLibModule:Cardinal;dwExitCode:Cardinal);stdcall; function MyGetProcAddress(hModule:Cardinal;lpProcName:PAnsiChar):pointer;stdcall; function MyFreeLibrary(hLibModule:Cardinal):LongBool;stdcall; function MyLoadLibraryExW(lpLibFilename:PWideChar;hFile:Cardinal;dwFlags:Cardinal):Cardinal;stdcall; function MyLoadLibraryExA(lpLibFilename:PAnsiChar;hFile:Cardinal;dwFlags:Cardinal):Cardinal;stdcall; function MyLoadLibraryW(lpLibFilename:PWideChar):Cardinal;stdcall; function MyLoadLibraryA(lpLibFilename:PAnsiChar):Cardinal;stdcall; function ImageDirectoryEntryToData(Base: Pointer; MappedAsImage: ByteBool;DirectoryEntry: Word; var Size: ULONG): Pointer; stdcall; external 'ImageHlp.dll'; implementation //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// function StrIComp(const Str1, Str2: PChar): Integer; assembler; asm PUSH EDI PUSH ESI MOV EDI,EDX MOV ESI,EAX MOV ECX,0FFFFFFFFH XOR EAX,EAX REPNE SCASB NOT ECX MOV EDI,EDX XOR EDX,EDX @@1: REPE CMPSB JE @@4 MOV AL,[ESI-1] CMP AL,'a' JB @@2 CMP AL,'z' JA @@2 SUB AL,20H @@2: MOV DL,[EDI-1] CMP DL,'a' JB @@3 CMP DL,'z' JA @@3 SUB DL,20H @@3: SUB EAX,EDX JE @@1 @@4: POP ESI POP EDI end; function ReplaceImportEntries(Instance:HMODULE;ModuleName:PChar;OldProc,NewProc:Pointer):Integer; type TIMAGE_IMPORT_DESCRIPTOR=record Union:DWORD; TimeDateStamp:DWORD; ForwarderChain:DWORD; Name:DWORD; FirstThunk:DWORD; end; var Size:DWORD; ppfn:PPointer; ImportDesc:^TIMAGE_IMPORT_DESCRIPTOR; begin Result:=0; if (OldProc=nil)or(Instance=0) then Exit; ImportDesc:=ImageDirectoryEntryToData(Pointer(Instance),True,IMAGE_DIRECTORY_ENTRY_IMPORT,Size); if ImportDesc=nil then Exit; while ImportDesc.Name<>0 do begin if (ModuleName=nil)or(StrIComp(ModuleName,PChar(Instance+ImportDesc.Name))=0) then begin ppfn:=Pointer(Instance+ImportDesc.FirstThunk); while ppfn^<>nil do begin if (ppfn^=OldProc)and WriteProcessMemory(GetCurrentProcess,ppfn,@NewProc,SizeOf(NewProc),Size)and(Size=SizeOf(NewProc)) then Inc(Result); Inc(ppfn); end; end; Inc(ImportDesc); end; end; procedure ReplaceAllFuncInModule(Instance:HMODULE;Unhook:Boolean); begin if not Unhook then begin ReplaceImportEntries(Instance,'user32.dll',adr_RegisterHotKey,@MyRegisterHotKey); ReplaceImportEntries(Instance,'kernel32.dll',adr_GetProcAddress,@MyGetProcAddress); ReplaceImportEntries(Instance,'kernel32.dll',adr_FreeLibraryAndExitThread,@MyFreeLibraryAndExitThread); ReplaceImportEntries(Instance,'kernel32.dll',adr_FreeLibrary,@MyFreeLibrary); ReplaceImportEntries(Instance,'kernel32.dll',adr_LoadLibraryExW,@MyLoadLibraryExW); ReplaceImportEntries(Instance,'kernel32.dll',adr_LoadLibraryExA,@MyLoadLibraryExA); ReplaceImportEntries(Instance,'kernel32.dll',adr_LoadLibraryW,@MyLoadLibraryW); ReplaceImportEntries(Instance,'kernel32.dll',adr_LoadLibraryA,@MyLoadLibraryA); end else begin ReplaceImportEntries(Instance,'user32.dll',@MyRegisterHotKey,adr_RegisterHotKey); ReplaceImportEntries(Instance,'kernel32.dll',@MyGetProcAddress,adr_GetProcAddress); ReplaceImportEntries(Instance,'kernel32.dll',@MyFreeLibraryAndExitThread,adr_FreeLibraryAndExitThread); ReplaceImportEntries(Instance,'kernel32.dll',@MyFreeLibrary,adr_FreeLibrary); ReplaceImportEntries(Instance,'kernel32.dll',@MyLoadLibraryExW,adr_LoadLibraryExW); ReplaceImportEntries(Instance,'kernel32.dll',@MyLoadLibraryExA,adr_LoadLibraryExA); ReplaceImportEntries(Instance,'kernel32.dll',@MyLoadLibraryW,adr_LoadLibraryW); ReplaceImportEntries(Instance,'kernel32.dll',@MyLoadLibraryA,adr_LoadLibraryA); end; end; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// function MyLoadLibraryA(lpLibFilename:PAnsiChar):Cardinal;stdcall; var RealLoadLibraryA:function(lpLibFilename:PAnsiChar):Cardinal;stdcall; begin @RealLoadLibraryA:=Adr_LoadLibraryA; result:=RealLoadLibraryA(lpLibFilename); if result<>0 then ReplaceAllFuncInModule(result,false); end; function MyLoadLibraryW(lpLibFilename:PWideChar):Cardinal;stdcall; var RealLoadLibraryW:function(lpLibFilename:PWideChar):Cardinal;stdcall; begin @RealLoadLibraryW:=Adr_LoadLibraryW; result:=RealLoadLibraryW(lpLibFilename); if result<>0 then ReplaceAllFuncInModule(result,false); end; function MyLoadLibraryExA(lpLibFilename:PAnsiChar;hFile:Cardinal;dwFlags:Cardinal):Cardinal;stdcall; var RealLoadLibraryExA:function(lpLibFilename:PAnsiChar;hFile:Cardinal;dwFlags:Cardinal):Cardinal;stdcall; begin @RealLoadLibraryExA:=Adr_LoadLibraryExA; result:=RealLoadLibraryExA(lpLibFilename,hFile,dwFlags); if result<>0 then ReplaceAllFuncInModule(result,false); end; function MyLoadLibraryExW(lpLibFilename:PWideChar;hFile:Cardinal;dwFlags:Cardinal):Cardinal;stdcall; var RealLoadLibraryExW:function(lpLibFilename:PWideChar;hFile:Cardinal;dwFlags:Cardinal):Cardinal;stdcall; begin @RealLoadLibraryExW:=Adr_LoadLibraryExW; result:=RealLoadLibraryExW(lpLibFilename,hFile,dwFlags); if result<>0 then ReplaceAllFuncInModule(result,false); end; function MyFreeLibrary(hLibModule:Cardinal):LongBool;stdcall; var RealFreeLibrary:function(hLibModule:Cardinal):LongBool;stdcall; begin @RealFreeLibrary:=adr_FreeLibrary; if hLibModule<>HInstance then begin ReplaceAllFuncInModule(hLibModule,true); result:=RealFreeLibrary(hLibModule); end else result:=false; end; procedure MyFreeLibraryAndExitThread(hLibModule:Cardinal;dwExitCode:Cardinal);stdcall; var RealFreeLibraryAndExitThread:procedure(hLibModule:Cardinal;dwExitCode:Cardinal);stdcall; begin @RealFreeLibraryAndExitThread:=adr_FreeLibraryAndExitThread; if hLibModule<>HInstance then begin ReplaceAllFuncInModule(hLibModule,true); RealFreeLibraryAndExitThread(hLibModule,dwExitCode); end else ExitThread(dwExitCode); end; function MyGetProcAddress(hModule:Cardinal;lpProcName:PAnsiChar):pointer;stdcall; var RealGetProcAddress:function(hModule:Cardinal;lpProcName:PAnsiChar):pointer;stdcall; begin @RealGetProcAddress:=adr_GetProcAddress; if hModule=GetModuleHandle('user32.dll')then begin if lpProcName='RegisterHotKey' then begin result:=@MyRegisterHotKey; exit; end; end; if hModule=GetModuleHandle('kernel32.dll')then begin if lpProcName='LoadLibraryA' then begin result:=@MyLoadLibraryA; exit; end; if lpProcName='LoadLibraryW' then begin result:=@MyLoadLibraryW; exit; end; if lpProcName='LoadLibraryExA' then begin result:=@MyLoadLibraryExA; exit; end; if lpProcName='LoadLibraryExW' then begin result:=@MyLoadLibraryExW; exit; end; if lpProcName='FreeLibrary' then begin result:=@MyFreeLibrary; exit; end; if lpProcName='FreeLibraryAndExitThread' then begin result:=@MyFreeLibraryAndExitThread; exit; end; if lpProcName='GetProcAddress' then begin result:=@MyGetProcAddress; exit; end; end; result:=RealGetProcAddress(hModule,lpProcName); end; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// function MyRegisterHotKey(hWnd:LongWord;id:integer;fsModifiers:Cardinal;vk:Cardinal):LongBool;stdcall; var RealRegisterHotKey:function(hWnd:LongWord;id:integer;fsModifiers:Cardinal;vk:Cardinal):LongBool;stdcall; begin @RealRegisterHotKey:=adr_RegisterHotKey; result:=RealRegisterHotKey(hWnd,id,fsModifiers,vk); end; //////////////////////////////////////////////////////////////////////////////// initialization adr_SetSystemCursor:=GetProcAddress(GetModuleHandle('user32.dll'),'SetSystemCursor'); adr_SetCursor:=GetProcAddress(GetModuleHandle('user32.dll'),'SetCursor'); adr_RegisterHotKey:=GetProcAddress(GetModuleHandle('user32.dll'),'RegisterHotKey'); adr_GetProcAddress:=GetProcAddress(GetModuleHandle('kernel32.dll'),'GetProcAddress'); adr_FreeLibraryAndExitThread:=GetProcAddress(GetModuleHandle('kernel32.dll'),'FreeLibraryAndExitThread'); adr_FreeLibrary:=GetProcAddress(GetModuleHandle('kernel32.dll'),'FreeLibrary'); adr_LoadLibraryExW:=GetProcAddress(GetModuleHandle('kernel32.dll'),'LoadLibraryExW'); adr_LoadLibraryExA:=GetProcAddress(GetModuleHandle('kernel32.dll'),'LoadLibraryExA'); adr_LoadLibraryW:=GetProcAddress(GetModuleHandle('kernel32.dll'),'LoadLibraryW'); adr_LoadLibraryA:=GetProcAddress(GetModuleHandle('kernel32.dll'),'LoadLibraryA'); hSnapShot:=CreateToolHelp32SnapShot(TH32CS_SNAPMODULE, GetCurrentProcessId); if not(hSnapshot=INVALID_HANDLE_VALUE) then begin try ZeroMemory(@me32,sizeof(MODULEENTRY32)); me32.dwSize:= sizeof(MODULEENTRY32); Module32First(hSnapShot, me32); repeat ReplaceAllFuncInModule(me32.hModule,false); until not Module32Next(hSnapShot, me32); finally CloseHandle(hSnapShot); end; end; finalization hSnapShot:=CreateToolHelp32SnapShot(TH32CS_SNAPMODULE, GetCurrentProcessId); if not(hSnapshot=INVALID_HANDLE_VALUE) then begin try ZeroMemory(@me32,sizeof(MODULEENTRY32)); me32.dwSize:= sizeof(MODULEENTRY32); Module32First(hSnapShot, me32); repeat ReplaceAllFuncInModule(me32.hModule,true); until not Module32Next(hSnapShot, me32); finally CloseHandle(hSnapShot); end; end; end. А ну да забыл сказать зачем я всё это в юнит запихнул. - У меня были проблемы с DllProc и код, выполняющийся при выгрузке длл я решил написать в finalization юнита. Этот юнит нужно просто подключить к пустой дллке.
спасибо всем, буду разбираться 2 asd В Рихтере написано что такой способ не будет работать в win9x: В Windows 98 основные системные DLL (KerneI32, AdvAPI32, User32 и GDI32) защищены так, что приложение не может что-либо изменить на их страницах кода. Это ограничение можно обойти, только написав специальный драйвер виртуального устройства (VxD).
А кто действительно посоветует как перехватывать функции в программах пожатые UPX'ом ? Уже все избил, не могу найти причины... Во всех программах нормально работает, в тех же, перехватить получается только LoadLibrary и GetProcAddress, ессно из за чего, потому что UPX в своих бинарниках ничего другого не оставляет
Мдя, оказывается достаточно в приостановленом режиме загрузить программу, перехватывать хотя бы LoadLibrary и все ок. Все работает... А с хуками тогда как быть ? я имею ввиду когда внедряем длл при помощи SetHook...
Чё-то я не понял, а что меняется то? Ну есть Dll которая совершает перехват, ну и внедряй её как хочешь. Хоть через SetWindowsHook, хоть через CreateRemoteThread, хоть через ключ реестра или какие-то ещё извраты.
Хмм, ( смайлик чешущий репу ) или я не правильно говорил или меня не правильно понимают ... по порядку если то 1 Запускаю лоудером программу в CREATE_SUSPENDED 2 Заражаю ее длл 3 Длл делает грязные дела 4 Отпускаю процесс Иначе не получается против UPX Может тебе показалось, что я потоки в процессе приостанавливаю ?