Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перехват API функции ReadFile 
:(
    Опции темы
GremlinProg
Дата 11.1.2012, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(freezeman @  11.1.2012,  12:50 Найти цитируемый пост)
Прописал в реестре "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs" путь к своей dll,запустил программу, но ничего не перехватывает

не перехватывает после перезагрузки?


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
freezeman
Дата 11.1.2012, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Цитата(actuator @ 10.1.2012,  16:33)
Найди в документации раздел Using Detours - там пример DLL-ки, которая делает перехват функции для процесса, к которому подключается, доработай его и добавь путь к ней в "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs" - тогда она будет подключаться ко всем процессам, где используется библиотека user32 (то есть, практически всем). В примере адрес перехватываемой функции получается статически, но его ещё можно найти в таблицах импорта/экспорта соответствующими функциями.

Я прописал в реестр путь к dll, но ничего не происходит... Сделал перехват MessageBox, запустил MessageBox'ы в разных приложениях системы, но ничего не происходит... в чем может быть проблема?

Код

#include <windows.h>
#pragma comment (lib, "detours.lib")
#include <detours.h>
static LONG dwSlept = 0;
// Target pointer for the uninstrumented Sleep API.
static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep;
// Detour function that replaces the Sleep API.
VOID WINAPI MyMessBox(HWND hwnd, char *text, char *hdr, UINT utype)
{
    // Save the before and after times around calling the Sleep API.
    DWORD dwBeg = GetTickCount();
    //TrueSleep(dwMilliseconds);
    DWORD dwEnd = GetTickCount();
    MessageBox(NULL, L"Hello from Hooked function", L"Hello", MB_OK);
    InterlockedExchangeAdd(&dwSlept, dwEnd - dwBeg);
}
// C:\Documents and Settings\SMan\Мои документы\Visual Studio 2010\Projects\msdetours\Debug\msdetours.dll
// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function.  The Sleep target function is referred to
// through the TrueSleep target pointer.
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        MessageBox(NULL, L"Hello from DLL_PROCESS_ATTACH", L"Hello", MB_OK);
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)MessageBoxA, MyReadFile);
        DetourTransactionCommit();
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        MessageBox(NULL, L"Hello from DLL_PROCESS_DETACH", L"Hello", MB_OK);
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)MessageBoxA, MyReadFile);
        DetourTransactionCommit();
    }
    return TRUE;
}

PM MAIL   Вверх
freezeman
Дата 11.1.2012, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Цитата(GremlinProg @ 11.1.2012,  11:43)
Цитата(freezeman @  11.1.2012,  12:50 Найти цитируемый пост)
Прописал в реестре "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs" путь к своей dll,запустил программу, но ничего не перехватывает

не перехватывает после перезагрузки?

Да, перезагружал..
PM MAIL   Вверх
freezeman
Дата 11.1.2012, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Что делать, если после того, как я прописал путь к подгружаемой dll в регистре "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs" она (dll) не хочет подключаться ни к одному процессу...может я допустил какую-нибудь типичную ошибку, код приводил выше...

После добавления в регистр комп. перегружал, ОС Windows XP x86 SP3.
PM MAIL   Вверх
actuator
Дата 11.1.2012, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 15.12.2011

Репутация: нет
Всего: 3



Во-первых, извини, с appinit_dlls - это всё-таки вредный совет. Из-за особенностей работы стандартных библиотек в VC (есть подозрение, что из-за поддержки расширений .NET), DLL-ка с перехватчиком неправильно инициализируется, что вообще может грохнуть систему. Так что придется этот вариант отложить. А не подключается у тебя перехватчик потому, что в пути к нему есть пробелы, а пробелы используются как разделитель списка библиотек. Нужно либо скопировать библиотеку в папку без них, либо использовать короткие имена файлов, которые можно получить winapi-функцией GetShortPathName.

