⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-apiworks.txt

📁 Cracker终结者——提供最优秀的软件保护技术
💻 TXT
📖 第 1 页 / 共 2 页
字号:
                  If it is not used, set it to NULL.

  HookAddress  -  pointer to your hook procedure (doesn't have to be exported).
                  If you are using C, your procedure can have format:

                  ResultType CallType MyApi(Par0, Par1,...) {
                     ResultType result;
                     // pre-orig-call actions: modify parameters, bufers
                     result = OrigApi(Par0, Par1,...);  // optional
                     lasterr = GetLastError(); 
                     // post-orig-call actions: modify parameters, buffers, result
                     SetLastError(lasterr); 
                     return(result);
                  }

                  if you are using ASM or __declspec(naked) there are no limits.


  ApiHookChain is array of API_HOOK structures. It must end with API_HOOK structure
which has ModuleExport == HOOKS_END.

NOTE: You can always change ApiHookChain during DllMain(,DLL_PROCESS_ATTACH),).

  Hooks can be exported (statically from Hooks_DLL) by 3 ways:
1) Hooks_DLL exports function "GetApiHookChain" which returns pointer
   to array of API_HOOK structures.
2) Hooks_DLL exports array of API_HOOK structures "ApiHookChain".

  Ad 1)----------------------------------------------------------
      API_HOOK ApiHookChain[9] = {
	{"KERNEL32.DLL", "WriteConsoleA",    HOOK_ALL,                          ALL_MODULES,   NULL,                  NewWriteConsoleA},
	{"USER32.DLL",   "FindWindowA",      HOOK_BY_ADDRESS,                   "MSVCRT.DLL",  NULL,                  NewWriteConsoleW},
	{NULL,           NULL,               0},
	{"GDI32.DLL",    "Pie",              HOOK_NY_ADDRESS|HOOK_BY_NAME,      "Display.drv", &UnhookPie,            NewPie},
	{"COMDLG32.DLL", "GetSaveFileNameA", HOOK_NY_ADDRESS|HOOK_BY_NAME,      MAIN_MODULE,   NULL,                  NewGetSaveFileNameA},
	{"KERNEL32.DLL", "GetProcAddress",   HOOK_ALL|HOOK_NOT_NT,              ALL_MODULES,   &UnhookGetProcAddress, NewGetProcAddress},
	{MAIN_MODULE,    "MyExeExportedAPI", HOOK_ALL,                          ALL_MODULES,   NULL,                  NewMyExeExportedAPI},
	{"KERNEL32.DLL", 7,                  HOOK_BY_NAME|HOOK_HARD|HOOK_NOT_NT, NULL,         &Unhook7,              New7},
	{HOOKS_END}
      };
      
      __EXPORT PAPI_HOOK GetApiHookChain(VOID) {
           return ApiHookChain;
      }

      or

      __EXPORT PAPI_HOOK GetApiHookChain(DWORD CallerPID) {
           return ApiHookChain;
      }

  Ad 2)----------------------------------------------------------
      __EXPORT API_HOOK ApiHookChain[6] = {
	{"KERNEL32.DLL", "WriteConsoleA",  HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteConsoleA},
	{"KERNEL32.DLL", "WriteConsoleW",  HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteConsoleW},
	{"KERNEL32.DLL", "GetStdHandle",   HOOK_BY_NAME, ALL_MODULES, NULL, NewGetStdHandle},
	{"KERNEL32.DLL", "WriteFile",      HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteFile},
	{"KERNEL32.DLL", "GetProcAddress", HOOK_BY_NAME, ALL_MODULES, NULL, NewGetProcAddress},
	{HOOKS_END}
      };    


  There is also possibility to build ApiHookChain on the fly (so-called dynamic hooks).
Dynamic ApiHookChain must begin with API_HOOK structure which has ModuleExport == HOOK_DYNAMIC.
UnhookAddresses member of API_HOOK with ModuleExport == HOOKS_DYNAMIC can point to
ExcludeModules - NULL terminated list of HMODULEs to exclude from hooking (when ALL_MODULES
and BY_NAME or BY_OVERWRITE were specified).
NULL UnhookAddresses == no exclusion.

      API_HOOK DynamicApiHookChain[7] = {
	{HOOKS_DYNAMIC}, //no exclusion
	{"KERNEL32.DLL", "WriteConsoleA",  HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteConsoleA},
	{"KERNEL32.DLL", "WriteConsoleW",  HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteConsoleW},
	{"KERNEL32.DLL", "GetStdHandle",   HOOK_BY_NAME, ALL_MODULES, NULL, NewGetStdHandle},
	{"KERNEL32.DLL", "WriteFile",      HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteFile},
	{"KERNEL32.DLL", "GetProcAddress", HOOK_BY_NAME, ALL_MODULES, NULL, NewGetProcAddress},
	{HOOKS_END}
      };    

