青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

不在浮沙筑高臺-demons
C++/OS/disassembly/Anti-virus
posts - 5,  comments - 5,  trackbacks - 0
 
  風格:為了讓國外朋友也能看懂,代碼中的注釋全部用英文,而分析部分我用中文做詳細解釋, 如果您不習慣這種表達風格,或者有什么意見,歡迎向我反饋.


    前言:本文主要討論現在網傳很廣的單線程函數hook 類CULHook 掛鉤代碼的致命漏洞以及設計缺陷,并給出我的解決方案.


   知識前提:您應該有windows 程序設計和C++的基本知識,以及對操作系統原理稍微了解.

     -----------人因相互學習而進步,若您發現文中有錯誤,請不吝賜教,能夠告訴我,感恩您.

    once, I saw a cpp class that realized the API hook by inline assembly  in user mode. Maybe some of you have known this class that named "CULHook" too.
However, there are some problems existed by now. One problem is that  hook method doesn't work well on multiple threads condition. And another  problem
seems not to be clear but fatal !

  This is the original code of the class CULHook:             代碼來自 <windows 程序設計> -王艷平         注: 注解見下面,可參考我的CSTAPIHook類的代碼


#include <windows.h>

class CULHook
{
public:
    CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook);
    ~CULHook();
    void Unhook();
    void Rehook();
protected:
    PROC m_pfnOrig;        
    BYTE m_btNewBytes[8];
    BYTE m_btOldBytes[8];   
    HMODULE m_hModule;
};

CULHook::CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook)
{
    // jmp eax == 0xFF, 0xE0
    BYTE btNewBytes[8] = { 0xB8, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xE0, 0x00 };
    memcpy(m_btNewBytes, btNewBytes, 8);
    *(DWORD *)(m_btNewBytes + 1) = (DWORD)pfnHook;
    m_hModule = ::LoadLibrary(pszModName);

    if(m_hModule == NULL)
    {
        m_pfnOrig = NULL;
        return;
    }
    m_pfnOrig = ::GetProcAddress(m_hModule, pszFuncName);
    if(m_pfnOrig != NULL)
    {
        DWORD dwOldProtect;
        MEMORY_BASIC_INFORMATION    mbi;                                         //1
        ::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) );
        ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect);   //2
        memcpy(m_btOldBytes, m_pfnOrig, 8);
        ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, m_btNewBytes, sizeof(DWORD)*2, NULL);
        ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0);
    }
}

CULHook::~CULHook()
{
    Unhook();
    if(m_hModule != NULL)
        ::FreeLibrary(m_hModule);
}

void CULHook::Unhook()
{
    if(m_pfnOrig != NULL)
    {
        DWORD dwOldProtect;
        MEMORY_BASIC_INFORMATION    mbi;
        ::VirtualQuery(m_pfnOrig, &mbi, sizeof(mbi));                               //1
        ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect);  //2

        ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig,
            m_btOldBytes, sizeof(DWORD)*2, NULL);

        ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0);
    }
}

void CULHook::Rehook()
{
    if(m_pfnOrig != NULL)
    {
        DWORD dwOldProtect;                                        
        MEMORY_BASIC_INFORMATION    mbi;                                         //1                       
        ::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) );                               
        ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect);    //2
        ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, m_btNewBytes, sizeof(DWORD)*2, NULL);
        ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0);
    }
}

 
一個事實:我用這個類掛鉤TerminateProcess和Process32NextW函數時,目標進程崩潰(下面你將會看到在什么情況下會失敗)
   凡是我標1的地方都有設計問題,凡是我標2的地方都有嚴重安全隱患。


   1, 首先我們先看一下這個類,有著很明顯的設計問題,我們可以看看構造函數和ReHook成員函數,有著明顯的代碼重復,一種解決方案是,把掛鉤功能放在一個成員函數中,在構造函數中調用即可。
   2, 凡是我標1 的地方完全沒有必要,我們知道VirtualProtect 的最后一個參數可以返回原來的權限,寫完內存后直接把 dwOldProtect再傳給 VirtualProtect 以恢復頁面權限屬性,而無需
      再大費周章的得到 mbi 結構.
  3, 最不容易被發現的一點,也就是我標2的地方,也就是我們應該獲取何種訪問權限,代碼中是PAGE_READWRITE, 這有問題嗎?我們不能給教科書挑錯吧,畢竟原書示例程序的卻是用這個類   攔截了Ws2_32.dll中的winsock2的 一些函數. 但是,這句有問題,要弄清楚這個問題就必須清楚這個類的原理.


  原理: 通過修把要掛鉤函數的前8個字節數據改為跳轉到我們函數的機器指令(原來的8字節保存起來),然后在我們的鉤子函數中執行我們的操作,我們要干預的動作全部結束后,再把原來       的8字節數據寫回去,再調用原函數,為了再次攔截目標函數,原函數調用完后, 要再次把原函數前8個字節寫成跳轉到我們函數的機器指令,至于為什么是8字節? 我們來看看實現這個跳轉的匯   編指令吧:


                mov eax,our_Hookfunction         //把我們函數地址裝入到eax寄存器的指令占1字節 ,我們的函數地址占4字節,  即:0xB8, 0x00, 0x00, 0x00, 0x00 
                jmp eax                                  //jmp 指令碼1字節, eax 寄存器號1字節 即: 0xFF, 0xE0, 


