Перехват Api-функций

Тема в разделе "WASM.WIN32", создана пользователем Coffein, 2 май 2007.

  1. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    Всех приветствую! Поставил себе задачу, реализовать механизм перехвата функций для работы с файлами(копирование, создание, удаление и др.). Для этого накидал следующий код:

    Код (Text):
    1. library Hook;
    2.  
    3. uses
    4.   Windows,
    5.   advApiHook;
    6.  
    7. {$R *.res}
    8.  
    9. const
    10.   MutexName='__API_HOOK';
    11.  
    12. var
    13. SH:HHOOK = 0;
    14.  
    15.   CopyFileNextHook: function (lpExistingFileName, lpNewFileName: PChar; bFailIfExists: BOOL): BOOL; stdcall;
    16.  
    17. //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    18.  
    19. function CopyFileHookProc(lpExistingFileName, lpNewFileName: PChar; bFailIfExists: BOOL): BOOL; stdcall;
    20. begin
    21.   MessageBox(0, 'Функция: CopyFile', 'Позволить ?', MB_YESNO or MB_ICONQUESTION);
    22. end;
    23.  
    24. function MsgProc(code:DWORD;wParam,lparam:DWORD):DWORD;stdcall;
    25. begin
    26.   CallNextHookEx(SH,code,wParam,lparam);
    27. end;
    28.  
    29. procedure SetWindowsHook(e:Boolean); stdcall;
    30. var
    31.   M:THandle;
    32. begin
    33.   if e then
    34.    begin
    35.     m:=CreateMutex(0,false,MutexName);
    36.     if m=0 then exit;
    37.     SH:=SetWindowsHookEx(WH_GETMESSAGE,@MsgProc,HInstance,0);
    38.    end
    39.        else
    40.     UnhookWindowsHookEx(sh);
    41. end;
    42.  
    43. procedure HandleEvents(reason: integer);
    44. begin
    45.   case reason of
    46.     DLL_PROCESS_ATTACH:
    47.       begin
    48.         SetWindowsHook(true);
    49.         HookProc('kernel32.dll', 'CopyFileW', @CopyFileHookProc, @CopyFileNextHook);
    50.       end;
    51.     DLL_PROCESS_DETACH:
    52.       begin
    53.         SetWindowsHook(false);  
    54.         UnhookCode(@CopyFileNextHook);
    55.       end;
    56.   end;
    57. end;
    58.  
    59.    //     HandleEvents(DLL_PROCESS_DETACH);
    60.  
    61. begin
    62.   DllProc := @HandleEvents;
    63.   MessageBox(0, 'Запускаем дллку', 'Позволить ?', MB_YESNO or MB_ICONQUESTION);
    64.   HandleEvents(DLL_PROCESS_ATTACH);
    65. ///  CopyFile('C:\test.txt','C:\test1.txt',true);
    66. end.
    67. end.
    Все работает нормально, перехватывает функции, да вот не задача, не перехватываются функции в самой винде, тоесть в explorer'е. Может Винда пользуетя другими функциями или еще есть какие ньюансы. Помогите пожалуста советом или примером.

    P.S. Перехватывал функцию SHFileOperation, ни каких реакций.
     
  2. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    CopyFileA? Хук то вообще устанавливается?

    NtCreateFile,NtWriteFile,NtDeleteFile,NtSetInformationFile в помощь. Хотя несколько геморройно имхо
     
  3. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    Устанавливается. Можешь дать ссылку, где об этих функциях можно почитать по подробней?
     
  4. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    В Google не смотрел?. А вообще, читай Нэббета.
     
  5. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    Спасибо за совет, попробовал в Google. Работает.
    Я извеняюсь, а ссылчка на онову книжку в электроном варианте не подскажешь? А то Google не показывает. ;)
     
  6. lamer2k

    lamer2k New Member

    Публикаций:
    0
    Регистрация:
    14 май 2006
    Сообщения:
    88
    В винде винапи юзермодные нужно перехватывать юникодовские(W), так как "A" является переходником на W и перехватывая CreteFileW ты автоматом перехватишь CreateFileA, кстати заметил, что не для всех API это так...
    Подозреваю что в эксплорере юзаются варинат именно CreateFileW, но проверять лениво :)
     
  7. Guest

    Guest Guest

    Публикаций:
    0
    Да, бывает и наоборот, а иногда и независимо.
     
  8. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    im1111
    лучше хукать обе.
    а есть и еще один вариант - и А и В переходники на внутреннюю функу
     
  9. lamer2k

    lamer2k New Member

    Публикаций:
    0
    Регистрация:
    14 май 2006
    Сообщения:
    88
    Чтобы не быть голословным, примерчик из kernel32.dll функция CreateFileA

    Код (Text):
    1. .text:7C801A24 ; HANDLE __stdcall CreateFileA(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
    2. .text:7C801A24                 public CreateFileA
    3. .text:7C801A24 CreateFileA     proc near               ; CODE XREF: OpenFile+10Dp
    4. .text:7C801A24                                         ; _lcreat+25p ...
    5. .text:7C801A24
    6. .text:7C801A24 lpFileName      = dword ptr  8
    7. .text:7C801A24 dwDesiredAccess = dword ptr  0Ch
    8. .text:7C801A24 dwShareMode     = dword ptr  10h
    9. .text:7C801A24 lpSecurityAttributes= dword ptr  14h
    10. .text:7C801A24 dwCreationDisposition= dword ptr  18h
    11. .text:7C801A24 dwFlagsAndAttributes= dword ptr  1Ch
    12. .text:7C801A24 hTemplateFile   = dword ptr  20h
    13. .text:7C801A24
    14. .text:7C801A24                 mov     edi, edi
    15. .text:7C801A26                 push    ebp
    16. .text:7C801A27                 mov     ebp, esp
    17. .text:7C801A29                 push    [ebp+lpFileName]
    18. .text:7C801A2C                 call    sub_7C80E2A4
    19. .text:7C801A31                 test    eax, eax
    20. .text:7C801A33                 jz      short loc_7C801A53
    21. .text:7C801A35                 push    [ebp+hTemplateFile] ; hTemplateFile
    22. .text:7C801A38                 push    [ebp+dwFlagsAndAttributes] ; dwFlagsAndAttributes
    23. .text:7C801A3B                 push    [ebp+dwCreationDisposition] ; dwCreationDisposition
    24. .text:7C801A3E                 push    [ebp+lpSecurityAttributes] ; lpSecurityAttributes
    25. .text:7C801A41                 push    [ebp+dwShareMode] ; dwShareMode
    26. .text:7C801A44                 push    [ebp+dwDesiredAccess] ; dwDesiredAccess
    27. .text:7C801A47                 push    dword ptr [eax+4] ; lpFileName
    28. .text:7C801A4A             call    CreateFileW ; Вот тут прыжок на нащу юникод функцию
    29. .text:7C801A4F
    30. .text:7C801A4F loc_7C801A4F:                           ; CODE XREF: CreateFileA+32j
    31. .text:7C801A4F                 pop     ebp
    32. .text:7C801A50                 retn    1Ch
    33. .text:7C801A53 ; ---------------------------------------------------------------------------
    34. .text:7C801A53
    35. .text:7C801A53 loc_7C801A53:                           ; CODE XREF: CreateFileA+Fj
    36. .text:7C801A53                 or      eax, 0FFFFFFFFh
    37. .text:7C801A56                 jmp     short loc_7C801A4F
    38. .text:7C801A56 CreateFileA     endp
    P.S глянул у себя exolrer на XP S2 он использует только юникод вызовы, в том числе обращается к файлам именно через CreateFileW

    Собственно развернутый ответ, на поставленный вопрос :)
     
  10. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    lamer2k, на сколько я знаю последние буквы A и W в конце Апи-функции означают в каком контексте рассматривать парамметры передаваемые ей, как данные типа AnsiString или WideString, более ни какой зависимости не замечал. Но факт, остается фактом в винде, то бишь в эксплорере они не перехватываются.
     
  11. lamer2k

    lamer2k New Member

    Публикаций:
    0
    Регистрация:
    14 май 2006
    Сообщения:
    88
    Епта :)

    у нас есть функция

    Код (Text):
    1. BOOL HaveBrainW(UNICODE , DWORD, BOOL)
    2. {
    3. ...
    4. тут
    5. много кода
    6. ...
    7. return XXX
    8. }
    9.  
    10. BOOL HaveBrainA(ANSI, DWORD, BOOL)
    11. {
    12.  тут производится перекодировка в юникод строк энсии
    13.  ANSI->UNICODE
    14.  //  и вызов функции юникодной
    15.  return HaveBrainW(UNICODE, DWORD, BOOL)
    16. }
    ты перехватываешь HaveBrainA, а не HaveBrainW и те программы котрые обращаются на прямую к HaveBrainW обходят твой хук.
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    поэтому лучше хукать обе
     
  13. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    Не понял о чем это lamer2k, но я узнал что надо перехватывать функции NtXXX. Может кто знает где о таких почитать?
     
  14. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    И еще может знает кто где можно достать книжку Гари Нэббета?
     
  15. Freeman

    Freeman New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2005
    Сообщения:
    1.385
    Адрес:
    Ukraine
    дык А обычно переходник на W
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    FreeManCPM
    не всегда. например,
    CreateProcessA -> CreateProcessInternalA
    CreateProcessW -> CreateProcessInternalW
    а дальше все уходит куда-то в неэкспортируемые функции kernel32. так что тут A не переходник для W.
    аналогичная ситуация с MessageBox и некоторыми другими
     
  17. lamer2k

    lamer2k New Member

    Публикаций:
    0
    Регистрация:
    14 май 2006
    Сообщения:
    88
    Лучше посмотреть код в диасме и точно узнать, что хукать, а ТС матчасть учить, а потом сюда, задавать вопросы ИМХО.
     
  18. Coffein

    Coffein New Member

    Публикаций:
    0
    Регистрация:
    2 май 2007
    Сообщения:
    11
    А я скажу что хукать, Windows XP пользуется функциями NtCreateFile, NtOpenFile и т.д.

    lamer2k, не понял кому это ты сказал, но помойму форум это то место где делятся своим опытом на задаваемые вопросы. А если опыта нет то и поверхностно отвечать не надо!
     
  19. tylerdurden

    tylerdurden New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    322
    не всегда. например,
    CreateProcessA -> CreateProcessInternalA
    CreateProcessW -> CreateProcessInternalW
    Иногда вообще наоборот, хотя сейчас ен вспомню имя той АПИ, но как-то в отладчике увидел (в смысле W -> A)
     
  20. Koshak

    Koshak New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2006
    Сообщения:
    31
    Адрес:
    Russia
    Coffein, насколько я понимаю цель стоит просто перехватить все обращения к файловой системе из 3го кольца. Как-то тоже немного страдал этим, могу поделиться измышлениями:

    1. Все CreateFile рано или поздно упрутся в NtCreateFile, ОpenFile в NtOpenFile, CreateFileMapping в NtOpenSection, хотя перед CreateFileMapping всё равно вызывается NtCreateFile или NtOpenFile. Т.е. достаточно перехватить NtCreateFile и NtOpenFile.

    2. Если мы хотим устанавливать свои обработчики NtCreateFile и NtOpenFile, то располагаться они должны в адресном пространстве контролируемого процесса.

    3. Для того, чтобы контролировать доступ к файлу мы должны ВСЕ процессы в системе снабдить обработчиками NtCreateFile и NtOpenFile, т.е. мы должны встроить во все существующие процессы механизм внедрения вышеуказанных обработчиков во ВСЕ порождаемые процессы. При создании процесса ОС выполняет выделение памяти под внутренние структуры процесса, его сегмент кода и данных, а также формирует главный поток процесса в состоянии SUSPENSED. Для детектирования порождения дочернего процесса будем пользоваться функцией NtResumeThread, которую родительский процесс вызывает для запуска главного потока дочернего процесса.

    Условимся в программе использовать только функции экспортируемые из ntdll.dll, т.к. другие библиотеки на момент внедрения в процесс обработчиков NtCreateFile и NtOpenFile могут быть не загружены. Да и вообще, приложение может использовать только функции ntdll (ну ещё kernel.dll, но не факт, хотя функции из kernel.dll и используются самим загрузчиком Windows, и, по логике вещей, если для загрузки приложения используется стандартный загрузчик Windows, то kernel.dll должна быть обязательно спроецирована в память процесса).

    Всё вышеизложенное реализовано в маленькой программке со следующим алгоритмом:

    1. Получаем список адресов всех используемых функций программы. Т.к. будут использоваться функции только из ntdll, то можно смело предположить, что во ВСЕХ приложениях адреса этих функций будут одними и теми же. Запихиваем эти адреса в структуру, которую будем внедрять во все процессы. Обработчики NtCreateFile и NtOpenFile внедрённые в процессы будут пользоваться для вызова системных функций адресами, сохранёнными в этой структуре.

    2. Получаем список ВСЕХ доступных процессов в системе. Это будут только пользовательские процессы. Если необходимо контролировать обращение к NtCreateFile и NtOpenFile из системных процессов, то необходимо поднять себе привелегии до уровня "SeDebugPrivilege".

    3. Читаем конфигурационный файл, в котором содержится список файлов, обращение к которым отследить надо. Считаем CRC для полного имени каждого файла - именно по СRC строки пути к файлу и будем определять надо или не надо отказать в доступе к файлу. Полученный результат - тоже в эту структуру.

    4. Для каждого процесса из полученных на шаге (1) выполняем:
    4.1 Открываем его (NtOpenProcess) с атрибутами PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE
    4.2 Выделям память под структуру, содержащуюю адреса функций и список отслеживаемых файлов.
    4.3 Выделям память под функцию расчёта алгоритма CRC (NtAllocateVirtualMemory с атрибутом PAGE_READWRITE)
    4.4 Записываем в эту память тело функции расчёта CRC (NtWriteVirtualMemory).
    4.5 Останавливаем все потоки процесса (т.к. в процессе внедрения какойто из потоков может попытаться вызвать NtCreateFile или NtOpenFile, что с большой долей вероятности приведёт к "абнормал терминэйшн").
    4.6 Выделям память и записываем в процесс процедуры обработки NtCreateFile, NtOpenFile и NtResumeThread. Здесь необходимо обратить внимание на то, что функции обработчиков (если только они не написаны на чистом ASM должны быть объявлены со спецификатором __declspec(naked), чтобы предотвратить запихивание в тело функции стандартного пролога и эпилога).
    4.7 После записи в процесс необходимо в каждую функцию-обработчик (NtCreateFile, NtOpenFile и NtResumeThread) внести адрес структуры с адресами функций и списком проверяемых файлов, размещённой в целевом процессе. Возможно не самое элегантное решение, но другого я не нашёл.
    4.8 Стартуем все остановленные потоки процесса.
    4.9 Закрываем процесс.

    Если мы всё сделали правильно, то мы получаем все процессы (кроме системных), с установленными обработчиками NtCreateFile, NtOpenFile и NtResumeThread. При порождении других процессов (например создании процесса FAR из процесса Explorer) во вновь порождаемые процессы будут автоматически внедряться вышерассмотренные обработчики, и ни один пользовательский процесс не сможет открыть какой бы то ни было файл в обход наших обработчиков NtCreateFile и NtOpenFile.

    Для упрощения отладки рекомендую сначала заражать свой процесс и ставить точки останова NtCreateFile, NtOpenFile в ntdll.

    Вот полезные ссылки:

    http://www.wasm.ru/article.php?article=apihook_1
    http://www.wasm.ru/article.php?article=apihook_3

    Как приаттачить исходники к посту я не догадался, поэтому если захочешь их поиметь - напиши почтовый адрес - вышлю.
    Для начала рекомендую ознакомиться с прилагаемыми статьями Ms-rem'а