Перехват функции через таблицу экспорта

Тема в разделе "WASM.BEGINNERS", создана пользователем _nic, 7 дек 2011.

  1. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    Просто неполучаеться перехват(((
    Подскажите плз где я ошибься:
    Код (Text):
    1. DWORD origadr;
    2. typedef HANDLE (WINAPI *CreateThrPrototype)(
    3.     __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    4.   __in       SIZE_T dwStackSize,
    5.   __in       LPTHREAD_START_ROUTINE lpStartAddress,
    6.   __in_opt   LPVOID lpParameter,
    7.   __in       DWORD dwCreationFlags,
    8.   __out_opt  LPDWORD lpThreadId);
    9.  
    10. void SetHook(DWORD libB,DWORD HookAdr)
    11. {
    12.     DWORD toNT=( (IMAGE_DOS_HEADER*) libB)->e_lfanew;
    13.     IMAGE_NT_HEADERS *nt=(IMAGE_NT_HEADERS *)(libB+toNT);
    14.     IMAGE_EXPORT_DIRECTORY *exp=(IMAGE_EXPORT_DIRECTORY *)(libB+nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    15.     DWORD *Names=(DWORD*)(exp->AddressOfNames+libB);
    16.     DWORD *Funcs=(DWORD*)(exp->AddressOfFunctions+libB);
    17.     char *name;
    18.     DWORD old;
    19.     if(VirtualProtect(Funcs,4*exp->NumberOfFunctions,PAGE_EXECUTE_READWRITE,&old))
    20.     {
    21.         for(DWORD i=0;i<exp->NumberOfNames;i++)
    22.         {
    23.             name=( (char*) (Names[i]+libB) );
    24.             if(strcmp("CreateThread",name)==0)
    25.             {
    26.                 //printf("%X\n",Funcs[i]);
    27.                 origadr=Funcs[i]+libB;
    28.                 Funcs[i]=HookAdr-libB;
    29.             }
    30.         }
    31.         VirtualProtect(Funcs,4*exp->NumberOfFunctions,old,&old);
    32.     }
    33. }
    34. HANDLE WINAPI HOOKf(
    35.     __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    36.   __in       SIZE_T dwStackSize,
    37.   __in       LPTHREAD_START_ROUTINE lpStartAddress,
    38.   __in_opt   LPVOID lpParameter,
    39.   __in       DWORD dwCreationFlags,
    40.   __out_opt  LPDWORD lpThreadId)
    41. {
    42.     printf("thread hook!\n");
    43.     CreateThrPrototype CreateThr=(CreateThrPrototype)origadr;
    44.     CreateThr(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter,dwCreationFlags,lpThreadId);
    45.     return 0;
    46. }
    47. DWORD WINAPI ThrFunc(LPVOID lParam)
    48. {
    49.     printf("thread func!\n");
    50.     return 0;
    51. }
    52. int _tmain(int argc, _TCHAR* argv[])
    53. {
    54.     HMODULE kernel=GetModuleHandle(L"kernel32.dll");
    55.     SetHook((DWORD)kernel,(DWORD)&HOOKf);
    56.     CreateThrPrototype CreateThr=(CreateThrPrototype)GetProcAddress(kernel,"CreateThread");
    57.     CreateThr(0,0,ThrFunc,0,0,0);
    58.     getch();
    59.     return 0;
    60. }
    ЗЫ:или так невозможно?
     
  2. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    _nic
    Кроме таблицы экспорта надо перехватить функцию в таблице импорта каждого модуля, который импортирует эту функцию.
     
  3. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    Импорт не экспорт.По этому я пытаюсь через экспорт.Кто то может сказать.Есть какие то ограничения на адрес в таблице экспорта или нет??Он что не может за грань образа модуля выходить?Тем более хрен поймешь когда в список модулей еще что то добавилось.
     
  4. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    _nic
    Может.
    Если перехватывать тольк экспорт, то GetProcAddress будет возвращать адрес вашей функции, но если вы не поставите перехват на импорт, то все вызовы через таблицу импорта продут мимо вас.
    Если добавилось после перехвата экспорта, то там будет адрес вашей функции.
     
  5. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    Смотрим код внимательно.Функция используеться динамически,после правки адреса в таблице экспорта.
    Но у меня или не тот адрес правился,то или вообще какая то магия =/ Несрабатывает функция заглушка.
     
  6. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    _nic
    Честно говоря сначала я в код особо не вчитывался.
    1) Проще будет искать не имя, а адрес: (OriginalCreateThread-libB) в AddressOfFunctions, и там-же его менять.
    2) Если большое желание именно по имени, то:
    I. Смотрим какой индекс в AddressOfNames.
    II. Достаём ординал по найденному индексу из AddressOfNameOrdinals.
    III. Используем этот ординал в качестве индекса в AddressOfFunctions.
    Если не ошибаюсь, то так.

    PS Тут есть:http://wasm.ru/article.php?article=1002007
     
  7. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    1й вариант работает.НО.При перехвате _beginthreadex,проблема.В дизассемблере видно что _beginthreadex обертка для CreateThread.Хук ф-ция вызываеться нормально,но когда вызываеться оригинальная CreateThread,то вылазит исключение о том что в нужном месте память не читаема(
    Код (Text):
    1. DWORD origadr;
    2. typedef HANDLE (WINAPI *CreateThrPrototype)(
    3.     __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    4.   __in       SIZE_T dwStackSize,
    5.   __in       LPTHREAD_START_ROUTINE lpStartAddress,
    6.   __in_opt   LPVOID lpParameter,
    7.   __in       DWORD dwCreationFlags,
    8.   __out_opt  LPDWORD lpThreadId);
    9.  
    10. void SetHook(DWORD libB,DWORD HookAdr,DWORD funcVA)
    11. {
    12.     DWORD toNT=( (IMAGE_DOS_HEADER*) libB)->e_lfanew;
    13.     IMAGE_NT_HEADERS *nt=(IMAGE_NT_HEADERS *)(libB+toNT);
    14.     IMAGE_EXPORT_DIRECTORY *exp=(IMAGE_EXPORT_DIRECTORY *)(libB+nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    15.     DWORD *Names=(DWORD*)(exp->AddressOfNames+libB);
    16.     DWORD *Funcs=(DWORD*)(exp->AddressOfFunctions+libB);
    17.     //char *name;
    18.     DWORD funcRVA=funcVA-libB;
    19.     DWORD old;
    20.     if(VirtualProtect(Funcs,4*exp->NumberOfFunctions,PAGE_EXECUTE_READWRITE,&old))
    21.     {
    22.         for(DWORD i=0;i<exp->NumberOfFunctions;i++)
    23.         {
    24.             /*name=( (char*) (Names[i]+libB) );
    25.             if(strcmp("CreateThread",name)==0)
    26.             {
    27.                 //printf("%X\n",Funcs[i]);
    28.                 origadr=Funcs[i]+libB;
    29.                 Funcs[i]=HookAdr-libB;
    30.             }*/
    31.             if(Funcs[i]==funcRVA)
    32.             {
    33.                 Funcs[i]=HookAdr-libB;
    34.                 break;
    35.             }
    36.         }
    37.         VirtualProtect(Funcs,4*exp->NumberOfFunctions,old,&old);
    38.     }
    39. }
    40. HANDLE WINAPI HOOKf(
    41.     __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    42.   __in       SIZE_T dwStackSize,
    43.   __in       LPTHREAD_START_ROUTINE lpStartAddress,
    44.   __in_opt   LPVOID lpParameter,
    45.   __in       DWORD dwCreationFlags,
    46.   __out_opt  LPDWORD lpThreadId)
    47. {
    48.     printf("thread hook!\n");
    49.     CreateThrPrototype CreateThr=(CreateThrPrototype)origadr;
    50.     CreateThr(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter,dwCreationFlags,lpThreadId);
    51.     return 0;
    52. }
    53. DWORD WINAPI ThrFunc(LPVOID lParam)
    54. {
    55.     printf("thread func!\n");
    56.     return 0;
    57. }
    58. typedef uintptr_t (__cdecl *_beginthreadexProt)(_In_opt_ void * _Security, _In_ unsigned _StackSize,
    59.         _In_ unsigned (__stdcall * _StartAddress) (void *), _In_opt_ void * _ArgList,
    60.         _In_ unsigned _InitFlag, _Out_opt_ unsigned * _ThrdAddr);
    61. static unsigned __stdcall bgThrEx(void *Params)
    62. {
    63.     printf("_beginthreadex\n");
    64.     return 0;
    65. }
    66. int _tmain(int argc, _TCHAR* argv[])
    67. {
    68.     HMODULE kernel=GetModuleHandle(L"kernel32.dll");
    69.     origadr=(DWORD)GetProcAddress(kernel,"CreateThread");
    70.     SetHook((DWORD)kernel,(DWORD)&HOOKf,origadr);
    71.     CreateThrPrototype CreateThr=(CreateThrPrototype)GetProcAddress(kernel,"CreateThread");
    72.     CreateThr(0,0,ThrFunc,0,0,0);
    73.     HMODULE CRT=LoadLibrary(L"msvcrt.dll");
    74.     if(CRT!=NULL)
    75.     {
    76.         _beginthreadexProt bgthreEX=(_beginthreadexProt)GetProcAddress(CRT,"_beginthreadex");
    77.         bgthreEX(0,0,bgThrEx,0,0,0);
    78.     }
    79.     getch();
    80.     return 0;
    81. }
    Почему так?
     
  8. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    _nic
    А черт его знает, посмотрите в отладчике, где конкретно падает.
     
  9. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    Код (Text):
    1. 6FF7DC97  cmp         dword ptr [ecx],edi
    Только мне это не очем не говорит(
     
  10. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    Плохо, что не говорит.

    Приведите больше кода, в окрестностях ошибки (из отладчика).

    P.S. Это говорит что у вас проблема с указателями.
     
  11. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    _nic
    Нормальный отладчик должен показать не только адреса, но и имена DLL и даже имя функции. Тогда проще будет анализировать. А так - никому это тоже почти ничего не говорит.

    Ну и просто мысли : то что хук отработал, еще не значит что вы ничего не запортили. Возможно ваша вставка и привела к падению в следующем вызове. Смотрите на отладчике вызов "проблемной" CreateThread с хуком и без хука - в чем там разница?
     
  12. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    немного видоизменил код:
    Код (Text):
    1. DWORD origadr;
    2. typedef HANDLE (WINAPI *CreateThrPrototype)(
    3.     __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    4.   __in       SIZE_T dwStackSize,
    5.   __in       LPTHREAD_START_ROUTINE lpStartAddress,
    6.   __in_opt   LPVOID lpParameter,
    7.   __in       DWORD dwCreationFlags,
    8.   __out_opt  LPDWORD lpThreadId);
    9.  
    10. void SetHook(DWORD libB,DWORD HookAdr,DWORD funcVA)
    11. {
    12.     DWORD toNT=( (IMAGE_DOS_HEADER*) libB)->e_lfanew;
    13.     IMAGE_NT_HEADERS *nt=(IMAGE_NT_HEADERS *)(libB+toNT);
    14.     IMAGE_EXPORT_DIRECTORY *exp=(IMAGE_EXPORT_DIRECTORY *)(libB+nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    15.     DWORD *Names=(DWORD*)(exp->AddressOfNames+libB);
    16.     DWORD *Funcs=(DWORD*)(exp->AddressOfFunctions+libB);
    17.     //char *name;
    18.     DWORD funcRVA=funcVA-libB;
    19.     DWORD old;
    20.     if(VirtualProtect(Funcs,4*exp->NumberOfFunctions,PAGE_EXECUTE_READWRITE,&old))
    21.     {
    22.         for(DWORD i=0;i<exp->NumberOfFunctions;i++)
    23.         {
    24.             /*name=( (char*) (Names[i]+libB) );
    25.             if(strcmp("CreateThread",name)==0)
    26.             {
    27.                 //printf("%X\n",Funcs[i]);
    28.                 origadr=Funcs[i]+libB;
    29.                 Funcs[i]=HookAdr-libB;
    30.             }*/
    31.             if(Funcs[i]==funcRVA)
    32.             {
    33.                 Funcs[i]=HookAdr-libB;
    34.                 break;
    35.             }
    36.         }
    37.         VirtualProtect(Funcs,4*exp->NumberOfFunctions,old,&old);
    38.     }
    39. }
    40. typedef unsigned (WINAPI *TrhRoutine)(LPVOID lParam);
    41. DWORD WINAPI ThrStub(LPVOID lParam)
    42. {
    43.     TrhRoutine Func=(TrhRoutine)lParam;
    44.     return(Func(lParam));//отладчик стопает тут
    45. }
    46. HANDLE WINAPI HOOKf(
    47.     __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    48.   __in       SIZE_T dwStackSize,
    49.   __in       LPTHREAD_START_ROUTINE lpStartAddress,
    50.   __in_opt   LPVOID lpParameter,
    51.   __in       DWORD dwCreationFlags,
    52.   __out_opt  LPDWORD lpThreadId)
    53. {
    54.     printf("thread hook!\n");
    55.     CreateThrPrototype CreateThr=(CreateThrPrototype)origadr;
    56.     //CreateThr(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter,dwCreationFlags,lpThreadId);
    57.     CreateThr(lpThreadAttributes,dwStackSize,ThrStub,lpStartAddress,dwCreationFlags,lpThreadId);
    58.     return 0;
    59. }
    60. DWORD WINAPI ThrFunc(LPVOID lParam)
    61. {
    62.     printf("thread func!\n");
    63.     return 0;
    64. }
    65. typedef uintptr_t (__cdecl *_beginthreadexProt)(_In_opt_ void * _Security, _In_ unsigned _StackSize,
    66.         _In_ unsigned (__stdcall * _StartAddress) (void *), _In_opt_ void * _ArgList,
    67.         _In_ unsigned _InitFlag, _Out_opt_ unsigned * _ThrdAddr);
    68. static unsigned __stdcall bgThrEx(void *Params)
    69. {
    70.     printf("_beginthreadex\n");
    71.     return 0;
    72. }
    73. int _tmain(int argc, _TCHAR* argv[])
    74. {
    75.     HMODULE kernel=GetModuleHandle(L"kernel32.dll");
    76.     origadr=(DWORD)GetProcAddress(kernel,"CreateThread");
    77.     SetHook((DWORD)kernel,(DWORD)&HOOKf,origadr);
    78.     CreateThrPrototype CreateThr=(CreateThrPrototype)GetProcAddress(kernel,"CreateThread");
    79.     CreateThr(0,0,ThrFunc,0,0,0);
    80.     //CreateThr(0,0,ThrFunc,0,0,0);
    81.     HMODULE CRT=LoadLibrary(L"msvcrt.dll");
    82.     if(CRT!=NULL)
    83.     {
    84.         _beginthreadexProt bgthreEX=(_beginthreadexProt)GetProcAddress(CRT,"_beginthreadex");
    85.         bgthreEX(0,0,bgThrEx,0,0,0);
    86.     }
    87.     getch();
    88.     return 0;
    89. }
    Теперь вылазит исключение об повреждение кучи.Ничего непонимаю(
     
  13. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    _nic
     
  14. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    _nic
    В дизасме видно, что это не простая обертка, и в CreateThread передается вовсе не сама функция _StartAddress, а спец.функция из самой msvcrt, а исходный адрес _StartAddress и _ArgList упаковываются в динамич.структуру, адрес которой передается в качестве lpParameter в CreateThread.
    Поэтому почему валится последний вариант вообще очевидно, т.к. так делать нельзя.
    А предыдущий валится из-за твоего собственного бага, т.к. твой HOOKf почему-то возвращает 0, а не результат CreateThread - в итоге _beginthreadex считает вызов неудачным и освобождает дин.блок данных с адресом функции, и когда msvcrt-шная функция потока начинает работать, то lpParameter, из которого она должна взять исходный _StartAddress уже давно затерт каким-то мусором