好了 1+4+2=7 , 按照對齊原則,最后一字節我們以0填充.
問題在哪里,我說過這個類是掛鉤單線程函數的,怎么理解, 試想這種情況:當我們修改目標函數前8個字節時,在32位系統中,,要寫完8字節(64位)得用兩個存儲周期,假如第一次寫了32位數據后,系統發生線程換,如果新線程也要調用我們要掛鉤的函數,因為這個函數我們只寫了前4個字節,后4字節還沒寫,天知道會發生什么事。假如只有一個線程會調用我們的目標函數,則萬事大吉。當然這個類本身就是掛鉤單線程函數的,我在這里說明是因為有人人問過我這個問題。

好了既然搞清楚了原理,我們就言歸正傳,分析下面這種情況:假設我們要掛鉤的目標進程中有D和W兩個線程分別只會調用fun1,fun2兩個函數,而fun1和fun2又都是dw.dll的導出函數,且在同一個頁面中,現在我們用上面的類掛鉤函數fun1,顯然fun1是單線程(D)調用的,符合單線程安全,按理說應該會成功. 難道真相就是能成功掛鉤嗎,如果是,我這篇博客就沒必要寫了.根據上面類的代碼我們來分析運行過程:首先我們把跳轉到我們函數的機器指令寫到fun1的前8個字節,首先代碼中獲取了PAGE_READWRITE權限,然后有了權限后開始寫,若只寫完前4個字節后,系統切換到線程W,假設W線程在這個時間片里沒有調用fun2,而線程W不會調用fun1,等線程切回來之后我們寫完剩下的4字節,如果是這樣則掛鉤成功,但是如果在寫了前4字節切換到W時,W調用了fun2,會發生什么,這就是我本篇博文主要的焦點了,因為fun1和fun2是在同一個頁面中,而VirtualProtect給該頁面獲取了PAGE_READWRITE權限,也許有人會認為只給fun1獲取了PAGE_READWRITE 權限,而fun2權限沒變,這是錯誤的,因為系統權限管理是以頁為單位的,VirtualProtect 會給fun1所在的所有頁都會獲取PAGE_READWRITE 權限(如果fun1的代碼橫跨兩個頁面,則這兩個頁面都會被改為PAGE_READWRITE 權限),也就是說此時fun2的權限是PAGE_READWRITE 即只能讀或寫,而不能執行,那么fun2調用將會失敗,產生非法操作,這時您的目標進程就被您成功的搞崩潰了.這也就解釋了我們用這個類掛鉤其他某些函數時,一掛鉤,目標進程就崩潰. 還有一個問題就是如果目標進程是單線程的,那么掛鉤還有沒有可能會失敗, 請讀者思考,我把答案直接告訴你,有可能!如果您實在想不到為什么可以向我反饋,我在這里說出原因主要是想讓您能夠獨立思考,授人以魚不如授人以漁.


解決方案:在VirtualProtect指定要獲取的操作權限時把PAGE_EXECUTE_WRITECOPY 或PAGE_EXECUTE_READWRITE,也就是加上EXECUTE可執行權限,就行了,到此我們的主要問題就解決了,但是別忘了你現在瀏覽的是Duwen的C++博客,所以我設計了CSTAPIHook類 意思就是 CPP Single Thread API Hook 的意思:


/************************************************************************

  Description :   SINGLE THREAD API Hook Class( CSTAPIHook)
  Notices      :   Copyright (c) Duwen
  TIME         :   4/27/2012
************************************************************************/

#ifndef _STAPIHOOK_
#define _STAPIHOOK_
#include<windows.h>

/*************************************************************
  NOTE: This C++ class is not thread safe. it's only allowed to hook SINGLE thread
  API.  once you using this class to hook multiple threads accessible API, it maybe
  lead to your whole system run abnormally.
************************************************************
*/

// CSTAPIHook (Single Thread API Hook)
class CSTAPIHook
{
public:
    CSTAPIHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook);
    ~CSTAPIHook();
    void Hook();// hook   
    void Unhook();// Cancel hook
