Установка хуков в JAVA.EXE

Тема в разделе "WASM.WIN32", создана пользователем ntdrivers, 17 фев 2011.

  1. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Загружаю в процесс ява-машины свою DLL, патчу образ kernel32.dll и делаю классический сплайсинг: в тела функций CreateFileW, ReadFile, WriteFile, CloseHandle внедряю джампы на функции из DLL, а также сохраняю модифицированный код ("трамплины"). У меня нет задачи определить с какими аргументами вызваны перехваченные функции, нужно только отследить факт их вызова, поэтому аргументы оставляю в стеке, отправляю оповещение о вызове (делаю OutputDebugString("CreateFile\n")) и делаю jmp на соответствующий трамплин. По шагам:
    1. Процесс вызывает одну из перехваченных функций, например CreateFileW;
    2. Через внедренный в kernel32.dll jmp управление попадает на функцию (экспортируется моей dll), которая вызывает OutputDebugStringA;
    3. Моя функция делает jmp на соответствующий "трамплин";
    4. "Трамплин" передает управление системе.

    Все это под XP SP2, пишу на С++, функции из пункта 2 выглядят так:
    extern "C" __declspec(naked,dllexport) void CreateFileStub()
    {
    OutputDebugStringA("CreateFile called\n");
    __asm { jmp CreateFileTrampline };
    }

    Это задача глобального перехвата, такие хуки ставятся во всех процессах в системе, никаких падений нет, работает везде кроме процесса java.exe: ява-машина почему-то не может прочитать свой файл конфигурации и выводит кучу ошибок. Если закоментировать вызов OutputDebugStringA и сразу сделать jmp на трамплин ява работает нормально. Стек проверял, OutputDebugString ничего лишнего там не оставляет. В чем может быть проблема?
     
  2. Babyshamble

    Babyshamble New Member

    Публикаций:
    0
    Регистрация:
    2 май 2010
    Сообщения:
    67
    Порятся регистры
     
  3. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Не должны по-идее: OutputDebugStringA сама должна следовать соглашению stdcall, и она ему следует - изменяются только ecx, edx. Пробовал даже делать pushad перед вызовом OutputDebugStringA и popad после него - эффекта ноль.
     
  4. ptr

    ptr New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2009
    Сообщения:
    130
    pushad/popad в своем обработчике вставь
     
  5. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    А не лучше ли вызвать сначала оригинальную ф-ю, а потом дебагстринг?
     
  6. RET

    RET Well-Known Member

    Публикаций:
    17
    Регистрация:
    5 янв 2008
    Сообщения:
    789
    Адрес:
    Jabber: darksys@sj.ms
    ntdrivers
    Явная ошибка в коде, выкладывайте его чтоб не гадать на кофе
     
  7. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Нашел ошибку. Моего запаса матерных слов не хватило что-бы охарактеризовать разработчиков Microsoft.. Дело в том, что у меня перехвачена CreateFileW, а Java вызывает CreateFileA, которая в свою очередь вызывает мою CreateFileW. Но имя файла CreateFileA передает в CreateFileW не через аргументы функции, а через именованную общую область памяти DBWIN_BUFFER (в MSDN такой способ вызова CreateFileW даже не описан). Получается так, что между вызовом явой CreateFileA и передачей управления на CreateFileW мой обработчик вызывает OutputDebugStringA, которая тоже работает через этот же DBWIN_BUFFER и благополучно затирает имя файла, к которому пытается обратиться Java. Видимо придется сохранять содержимое этого DBWIN_BUFFER в стеке и восстанавливать перед джампом на CreateFileW.
     
  8. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    Ни разу такого не видел. Можно поподробнее? (Что же тогда будет если будет работать одновременно несколько потоков?)
     
  9. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    А там есть mutex который этого не допускает. Но беда в том, что этот mutex уже захвачен потоком при исполнении CreateFileA и при вызове этим же потоком OutputDebugStringA никакой блокировки нет (рекурсивный захват). Подробнее описано тут: http://unixwiz.net/techtips/outputdebugstring.html
     
  10. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Насколько я понял, такое поведение CreateFileA не во всех версиях винды, возможно, что в семерке этот маразм уже убрали, но у меня в XP SP2 это работает именно так. В качестве имени файла в CreateFileW в этом случае передается строка "DBWIN_BUFFER".
     
  11. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Разобрался подробнее, все немного иначе. CreateFileA использует статический буфер в kernel32 для преобразования Ansi в Unicode, и указатель на этот буфер передается в CreateFileW в качестве имени файла. Но OutputDebugStringA использует тот же самый статический буфер для формирования имени меппинга DBWIN_BUFFER, и если вызвать ее между CreateFileA и CreateFileW имя файла будет затерто. Даже не знаю как гарантированно решить эту проблему, ведь у меня задача не извлекать аргументы из стека (это удобно тем, что не важно какая функция была вызвана, не нужно описывать прототипы). Единственное, что приходит на ум, это проверять в CreateFileW адрес возврата, находящийся на вершине стека при вызове хука, и если он соответствует kernel32.dll - не вызывать OutputDebugStringA, а сразу отдавать управление системе.
     
  12. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    хукни ZwCreateFile и не парься, либо костыль придумывай
     
  13. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    ntdrivers
    вызывай DbgPrint или какая там функция ее аналог.
     
  14. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    У нее нет аналогов, только если самому реализовывать общение с отладчиком через этот DBWIN_BUFFER. DbgPrint из ntdll не работает в режиме пользователя.
     
  15. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    Под какую систему это делаешь? Та статья мега древняя, там реверс OutputDebugStringA с winNT. В хр она реализована очень просто через документированую RaiseException, там кода на пару строк. И никакого маппинга там и в помине нет.

    А DbgPrint помоему очень даже работает в юзер моде, это OutputDebugString нету в кернеле, насколько я помню.

    Ты сам наблюдал все что написал выше? Я про передачу параметров через DBWIN_BUFFER. Или это догадки на основе древней статьи?)))
     
  16. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Система XP SP2. DbgPrint из ntdll это первое что я попробовал, но его вызов ничего не дает, сообщение не выводится. Проблема в другом, OutputDebugStringA портит статический буфер (пишет в него строку "DBWIN_BUFFER") в котором CreateFileA формирует имя файла в юникоде. Пробовал под Windows7, там действительно уже такой проблемы нет, но нужно что бы работало под XP SP2.
     
  17. ilja_

    ilja_ New Member

    Публикаций:
    0
    Регистрация:
    27 май 2010
    Сообщения:
    33
    можно просто в начале твоего кода скопировать имя файла в свой буффер и передать уже его в оригинальную функцию тогда результат будет нормальный.
     
  18. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    Все равно не верится блин)) На хр3 точно нету такой фигни. Можешь скинуть свою кернел32 плиз, охота глянуть на это)
     
  19. ntdrivers

    ntdrivers New Member

    Публикаций:
    0
    Регистрация:
    9 окт 2010
    Сообщения:
    25
    Да чего там, я порылся в исходниках 2000 винды, там такая хрень в каждой ansi функции, называется так:

    PUNICODE_STRING
    Basep8BitStringToStaticUnicodeString(
    IN LPCSTR lpSourceString
    )
    /*++

    Routine Description:

    Captures and converts a 8-bit (OEM or ANSI) string into the Teb Static
    Unicode String

    Arguments:

    lpSourceString - string in OEM or ANSI

    Return Value:

    Pointer to the Teb static string if conversion was successful, NULL
    otherwise. If a failure occurred, the last error is set.

    --*/
     
  20. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    Так то старая винда. Ты в дизасме OutputDebugStringA на хр у себя глянь. У меня там почти сразу вызывается kernel32.RaiseException->ntdll.RtlRaiseException->ntdll.NtRaiseException, и никаких преобразований не видно.