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

在C++中使用HOOK修改sleep函數(shù)的方法

 更新時間:2025年12月15日 09:00:19   作者:koddnty  
Hook(鉤子)是一種編程機(jī)制,它允許開發(fā)者在程序執(zhí)行的特定點(diǎn)插入自定義代碼,從而攔截、處理或修改原有的函數(shù)調(diào)用、消息傳遞或系統(tǒng)事件,本篇文章將以sleep函數(shù)為例子介紹如何在c++中使用hook修改系統(tǒng)函數(shù),需要的朋友可以參考下

HOOK是什么

Hook(鉤子)是一種編程機(jī)制,它允許開發(fā)者在程序執(zhí)行的特定點(diǎn)插入自定義代碼,從而攔截、處理或修改原有的函數(shù)調(diào)用、消息傳遞或系統(tǒng)事件。

通俗地說,Hook就像是給程序安裝了一個“監(jiān)聽器”或“攔截器”。當(dāng)目標(biāo)函數(shù)被調(diào)用時,控制權(quán)會先轉(zhuǎn)移到你的Hook代碼,你可以在執(zhí)行原有操作之前或之后插入自定義邏輯,甚至完全替換原有行為。例如游戲外 掛通過hook來對游戲運(yùn)行時用到的函數(shù)或其他API進(jìn)行修改來實(shí)現(xiàn)外 掛的功能。同時,hook也常與協(xié)程搭配使用,修改系統(tǒng)函數(shù)來為類似sleep等阻塞線程的函數(shù)添加協(xié)程的功能。

如何使用hook來修改sleep函數(shù)

下面的代碼是最簡單的hook的實(shí)現(xiàn)

#include <iostream>
#include <unistd.h>

extern "C" unsigned int sleep(unsigned int seconds)
{
    std::cout << "我們成功修改了系統(tǒng)提供的sleep函數(shù)!" << std::endl;
    return 0;
}

void test1()
{
    std::cout << "使用sleep函數(shù)睡2s"<< std::endl;
    sleep(2);
    std::cout << "sleep函數(shù)睡完了"<< std::endl;
}

調(diào)用函數(shù)test1(),程序運(yùn)行結(jié)果如下:

使用sleep函數(shù)睡2s
我們成功修改了系統(tǒng)提供的sleep函數(shù)!
sleep函數(shù)睡完了

在上面的代碼中,我們僅做了兩件事

  • 實(shí)現(xiàn)一個sleep函數(shù),與unistd.h中的sleep函數(shù)簽名一致
  • 使用extern "C"告訴C++編譯器"按C語言的方式處理這個函數(shù)"

定義一個相同簽名的sleep為什么鏈接過程中不會產(chǎn)生重定義問題呢?在鏈接器鏈接過程中,函數(shù)符號有類似強(qiáng)弱符號之分,在動態(tài)庫中的函數(shù)會被新目標(biāo)文件的函數(shù)替換,因此此處程序運(yùn)行時會運(yùn)行我們重新寫的sleep函數(shù)而不是unistd.h內(nèi)的。

至于加extern "C"的作用,在c++編譯過程中,為了區(qū)分不同的重載函數(shù),編譯器會給同名函數(shù)加入隨即字符進(jìn)行區(qū)分,我們的目的是重寫sleep函數(shù),因此要確保函數(shù)名與unistd.h中相同,通過加入extern "C"來做到這一點(diǎn)

對上述代碼的改進(jìn)

上述代碼存在很大的缺陷,最主要的是它失去了sleep函數(shù)最基本的功能。通常我們利用hook修改函數(shù)時,我們需要維持其原有功能。我們不可能真的去實(shí)現(xiàn)一個完整的sleep,但我們可以獲得原sleep的函數(shù)指針

在不同的平臺有不同的獲取庫函數(shù)指針的方法,下面時在linux平臺來獲取sleep函數(shù)指針的例子:

獲取sleep函數(shù)指針

linux為獲取庫函數(shù)指針提供了特定的函數(shù)dlsym,定義在<dlfcn.h>中。其函數(shù)簽名為:

void *dlsym(void *restrict handle, const char *restrict symbol);

dlsym返回值是函數(shù)指針,其第一個參數(shù)是指定查找的庫,第二個參數(shù)傳入函數(shù)名稱。

在hook場景中,handle參數(shù)常取RTLD_NEXT,表示跳過當(dāng)前庫查找其他庫。也就是說,當(dāng)symbol傳入"sleep"時,dlsym跳過當(dāng)前庫我們定義的sleep,找到了unistd.h定義的sleep函數(shù),并返回其函數(shù)指針。

代碼改進(jìn)

有了上邊提供的函數(shù),我們可以保存原有sleep函數(shù)并給他加點(diǎn)"小料",代碼如下:

#include <iostream>
#include <unistd.h>
#include <dlfcn.h>
using sleep_fun_type = unsigned int (*)(unsigned int seconds);

sleep_fun_type original_sleep = NULL;

extern "C" unsigned int sleep(unsigned int seconds)
{
    std::cout << "我們成功修改了系統(tǒng)提供的sleep函數(shù)!" << std::endl;
    return original_sleep(seconds);                             // <-----這里調(diào)用我們保存下來的原始的sleep
}