private:
    PROC m_pfnOrig;              // Destination API address.
    BYTE m_btNewBytes[8];    // the new start 8B data of the original API .
    BYTE m_btOldBytes[8];        // the old start 8B data of the original API .
    HMODULE m_hModule;      // DLL module handle.
};
#endif 
#include "stdafx.h"
#include "STAPIHOOK.h"

CSTAPIHook::CSTAPIHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook)
{
    // jmp eax == 0xFF, 0xE0
    BYTE btNewBytes[8] = { 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00 };
    memcpy(m_btNewBytes, btNewBytes, 8);
    //save our hook function address to btNewBtytes[1]~ btNewBtytes[4]
    *((DWORD *)(m_btNewBytes + 1)) = reinterpret_cast<DWORD>(pfnHook);

    // Loading dll module.
    m_hModule = ::LoadLibraryA(pszModName);
    if(m_hModule == NULL)
    {
        m_pfnOrig = NULL;
        return;
    }
    m_pfnOrig =(PROC)(::GetProcAddress(m_hModule, pszFuncName));

    // Revising the original  8B data of the hook_function start entry.
    if(m_pfnOrig != NULL)
        Hook();
}

void CSTAPIHook:: Hook()
{
    DWORD dwOldProtect=0;
    ::VirtualProtect((void *)m_pfnOrig, 8, PAGE_EXECUTE_WRITECOPY, &dwOldProtect);
     memcpy(m_btOldBytes,(void *) m_pfnOrig, 8);// Save the original 8B data.
   
// Write the new 8B data to the hook_function entry .
    ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, m_btNewBytes, 8, NULL);
    //Recover the page protection property.
    ::VirtualProtect((void*)m_pfnOrig,8, dwOldProtect, 0);

}


CSTAPIHook::~CSTAPIHook()
{
    Unhook();
    if(m_hModule != NULL)
        ::FreeLibrary(m_hModule);
}

void CSTAPIHook::Unhook()
{
    if(m_pfnOrig != NULL)
    {
        DWORD dwOldProtect;
        ::VirtualProtect(m_pfnOrig, 8, PAGE_EXECUTE_WRITECOPY, &dwOldProtect);
        // write the original 8B data
        ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, m_btOldBytes, 8, NULL);
        ::VirtualProtect(m_pfnOrig, 8, dwOldProtect , 0);
    }
}

/*********************END FILE******************************/

上面的代碼我給您使用以及傳播的權利,但我不希望以后有人說我是在那里抄的xx的,所以轉載或使用請說明Copyright (c) Duwen,請您尊重原創,支持原創.也希望廣大網友支持.
posted on 2012-05-08 20:41 demons 閱讀(1763) 評論(0)  編輯 收藏 引用 所屬分類: Program in Windows

<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(1)

隨筆分類

隨筆檔案

文章分類