HOOKS_DYNAMIC can be specified in any (static or dynamic) AHChain.
Its UnhookAddresses determines modules to exclude from hooking (via BY_ADDRESS, BY_NAME)
for the hook(s) that follow until HOOKS_END or next HOOKS_DYNAMIC is found in AHChain:
      HMODULE Exclude1[2] = 0x00400000, 0x74560000;
      HMODULE Exclude2[2] = 0x65400000, 0x10000000;

      API_HOOK DynamicApiHookChain[7] = {
	{"KERNEL32.DLL", "WriteConsoleA",  HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteConsoleA},
	{HOOKS_DYNAMIC, NULL, 0, NULL, Exclude1},
	{"KERNEL32.DLL", "WriteConsoleW",  HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteConsoleW},
	{HOOKS_DYNAMIC, NULL, 0, NULL, Exclude2},
	{"KERNEL32.DLL", "GetStdHandle",   HOOK_BY_NAME, ALL_MODULES, NULL, NewGetStdHandle},
	{"KERNEL32.DLL", "WriteFile",      HOOK_BY_NAME, ALL_MODULES, NULL, NewWriteFile},
	{HOOKS_DYNAMIC}, //no exclusion
	{"KERNEL32.DLL", "GetProcAddress", HOOK_BY_NAME, ALL_MODULES, NULL, NewGetProcAddress},
	{HOOKS_END}
      };    

--------------------------------------------------------------------------------------------------------------------------------------------------------------------
  ApiWorks also exports this high-level function:

  DWORD __stdcall HookApi(LPCTSTR  ModuleExport, LPCTSTR ApiNameOrOrd,  DWORD dwFlags, LPCTSTR ModuleImport,  PAPI_UNHOOK ApiUnhook, LPVOID HookAddress, HANDLE ExcludeModules[]);

    Prepares 1 dynamic hook and calls EstablishApiHooks
  == hooks ModuleExport.ApiNameOrOrd in the current process.

    Parameters have the same meaning as members of API_HOOK structure. ExcludeModules is
  the same as UnhookAddresses in API_HOOK {HOOKS_DYNAMIC} structure -> NULL terminated
  list of HMODULEs to exclude from hooking. UnhookAddresses and ExcludeModules parameters
  are optional: they must be NULL if they aren't used.
    If there's HOOK_OVERWRITE/RAW among/in dwFlags, ModuleImport is thought as a pointer
  to pointer-to-routine-to-jump-to-original-API. If this pointer is initially NULL, space
  for routine is allocated from current process' heap. 

    HookApi functions uses default RCINFO. If RCFlags.RC_FL_OWNFREE flag is set, memory
  isn't freed.

  If there wasn't unexpected exception in ApiWorks, ErrorAWSuccess is returned.
  This tells nothing about hooks application.

Following 2 examples do the same thing:
1)
  HANDLE ExcludeThem[6], hDll;
  int i = 0;
  DWORD status;
  ExcludeThem[i++] = GetModuleHandle(TEXT("~ThisModule~"));  //or hModule from DllMain
  if(hDll = GetModuleHandle(TEXT("ApiHooks.dll"))) ExcludeThem[i++] = hDll;  
  if(hDll = GetModuleHandle(TEXT("CRTDLL.dll")))   ExcludeThem[i++] = hDll;  
  if(hDll = GetModuleHandle(TEXT("MSVCRT.dll")))   ExcludeThem[i++] = hDll;  
  if(hDll = GetModuleHandle(TEXT("MFC42.dll")))    ExcludeThem[i++] = hDll;  
  ExcludeThem[i] = NULL; // NULL terminated list
  status = HookApi(TEXT("KERNEL32.dll"), TEXT("GetLocalTime"), HOOK_ALL, ALL_MODULES, NULL, NewGetLocalTime, ExcludeThem);
  if(status != ErrorAWSuccess) printf("Error %x", status);