void test1()
{
    original_sleep = (sleep_fun_type)dlsym(RTLD_NEXT, "sleep"); // <-----這里獲得了unistd中的sleep

    std::cout << "使用sleep函數(shù)睡2s"<< std::endl;
    sleep(2);                                                   // <-----這里調(diào)用我們自己寫的sleep
    std::cout << "sleep函數(shù)睡完了"<< std::endl;
}

代碼相較于開始,只做了一點(diǎn)改進(jìn),即保存原始sleep函數(shù),并在我們自己定義的sleep函數(shù)中調(diào)用保存的原始sleep函數(shù)。

需注意的是,編譯時應(yīng)加上-ldl選項(xiàng)鏈接動態(tài)庫

總結(jié)

上述代碼仍有許多不完善的地方,實(shí)際過程中要檢查dlsym返回值是否為NULL等問題,同時代碼對初始化并不規(guī)范,可以使用下面的初始化方法(gcc編譯器),也可以使用其他更兼容的方法進(jìn)行初始化。

__attribute__((constructor)) void init_hook()       // gcc編譯器提供,main函數(shù)運(yùn)行前,庫和內(nèi)存初始化完成后運(yùn)行
{
    // 在main函數(shù)執(zhí)行前先初始化—original_sleep。
    original_sleep = (SleepFunc)dlsym(RTLD_NEXT,"sleep");
}

最后,需要注意的是,如果采用上述方法重新定義sleep,會使所有庫運(yùn)行的sleep函數(shù)都改變成我們自己定義的sleep,如果返回值與原sleep存在差異,可能導(dǎo)致一些其他的隱含問題。

以上就是在C++中使用HOOK修改sleep函數(shù)的方法的詳細(xì)內(nèi)容,更多關(guān)于C++ HOOK修改sleep函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于C++和MFC開發(fā)象棋程序

    基于C++和MFC開發(fā)象棋程序

    這篇文章主要為大家詳細(xì)介紹了基于C++和MFC開發(fā)象棋程序,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Linux系統(tǒng)下C語言中的標(biāo)準(zhǔn)IO總結(jié)

    Linux系統(tǒng)下C語言中的標(biāo)準(zhǔn)IO總結(jié)

    最近用到了C語言的標(biāo)準(zhǔn)IO庫,由于對其中的一些細(xì)節(jié)不是非常清楚,導(dǎo)致了許多Bug,花了好長時間來調(diào)試,所以在此做個筆記,這篇文章主要給大家介紹了關(guān)于Linux系統(tǒng)下C語言中標(biāo)準(zhǔn)IO的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • C++ COM編程之QueryInterface函數(shù)(一)

    C++ COM編程之QueryInterface函數(shù)(一)

    這篇文章主要介紹了C++ COM編程之QueryInterface函數(shù)(一),QueryInterface是組件本身提供對自己查詢的一個接口,需要的朋友可以參考下
    2014-10-10
  • C++11中std::future的具體使用方法

    C++11中std::future的具體使用方法

    這篇文章主要介紹了C++11中std::future的具體使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • VC雙畫布消除屏幕閃爍實(shí)例詳解

    VC雙畫布消除屏幕閃爍實(shí)例詳解

    這篇文章主要介紹了VC雙畫布消除屏幕閃爍實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C語言的循環(huán)小練習(xí)詳解

    C語言的循環(huán)小練習(xí)詳解

    這篇文章主要為大家介紹了C語言的循環(huán)小練習(xí),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • C++ Qt之halcon讀取像素項(xiàng)目過程詳解

    C++ Qt之halcon讀取像素項(xiàng)目過程詳解

    這篇文章主要介紹了C++ Qt之halcon讀取像素項(xiàng)目過程詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 詳解C++構(gòu)造函數(shù)

    詳解C++構(gòu)造函數(shù)

    這篇文章主要為大家介紹了C++構(gòu)造函數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • C++ Boost實(shí)現(xiàn)數(shù)字與字符串轉(zhuǎn)化詳解

    C++ Boost實(shí)現(xiàn)數(shù)字與字符串轉(zhuǎn)化詳解

    Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱
    2022-11-11
  • 手把手帶你學(xué)習(xí)C++的數(shù)據(jù)類型

    手把手帶你學(xué)習(xí)C++的數(shù)據(jù)類型

    這篇文章主要為大家介紹了C++的數(shù)據(jù)類型,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助,希望能夠給你帶來幫助
    2021-11-11

最新評論

衢州市| 永兴县| 池州市| 双辽市| 松潘县| 太仆寺旗| 丘北县| 印江| 镇江市| 遂溪县| 霍林郭勒市| 娄烦县| 勃利县| 沐川县| 常熟市| 图们市| 铅山县| 色达县| 卢湾区| 赤峰市| 商洛市| 靖西县| 略阳县| 新化县| 监利县| 桃园市| 博野县| 井陉县| 美姑县| 和政县| 闵行区| 旌德县| 兴国县| 浪卡子县| 方城县| 景宁| 明水县| 涿州市| 黄大仙区| 海安县| 扎鲁特旗|