Во-вторых, прежде чем писать код, пойми, как работает перехватчик: он, внедряясь в процесс, переписывает несколько инструкций в начале перехватываемой функции переходом (jmp) к предоставленной тобой функции. Если ты, как сделал выше, попробуешь из MyMessBox вызвать MessageBox, то программа просто уйдет в бесконечный цикл. Именно поэтому функция DetourAttach принимает указатель на указатель - перед перехватом она выделяет блок памяти, в который копирует заменяемые инструкции, и дописывает в него переход на остаток функции в обход уже записанного туда перехода на твою функцию и заменяет переданный указатель, чтобы он указывал на этот блок памяти. Когда тебе потребуется оригинал функции, ты используешь его.

В итоге код библиотеки выглядит как-то так:
Код
#include <windows.h>
#include <detours.h>

#pragma comment (lib, "detours.lib")

static int (WINAPI * RealMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT) = MessageBoxA;

VOID WINAPI MyMessBox(HWND hwnd, char *text, char *hdr, UINT utype)
{
    RealMessageBoxA(NULL, "Hello from Hooked function", "Hello", MB_OK);
    RealMessageBoxA(hwnd, text, hdr, utype);
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
    return TRUE;
    if (dwReason == DLL_PROCESS_ATTACH) {
        // До перехвата можно использовать оригинальный адрес функции
        MessageBoxA(NULL, "Hello from DLL_PROCESS_ATTACH", "Hello", MB_OK);

        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)RealMessageBoxA, MyMessBox);
        DetourTransactionCommit();
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        // После перехвата - только тот, что нам дала функция DetourAttach
        // (иначе вызовем перехватчик, а не оригинал функции)
        RealMessageBoxA(NULL, "Hello from DLL_PROCESS_DETACH", "Hello", MB_OK);
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)RealMessageBoxA, MyMessBox);
        DetourTransactionCommit();
    }
    return TRUE;
}


Теперь о том, как без appinit_dlls цеплять её к процессам. В статье на RSDN в разделе "Внедрение 1" есть подходящий для этого код, надо только обернуть struct INJECTORCODE в блок #pragma pack(push,1) / #pragma pack(pop), чтобы убрать выравнивание. Разве что искать id нужных процессов придется, самостоятельно. А вот сам их способ перехвата лучше не использовать - в detours он надежнее.
PM MAIL   Вверх
freezeman
Дата 11.1.2012, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



actuator большое спасибо за помощь, буду пробовать...
благодарю также всех за помощь...
PM MAIL   Вверх
freezeman
Дата 11.1.2012, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Цитата(actuator @ 11.1.2012,  20:05)
Во-первых, извини, с appinit_dlls - это всё-таки вредный совет. Из-за особенностей работы стандартных библиотек в VC (есть подозрение, что из-за поддержки расширений .NET), DLL-ка с перехватчиком неправильно инициализируется, что вообще может грохнуть систему. Так что придется этот вариант отложить. А не подключается у тебя перехватчик потому, что в пути к нему есть пробелы, а пробелы используются как разделитель списка библиотек. Нужно либо скопировать библиотеку в папку без них, либо использовать короткие имена файлов, которые можно получить winapi-функцией GetShortPathName.

Во-вторых, прежде чем писать код, пойми, как работает перехватчик: он, внедряясь в процесс, переписывает несколько инструкций в начале перехватываемой функции переходом (jmp) к предоставленной тобой функции. Если ты, как сделал выше, попробуешь из MyMessBox вызвать MessageBox, то программа просто уйдет в бесконечный цикл. Именно поэтому функция DetourAttach принимает указатель на указатель - перед перехватом она выделяет блок памяти, в который копирует заменяемые инструкции, и дописывает в него переход на остаток функции в обход уже записанного туда перехода на твою функцию и заменяет переданный указатель, чтобы он указывал на этот блок памяти. Когда тебе потребуется оригинал функции, ты используешь его.

В итоге код библиотеки выглядит как-то так:
...

Пробовал внедрить, как описано на rsdn, но при инъекции выдает звуковой сигнал и всё... Прописал в реестре без пробелов и действительно заработало, но выдает сообщения из DLL_PROCESS_ATTACH и DLL_PROCESS_DETACH, но не перенаправляет на MyMessBox, а при выходе из почти любого приложения появляется сообщение "Инструкция по адресу "0x7c9100e8" обратилась к памяти по адресу "0x00000010". Память не может быть "read" ". В чем может быть проблема?