2)
  HANDLE ExcludeThem[6], hDll;
  int i = 0;
  DWORD status;
  API_HOOK DynamicApiHookChain[3] = {
    {HOOKS_DYNAMIC,                ,         ,            , ExcludeThem},
    {"KERNEL32.DLL", "GetLocalTime", HOOK_ALL, ALL_MODULES, NULL, NewWriteConsoleA},
    {HOOKS_END}
  };    
  ExcludeThem[i++] = GetModuleHandle(TEXT("~ThisModule~"));  //or hModule from DllMain
  if(hDll = GetModuleHandle(TEXT("ApiHooks.dll"))) ExcludeThem[i++] = hDll;  
  if(hDll = GetModuleHandle(TEXT("CRTDLL.dll")))   ExcludeThem[i++] = hDll;  
  if(hDll = GetModuleHandle(TEXT("MSVCRT.dll")))   ExcludeThem[i++] = hDll;  
  if(hDll = GetModuleHandle(TEXT("MFC42.dll")))    ExcludeThem[i++] = hDll;  
  ExcludeThem[i] = NULL; // NULL terminated
  status = hEstablishApiHooks((LPCTSTR)DynamicApiHookChain, GetCurrentProcess(), 0);
  if(status != ErrorAWSuccess) printf("Error %x", status);

  Using dynamic hooks is more powerful than using HookApi. HookApi can hook 1 API
at time only.

  See:
    Examples\C-ApiWorks.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------
  How to call original API
  ------------------------

In case of HOOK_OVERWRITE is only one way of calling original API.
Similar case is HOOK_RAW, but developer must have intimate knowledge of code he hooks
(for example: all general registers and flags must be preserved, often it is not possible
to call original code - NewAPI must jump there).


In case of HOOK_BY_NAME or HOOK_BY_ADDRESS there are two possibilities of calling original
API:
  a) just call the API
    DWORD WINAPI NewGetVersion {
      DWORD Result = GetVersion() +1;
      return(Result);
    }
    In this case API is statically imported - ModuleExport was loaded by OS and Hooks_DLL
    import entry for GetVersion points to ModuleExport.GetVersion.

  b) call API using UnhookAddresses
    DWORD WINAPI NewGetVersion {
      DWORD Result =
      (TGetVersion)(ApiHookChain[GETVERSION_ENTRY].UnhookAddresses.WhereWhat[0].ReturnWhat)() +1;
      return(Result);
    }
    In this case ModuleExport should not be loaded due to Hooks_DLL loading (if Hooks_DLL
    doesn't import from ModuleExport at all).

Method b) is required for hook chaining. Consider two Hooks_DLL hooking the same
ModuleExport.ApiNameOrOrd in the same ModuleImport.
1) Hooks are established according to ApiHookChain of the first Hooks_DLL1. ApiNameOrOrd
   in ModuleImport points to NewApiOrOrd1.
2) AH is about to establish hooks according to ApiHookChain of the second Hooks_DLL2:
   HOOK_BY_ADDRESS fails - ModuleImport's IAT entry for ApiNameOrOrd was changed (points
   to Hooks_DLL1.NewApiNameOrOrd, not to ModuleExport.ApiNameOrOrd.
   Hooks_DLL2 must use HOOK_BY_NAME method. O.K., hooks were established and ApiNameOrdOrd
   in ModuleImport points to NewApiOrdOrd2.
   See: Examples\C-ApiWorks\HookSharing.


Original function can be called through this high-level function:
  DWORD __stdcall CallOrigFn(LPCSTR ModuleExport, LPCSTR ApiNameOrOrd, DWORD dwFlags, LPCVOID OrigFn, PAPI_UNHOOK ApiUnhook, DWORD nArgs, LPVOID pArgs);
Its parameters are the same as API_HOOK structure members (ANSI strings only).
The last two parameters nArgs and pArgs are the same as for LoadAndCall (ModWorks) API.
  CallOrigFn returns ErrorAMApi when it can find pointer to called function or when there's
HOOK_EXPORT but no HOOK_OVERWRITE/RAW set in dwFlags. In such a case can be original fucntion
called as follows:
  if(CallOrigFn(.....) == ErrorAMApi)
    OrigFn(.....);
where OrigFn is address of API before hooks application.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Being hook-friendly
  -------------------

  Some programs expect specific bytes to be located on address of API+-X.
What happens, if these special conditions aren't fulfilled and module is PE-hooked,
depends on hooked application.

Example: In TMext01 I've put 0xb8,0,0,0 at OpenProcess+0x24 -> ATM can control threads.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -