最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++實(shí)現(xiàn)inline hook的原理及應(yīng)用實(shí)例

 更新時(shí)間:2014年08月11日 09:22:18   投稿:shichen2014  
這篇文章主要介紹了C++實(shí)現(xiàn)inline hook的原理及應(yīng)用,需要的朋友可以參考下

本文實(shí)例簡(jiǎn)述了C++實(shí)現(xiàn)inline hook的原理及應(yīng)用,對(duì)于大家更好的理解inline hook原理及其應(yīng)用有很大的幫助。具體內(nèi)容如下:

一、Inline Hook簡(jiǎn)介:

1.INLINE HOOK原理:

Inline Hook通過(guò)硬編碼的方式向內(nèi)核API的內(nèi)存空間(通常是開(kāi)始的一段字節(jié),且一般在第一個(gè)call之前,這么做是為了防止堆?;靵y)寫(xiě)入跳轉(zhuǎn)語(yǔ)句,這樣,該API只要被調(diào)用,程序就會(huì)跳轉(zhuǎn)到我們的函數(shù)中來(lái),我們?cè)谧约簩?xiě)的函數(shù)里需要完成3個(gè)任務(wù):

1)重新調(diào)整當(dāng)前堆棧。程序流程在剛剛跳轉(zhuǎn)的時(shí)候,內(nèi)核API并沒(méi)有執(zhí)行完,而我們的函數(shù)需要根據(jù)其結(jié)果來(lái)進(jìn)行信息過(guò)濾,所以我們需要保證內(nèi)核API能在順利執(zhí)行完畢后返回到我們的函數(shù)中來(lái),這就要求對(duì)當(dāng)前堆棧做一個(gè)調(diào)整。

2)執(zhí)行遺失的指令。我們向內(nèi)核API地址空間些如跳轉(zhuǎn)指令(jmp xxxxxxxx)時(shí),勢(shì)必要覆蓋原先的一些匯編指令,所以我們一定要保證這些被覆蓋的指令能夠順利執(zhí)行(否則,你的及其就要BSOD了,呵呵,Blue Screen Of Death)。關(guān)于這部分指令的執(zhí)行,一般是將其放在我們的函數(shù)中,讓我們的函數(shù)“幫助”內(nèi)核API執(zhí)行完被覆蓋的指令,然后再跳回內(nèi)核API中被覆蓋內(nèi)后后的地址繼續(xù)執(zhí)行剩余內(nèi)容。跳回去的時(shí)候,一定要算好是跳回到什么地址,是內(nèi)核API起始地址后的第幾個(gè)字節(jié)。

3)信息過(guò)濾。這個(gè)就不用多說(shuō)了,內(nèi)核API順利執(zhí)行并返回到我們的函數(shù)中,我們自然要根據(jù)其結(jié)果做一些信息過(guò)濾,這部分內(nèi)容因被hook的API以及Hook目的的不同而不同。

2.Inline hook的工作流程:

1)驗(yàn)證內(nèi)核API的版本(特征碼匹配)。

2)撰寫(xiě)自己的函數(shù),要完成以上三項(xiàng)任務(wù)。

3)獲取自己函數(shù)的地址,覆蓋內(nèi)核API內(nèi)存,供跳轉(zhuǎn)。

簡(jiǎn)而言之,inlinehook的原理就是,修改函數(shù),使其跳轉(zhuǎn)到我們指定的地方。

常見(jiàn)的有改函數(shù)入口,也有改函數(shù)尾,函數(shù)中間的
比如,通常函數(shù)開(kāi)頭的匯編代碼都是這樣:mov edi,edi;push esp;mov ebp,esp,而我們便可以通過(guò)修改這里進(jìn)行HOOK。

二、示例代碼(該示例摘自看雪)

#include <ntifs.h>
#include <windef.h>
ULONG g_KiInsertQueueApc;
ULONG g_uCr0;
BYTE g_HookCode[5] = { 0xe9, 0, 0, 0, 0 }; //JMP NEAR
BYTE g_OrigCode[5] = { 0 }; // 原函數(shù)的前字節(jié)內(nèi)容
BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 }; //JMP FAR
BOOL g_bHooked = FALSE;
VOID
fake_KiInsertQueueApc (
            PKAPC Apc,
            KPRIORITY Increment
            );
VOID
Proxy_KiInsertQueueApc (
            PKAPC Apc,
            KPRIORITY Increment
            );