文章檔案

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美在线视频一区| 亚洲欧美日韩国产综合| 亚洲人成人99网站| 午夜精品久久久久久久蜜桃app| 欧美韩日一区二区| 久久99伊人| 国产欧美一区二区白浆黑人| 老巨人导航500精品| 久久国产精品一区二区| 国产精品福利影院| 99国内精品久久| 欧美激情一区二区久久久| 久久久福利视频| 国产一区视频观看| 久久精品男女| 久久国产精品久久w女人spa| 国产亚洲精品久久久久动| 欧美在线观看视频在线| 亚洲欧美日韩精品综合在线观看| 国产精品久久久久av| 亚洲先锋成人| 亚洲免费中文字幕| 国产亚洲精品综合一区91| 久久精品国产免费| 久久精品国产精品亚洲综合| 国产亚洲综合性久久久影院| 久久婷婷蜜乳一本欲蜜臀| 久久另类ts人妖一区二区| 在线观看三级视频欧美| 欧美成人性网| 欧美韩日高清| 亚洲手机视频| 欧美在线一二三| 亚洲精品国产品国语在线app | 在线日韩中文字幕| 免播放器亚洲| 欧美国产精品人人做人人爱| 亚洲私人影院| 欧美一区二区三区免费视| 在线观看日韩欧美| 狼人社综合社区| 亚洲先锋成人| 影音先锋亚洲一区| 日韩视频一区二区三区| 国产精品看片你懂得| 蜜桃久久av| 欧美四级伦理在线| 久久婷婷一区| 久久影院午夜论| 亚洲一区二区三区在线视频| 欧美影院成年免费版| 亚洲另类在线视频| 性做久久久久久免费观看欧美| 亚洲电影成人| 日韩视频免费观看高清完整版| 国产精品免费在线| 欧美成人dvd在线视频| 国产精品爱久久久久久久| 久久亚洲精品网站| 国产精品久久久91| 亚洲国产裸拍裸体视频在线观看乱了 | 欧美黄色日本| 国产精品成人国产乱一区| 欧美ed2k| 国产伦精品一区二区三区视频黑人 | 另类春色校园亚洲| 欧美国产一区在线| 久久av免费一区| 欧美成人免费观看| 久久综合狠狠综合久久综青草 | 能在线观看的日韩av| 欧美在线亚洲| 欧美视频免费看| 欧美激情一区在线观看| 国产精品免费观看在线| 久久精品一区蜜桃臀影院| 午夜精品影院在线观看| 欧美精品久久一区二区| 欧美顶级大胆免费视频| 国产主播一区| 亚洲欧美日韩精品久久| 亚洲欧美三级伦理| 欧美日韩一区不卡| 亚洲精品美女在线| 亚洲另类在线视频| 欧美ed2k| 亚洲国产一二三| 亚洲精品欧美日韩| 欧美大片在线看免费观看| 欧美成人一区二区| 亚洲高清在线观看| 久久亚洲综合色一区二区三区| 久久噜噜亚洲综合| 韩国精品主播一区二区在线观看| 午夜精品视频在线观看| 欧美在线视频观看免费网站| 国产区日韩欧美| 亚洲特色特黄| 欧美中文字幕不卡| 国产日韩综合| 久久国产精品久久久久久久久久| 久久久久久久久久看片| 韩国精品久久久999| 老色鬼精品视频在线观看播放| 免费日韩av电影| 亚洲精品国产拍免费91在线| 欧美日韩精品系列| 这里只有精品在线播放| 欧美在线亚洲一区| 在线观看日韩| 欧美激情国产日韩精品一区18| 亚洲精品视频免费观看| 日韩午夜视频在线观看| 欧美日韩一区二区三区高清| 亚洲一区二区免费看| 久久精品中文字幕一区二区三区| 精品成人一区| 欧美日韩国产免费观看| 亚洲欧美日本日韩| 农夫在线精品视频免费观看| 亚洲精品一区二区三区四区高清| 欧美日韩专区在线| 欧美一区二区三区免费看| 亚洲第一精品夜夜躁人人爽| 亚洲香蕉网站| 在线免费不卡视频| 欧美日韩一区二区免费在线观看 | 国产综合色一区二区三区| 久久国产免费| 亚洲黄色在线视频| 校园春色国产精品| 亚洲高清123| 国产精品免费电影| 欧美成人一品| 欧美一级久久久| 亚洲欧洲一区二区三区| 亚洲午夜av电影| 在线精品观看| 国产精品一区二区在线观看不卡| 六月天综合网| 午夜精彩国产免费不卡不顿大片| 亚洲国产日韩欧美综合久久| 欧美影院一区| 在线视频欧美精品| 在线日韩欧美视频| 国产一区二区三区在线观看免费视频 | 久久久久国产精品麻豆ai换脸| 亚洲精品久久久久久久久久久| 久久久久久久一区| 亚洲女同性videos| 亚洲另类视频| 亚洲国产欧美精品| 国产性做久久久久久| 欧美系列精品| 欧美三级视频在线观看| 欧美91福利在线观看| 欧美在线观看日本一区| 亚洲午夜av在线| 亚洲免费精彩视频| 亚洲欧洲午夜| 亚洲精品国产精品乱码不99按摩| 另类亚洲自拍| 久久深夜福利| 久久久久久久久综合| 久久国产主播| 欧美一区二视频| 亚洲欧美日韩精品综合在线观看| 一本色道久久综合亚洲二区三区| 亚洲激情一区二区三区| 亚洲第一视频网站| 亚洲高清一区二区三区| 亚洲国产精品久久久久秋霞蜜臀| 黑人巨大精品欧美一区二区| 国产欧美va欧美va香蕉在| 国产精品久线观看视频| 国产精品黄页免费高清在线观看| 欧美精品在线观看播放| 欧美高清视频在线播放| 能在线观看的日韩av| 欧美精品1区2区| 欧美日韩在线一区二区三区| 欧美日韩亚洲在线| 国产精品久久久久9999高清| 国产精品一区免费观看| 国产日韩精品一区二区三区在线| 国产欧美一区二区在线观看| 国产日韩欧美麻豆| 狠狠干综合网| 亚洲精品国产精品久久清纯直播 | 欧美成人精品影院| 欧美国产激情二区三区| 亚洲电影视频在线| 亚洲欧洲精品一区二区三区不卡 | 国产精品vvv| 国产精品久久久久一区二区三区共| 国产精品精品视频| 国产私拍一区| 亚洲高清成人| 国产精品99久久久久久白浆小说| 亚洲女性裸体视频|