Переделал Вашу dll-ку для перехвата функции ReadFile... Перехватывает, заходит в функцию, но при выходе из приложения выдает туже ошибку
"Инструкция по адресу "0x7c9100e8" обратилась к памяти по адресу "0x00000010". Память не может быть "read" "


Это сообщение отредактировал(а) freezeman - 11.1.2012, 22:52
PM MAIL   Вверх
freezeman
Дата 12.1.2012, 09:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Что если реализовать какой-нибудь обработчик ошибок и перехватить её? Например, try ... catch...

PM MAIL   Вверх
actuator
Дата 12.1.2012, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 15.12.2011

Репутация: нет
Всего: 3



Не исключениями, а JIT-отладчиком. Если у тебя только express-версии среды, скачай какой-нибудь OllyDbg, назначь его отладчиком по умолчанию и прогони на отладочной сборке перехватчика - покажет, какая функция роняет программу. Ничего подробнее сказать не могу, пока не покажешь код.
PM MAIL   Вверх
freezeman
Дата 13.1.2012, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Если сделал все правильно... Запустил через OllyDbg notepad.exe и когда закрываю программу отладчик указывает на 
7C9100E8   . 0B43 10        OR EAX,DWORD PTR DS:[EBX+10]

эти данные нужно было отследить?


Это сообщение отредактировал(а) freezeman - 13.1.2012, 13:40
PM MAIL   Вверх
actuator
Дата 13.1.2012, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 15.12.2011

Репутация: нет
Всего: 3



Нет, нужно по содержимому стека (там, где ты смотрел - правое нижнее окно) посмотреть цепочку вызовов, скорее всего там будет вызов твоей библиотеки (заодно укажи в меню Debug -> Select path for symbols папку, где у тебя лежит .pdb-шка от библиотеки, обычно там же где она сама - так будут доступны более подробные символы).
Хотя я уверен, что ошибка где-то у тебя в коде - может, указатель провисший. Проверь также настройки компиляции - "C/C++ -> Создание кода, Библиотека времени выполнения - многопоточная".

Это сообщение отредактировал(а) actuator - 13.1.2012, 15:08
PM MAIL   Вверх
freezeman
Дата 13.1.2012, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Вот скрин отладчика... img 


По поводу локального перехвата, я переписал вариант с rsdn и написал тестовое приложение, которое использует api readfile, после внедрения он эту функцию прекрасно перехватил, но когда внедряю в другие процессы, то он заходит, но не перехватывает.

вот код инъектора
Код

#include "stdafx.h"
// #include <afxwin.h>
#include "stddef.h"
#include <windows.h>
#pragma pack(push,1) 
BOOL InjectDll(DWORD, char*);

int main(int argc, char* argv[])
{
  if(argc<3) 
  {
    printf("Parameters: PID , Dllname"); 
    //getch();
    return 0;
  }
  InjectDll(atol(argv[1]), argv[2]);
  return 0;
}

//структура описывает поля, в которых содержится код внедрения
struct INJECTORCODE
{
  BYTE  instr_push_loadlibrary_arg; //инструкция push
  DWORD loadlibrary_arg;            //аргумент push  

  WORD  instr_call_loadlibrary;     //инструкция call []  
  DWORD adr_from_call_loadlibrary;

  BYTE  instr_push_exitthread_arg;
  DWORD exitthread_arg;

  WORD  instr_call_exitthread;
  DWORD adr_from_call_exitthread;

  DWORD addr_loadlibrary;
  DWORD addr_exitthread;     //адрес функции ExitTHread
  BYTE  libraryname[100];    //имя и путь к загружаемой библиотеке  
};


BOOL InjectDll(DWORD pid, char *lpszDllName)
{
      
  HANDLE hProcess;
  BYTE *p_code;
  INJECTORCODE cmds;
  DWORD wr, id;

  //открыть процесс с нужным доступом
  hProcess=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, FALSE, pid);
  if(hProcess == NULL)
  {
    MessageBoxA(NULL, "You have not enough rights to attach dlls", "Error!", 0);
    return FALSE;
  }

  //зарезервировать память в процессе
    p_code = (BYTE*)VirtualAllocEx(hProcess, 0, sizeof(INJECTORCODE),
                                   MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(p_code==NULL)
    {
      MessageBox(NULL, TEXT("Unable to alloc memory in remote process"),
                       TEXT("Error!"), 0);
      return FALSE;
    }

  //инициализировать  машинный код
  cmds.instr_push_loadlibrary_arg = 0x68; //машинный код инструкции push
  cmds.loadlibrary_arg = (DWORD)((BYTE*)p_code + offsetof(INJECTORCODE, libraryname));

  cmds.instr_call_loadlibrary = 0x15ff; //машинный код инструкции call
  cmds.adr_from_call_loadlibrary = (DWORD)(p_code + offsetof(INJECTORCODE, addr_loadlibrary));

  cmds.instr_push_exitthread_arg  = 0x68;
  cmds.exitthread_arg = 0;

  cmds.instr_call_exitthread = 0x15ff; 
  cmds.adr_from_call_exitthread = (DWORD)(p_code + offsetof(INJECTORCODE, addr_exitthread));

  cmds.addr_loadlibrary = (DWORD)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");

  cmds.addr_exitthread  = (DWORD)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"ExitThread");

  if(strlen(lpszDllName)>99)
  {
     MessageBox(NULL, TEXT("Dll Name too long"), TEXT("Error!"), 0);
     return FALSE;
  }
  strcpy((char*)cmds.libraryname, lpszDllName );
  /*После инициализации cmds в мнемонике ассемблера выглядит следующим
    образом:
      push  adr_library_name               ;аргумент ф-ции loadlibrary
      call dword ptr [loadlibrary_adr]     ; вызвать LoadLibrary 
      push exit_thread_arg                 ;аргумент для ExitThread
      call dword ptr [exit_thread_adr]     ;вызвать ExitThread     
  */
  //записать машинный код по зарезервированному адресу
  WriteProcessMemory(hProcess, p_code, &cmds, sizeof(cmds), &wr);
  //выполнить машинный код
  HANDLE z = CreateRemoteThread(hProcess, NULL, 0, (unsigned long (__stdcall *)(void *))p_code, 0, 0, &id);
  //ожидать завершения удаленного потока
  WaitForSingleObject(z, INFINITE);
  //освободить память

  VirtualFreeEx(hProcess, (void*)p_code, sizeof(cmds), MEM_RELEASE);
  #pragma pack(pop)
  return TRUE;
}



Это сообщение отредактировал(а) freezeman - 13.1.2012, 17:05
PM MAIL   Вверх
actuator
Дата 14.1.2012, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 15.12.2011

Репутация: нет
Всего: 3



Вот, сделал программку, пишущую c:\readfile-log\readfile-log.txt файлик с аргументами всех вызовов твоего ReadFile для заданного процесса: http://ifolder.ru/28114248. Папку создай, у тебя должны быть в ней права на запись. Запускаешь так:

injector.exe <pid процесса> <полный путь к library.dll>

У меня никаких падений не наблюдается. Если у тебя не заработает - то помочь не смогу. В коде просто нечему падать.
PM MAIL   Вверх
freezeman
Дата 15.1.2012, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 175
Регистрация: 21.1.2011

Репутация: нет
Всего: нет



Хоть и вылетает ошибка, но у ладно с ней, решу позже...Решил проверить на Windows 7 x86, но ничего не происходит, не перехватывается...прописал в путь к моей dll в реестре...что это моджет быть? Мне казалось, что MS Detours подходит для всех систем семейства Windows NT...
PM MAIL   Вверх
actuator
Дата 16.1.2012, 04:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 15.12.2011

Репутация: нет
Всего: 3



Все-таки используешь appinit_dlls? Вот потому и не работает, я уже писал выше. Майкрософтовская библиотека при этом глючит. Делай процесс и подключай библиотеку через него него. Если нужен перехват системных процессов - делай программу службой и назначай запуск от имени администратора.
Ну а чтобы включить appinit_dlls на windows 7, нужно изменить ещё пару ключей реестра.
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1730 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.