void WPOFF()
{
  ULONG uAttr;
  _asm
  {
    push eax;
    mov eax, cr0;
    mov uAttr, eax;
    and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
    mov cr0, eax;
    pop eax;
    cli
  };
  g_uCr0 = uAttr; //保存原有的 CRO 屬性
}
VOID WPON()
{
  _asm
  {
    sti
      push eax;
    mov eax, g_uCr0; //恢復(fù)原有 CR0 屬性
    mov cr0, eax;
    pop eax;
  };
}
//
// 停止inline hook
//
VOID UnHookKiInsertQueueApc ()
{
  KIRQL oldIrql;
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, g_OrigCode, 5 );
  KeLowerIrql(oldIrql);
  WPON();
  g_bHooked = FALSE;
}
//
// 開(kāi)始inline hook -- KiInsertQueueApc
//
VOID HookKiInsertQueueApc ()
{
  KIRQL oldIrql;
  if (g_KiInsertQueueApc == 0) {
    DbgPrint("KiInsertQueueApc == NULL\n");
    return;
  }
  //DbgPrint("開(kāi)始inline hook -- KiInsertQueueApc\n");
  DbgPrint( "KiInsertQueueApc的地址t0x%08x\n", (ULONG)g_KiInsertQueueApc );
  DbgPrint( "fake_KiInsertQueueApc的地址t0x%08x\n", (ULONG)fake_KiInsertQueueApc );
  
  // 保存原函數(shù)的前字節(jié)內(nèi)容
  RtlCopyMemory (g_OrigCode, (BYTE*)g_KiInsertQueueApc, 5);
  //jmp指令,此處為短跳,計(jì)算相對(duì)偏移,同時(shí),jmp xxxxxx這條指令占了5個(gè)字節(jié)
  *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_KiInsertQueueApc - (ULONG)g_KiInsertQueueApc - 5;
  // 禁止系統(tǒng)寫(xiě)保護(hù),提升IRQL到DPC
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, g_HookCode, 5 );
  *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)g_KiInsertQueueApc + 5 );
  RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc, g_OrigCode, 5);
  RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc + 5, jmp_orig_code, 7);
  // 恢復(fù)寫(xiě)保護(hù),降低IRQL
  KeLowerIrql(oldIrql);
  WPON();
  g_bHooked = TRUE;
}
//
// 跳轉(zhuǎn)到我們的函數(shù)里面進(jìn)行預(yù)處理,裸函數(shù),有調(diào)用者進(jìn)行堆棧的平衡
//
__declspec (naked)
VOID
fake_KiInsertQueueApc (
            PKAPC Apc,
            KPRIORITY Increment
            )
{
  // 去掉DbgPrint,不然這個(gè)hook會(huì)產(chǎn)生遞歸
  //DbgPrint("inline hook -- KiInsertQueueApc 成功\n");
  __asm
  {
    jmp Proxy_KiInsertQueueApc
  }
}
//
// 代理函數(shù),負(fù)責(zé)跳轉(zhuǎn)到原函數(shù)中繼續(xù)執(zhí)行
//
__declspec (naked)
VOID
Proxy_KiInsertQueueApc (
            PKAPC Apc,
            KPRIORITY Increment
            )
{
  __asm { // 共字節(jié)
    _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90 // 前字節(jié)實(shí)現(xiàn)原函數(shù)的頭字節(jié)功能
      _emit 0x90 // 這個(gè)填充jmp
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90 // 這字節(jié)保存原函數(shù)+5處的地址
      _emit 0x90 
      _emit 0x90 // 因?yàn)槭情L(zhǎng)轉(zhuǎn)移,所以必須是0x0080
  }
}
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
  UNICODE_STRING UniCodeFunctionName;
  RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
  return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName ); 
}
//根據(jù)特征值,從KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG FindKiInsertQueueApcAddress()
{
  char * Addr_KeInsertQueueApc = 0;
  int i = 0;
  char Findcode[] = { 0xE8, 0xcc, 0x29, 0x00, 0x00 };
  ULONG Addr_KiInsertQueueApc = 0;
  Addr_KeInsertQueueApc = (char *) GetFunctionAddr(L"KeInsertQueueApc");
  for(i = 0; i < 100; i ++)
  {
    if( Addr_KeInsertQueueApc[i] == Findcode[0] &&
      Addr_KeInsertQueueApc[i + 1] == Findcode[1] &&
      Addr_KeInsertQueueApc[i + 2] == Findcode[2] &&
      Addr_KeInsertQueueApc[i + 3] == Findcode[3] &&
      Addr_KeInsertQueueApc[i + 4] == Findcode[4]
    )
    {
      Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
      break;
    }
  }
  return Addr_KiInsertQueueApc;
}
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
  DbgPrint("My Driver Unloaded!");
  UnHookKiInsertQueueApc();
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
  DbgPrint("My Driver Loaded!");
  theDriverObject->DriverUnload = OnUnload;
  g_KiInsertQueueApc = FindKiInsertQueueApcAddress();
  HookKiInsertQueueApc();
  return STATUS_SUCCESS;
}

相關(guān)文章

  • C語(yǔ)言編程深入理解取整取余取模問(wèn)題示例分析

    C語(yǔ)言編程深入理解取整取余取模問(wèn)題示例分析

    這篇文章主要為大家介紹了C語(yǔ)言編程深入理解取整取余取模問(wèn)題的示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • 如何用C寫(xiě)一個(gè)web服務(wù)器之GCC項(xiàng)目編譯

    如何用C寫(xiě)一個(gè)web服務(wù)器之GCC項(xiàng)目編譯

    本文主要介紹了,如何用C寫(xiě)一個(gè)web服務(wù)器,Linux下用GCC進(jìn)行項(xiàng)目編譯,對(duì)此感興趣的同學(xué),可以參考下。
    2021-05-05
  • C++隨機(jī)生成迷宮算法

    C++隨機(jī)生成迷宮算法

    這篇文章主要為大家詳細(xì)介紹了C++隨機(jī)生成迷宮算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • c++ 移動(dòng)構(gòu)造相關(guān)總結(jié)

    c++ 移動(dòng)構(gòu)造相關(guān)總結(jié)

    這篇文章主要介紹了c++ 移動(dòng)構(gòu)造的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下
    2021-02-02
  • visualstudio2022工程重命名的圖文步驟

    visualstudio2022工程重命名的圖文步驟

    很多時(shí)候需要用到項(xiàng)目重命名,本文主要介紹了visualstudio2022工程重命名的圖文步驟,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • C++ virtual destructor虛擬析構(gòu)函數(shù)

    C++ virtual destructor虛擬析構(gòu)函數(shù)

    C++中基類采用virtual虛析構(gòu)函數(shù)是為了防止內(nèi)存泄漏。具體地說(shuō),如果派生類中申請(qǐng)了內(nèi)存空間,并在其析構(gòu)函數(shù)中對(duì)這些內(nèi)存空間進(jìn)行釋放,今天通過(guò)本文給大家介紹C++ virtual destructor虛擬析構(gòu)函數(shù)的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-05-05
  • 基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單五子棋游戲

    基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++中based for循環(huán)的實(shí)現(xiàn)

    C++中based for循環(huán)的實(shí)現(xiàn)

    C++中的范圍for循環(huán)是一種簡(jiǎn)潔的遍歷容器的方法,本文主要介紹了C++中based for循環(huán)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02
  • C++變量存儲(chǔ)的生命周期與作用域?qū)嵗a精講

    C++變量存儲(chǔ)的生命周期與作用域?qū)嵗a精講

    這篇文章主要介紹了C++變量存儲(chǔ)的生命周期與作用域,從創(chuàng)建到消亡的完整過(guò)程,例如人從出生到死亡的整個(gè)過(guò)程就是一個(gè)生命周期。本文將通過(guò)示例為大家詳細(xì)講講,感興趣的可以學(xué)習(xí)一下
    2022-10-10
  • C語(yǔ)言中指針 int *p=0;和int *p;*p=0;和”&“的關(guān)系和區(qū)別詳解

    C語(yǔ)言中指針 int *p=0;和int *p;*p=0;和”&“的關(guān)系和區(qū)別詳解

    這篇文章主要介紹了C語(yǔ)言中指針 int *p=0;和int *p;*p=0;和”&“有什么關(guān)系和區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02

最新評(píng)論

尼勒克县| 东方市| 岢岚县| 镇巴县| 榆中县| 旬邑县| 仁化县| 绥中县| 林芝县| 郯城县| 游戏| 兴义市| 韶山市| 兰西县| 汾阳市| 双峰县| 且末县| 砀山县| 大竹县| 印江| 龙游县| 平远县| 吉木萨尔县| 济南市| 高台县| 营口市| 中西区| 朝阳县| 本溪| 满洲里市| 泗阳县| 宜阳县| 大英县| 滕州市| 铅山县| 新巴尔虎右旗| 苗栗市| 谢通门县| 忻城县| 香港 | 张北县|