99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

x86_64運(yùn)行時(shí)動(dòng)態(tài)替換函數(shù)的hotpatch機(jī)制

Linux閱碼場 ? 來源:未知 ? 作者:李倩 ? 2018-11-26 16:32 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

晚上回去有朋友在朋友圈回復(fù)了我關(guān)于 “函數(shù)開頭5字節(jié)跳轉(zhuǎn)” 的事。今天正好要確認(rèn)一個(gè)與此相關(guān)的細(xì)節(jié),就順便又把這問題重新擼了一遍。

其實(shí)起初我也很納悶,以前不都是0x55開頭的指令嗎?怎么現(xiàn)在這種call self或者lea 0x0(%rsp),%rsp套路卻都成了慣例。…

關(guān)于5字節(jié)跳轉(zhuǎn),說的是下面的情況:

請注意函數(shù)最開頭的5個(gè)字節(jié):

可見,它實(shí)際上call的是緊接著它下面的地址,所以說這個(gè)5字節(jié)的call指令其實(shí)是 沒有用 的!

仔細(xì)看一下這5個(gè)字節(jié),思考一下它到底有什么用。

我們可以任意將它替換成 jmp $4字節(jié)相對偏移

這樣,代碼指令流就會(huì)進(jìn)入我們自己的HOOK函數(shù)里了。

當(dāng)然了,關(guān)于 “e8 00 00 00 00 callq …” 這個(gè)有很多話可以講,比如和Link相聯(lián)系的時(shí)候就比較有意思了,它可是作為一個(gè)樁指令存在。這個(gè)和HOOK無關(guān),也不再說太多。

讓我覺得最有意思的是,昨天那位朋友提到了微軟的/hotpatch編譯選項(xiàng),我大致看了一下:

/hotpatch (Create Hotpatchable Image):https://docs.microsoft.com/en-us/cpp/build/reference/hotpatch-create-hotpatchable-image?view=vs-2017

When /hotpatch is used in a compilation, the compiler ensures that first instruction of each function is at least two bytes, which is required for hot patching.

這是一個(gè)很有意思的選項(xiàng),其實(shí)編譯器提供這個(gè)機(jī)制也是舉手之勞吧,雖然簡單,但它確實(shí)為程序員HOOK運(yùn)行中的函數(shù)提供了很大的方便。

/hotpatch的實(shí)質(zhì)其實(shí)就是在函數(shù)的開頭和結(jié)尾填充了一些無關(guān)緊要的指令,方便HOOK來用自己的jmp指令覆蓋這個(gè)無關(guān)緊要的指令。比如下面是一個(gè)函數(shù)的開頭:

0x90代表一個(gè)nop指令,即 “什么也不做”的意思,如此一來,程序員便非常容易將類似下面的指令插入到函數(shù)開頭了:

無需任何額外的指令保存動(dòng)作。

既然微軟的編譯器有這個(gè)功能可用,GCC有沒有呢?看了GCC的manual,發(fā)現(xiàn)了一個(gè)-mhotpatch=x,y的選項(xiàng),但是在x86平臺(tái)不能用,還是比較不爽的。

后來發(fā)現(xiàn)了在編寫函數(shù)的時(shí)候,可以加上下面的屬性,然后編譯器就可以將其編譯成帶有填充的指令了:

那么,簡單來用一下,看看效果咯。

由于時(shí)間并不是很多,我也沒有那么多精力去應(yīng)對不斷的panic,所以這次準(zhǔn)備在用戶態(tài)搞。

由于用戶態(tài)可以直接使用mprotect函數(shù)更改內(nèi)存的使用權(quán)限,所以就不需要那個(gè)stub函數(shù)了。今天的這個(gè)例子,原理圖如下:

加上ms_hook_prologue屬性修飾的函數(shù),編譯好了之后,你會(huì)在函數(shù)最開頭兩行找到下面的廢指令:

隨意替換之就好。所以對于這個(gè)例子,上面圖示里的n的值就是5.

此外,上圖中,我們的一個(gè)指令buffer不再是一個(gè)stub函數(shù),而真的就是一塊分配的內(nèi)存,所以我們需要給它加上EXEC權(quán)限,不然會(huì)segment fault。這個(gè)在內(nèi)核模塊中是不能直接做的,因?yàn)榉峙鋷в蠩XEC權(quán)限的module_alloc并沒有導(dǎo)出,所以如若想用它,則必須通過kallsyms_lookup_name的內(nèi)省方式來做。

再一個(gè)需要注意的是,由于指令buffer是在堆上分配的,在64位系統(tǒng)上,它的位置和函數(shù)代碼的位置之差會(huì)超過4個(gè)字節(jié)界定的相對偏移,所以就不能用0xe9+4字節(jié)相對偏移來jmp了,而要通過64位絕對地址來跳轉(zhuǎn)了,指令如下:

好了,說了這么多,該上代碼了:

結(jié)果當(dāng)然是先調(diào)用自己的hook函數(shù),然后再調(diào)用原始函數(shù)咯:

為什么不用kprobe機(jī)制呢?kprobe的原理是 為了靈活性,使用int 3指令替換被hook的指令。 這樣就可以任意編寫pre/post回調(diào)函數(shù)了,但是我們也能看出來,通過int方式來hook,對效率的影響是不能忽略,特別是對于那些頻繁被調(diào)用的函數(shù),kprobe更加不可行。

kprobe非常適合做問題排查,熱點(diǎn)分析,但不好在生產(chǎn)環(huán)境跑的。

其實(shí),本文所描述的hotpatch原理還可以做的更好些,達(dá)到 在任意點(diǎn)插入自己的邏輯的目的,包括在函數(shù)的內(nèi)部。 這樣可以達(dá)到和kprobe相同的效果。當(dāng)然,這需要對運(yùn)行中的二進(jìn)制指令序列做相對周密詳細(xì)的分析。

這里還有一篇關(guān)于hotpatch的文章,比我這篇好,可以看一下:

Hotpatching a C Function on x86 :https://nullprogram.com/blog/2016/03/31/

補(bǔ)充說明一下,朋友圈有高手最新評論,讓我又知道了些新東西:

nop指令的實(shí)現(xiàn)方式有很多種,比如mov edi edi??赡芎芏嗥脚_(tái)并沒有類似獨(dú)立的0x90指令吧。不過既然有,那還是0x90純粹些。

kprobe也不全部一來int 3,只有return hook的場景才依賴int 3,其它的也可以做jmp hook。

線程安全,原子化操作也是生產(chǎn)環(huán)境必須考慮的,不然就是玩具。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4381

    瀏覽量

    64853
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1662

    瀏覽量

    50211

原文標(biāo)題:x86_64運(yùn)行時(shí)動(dòng)態(tài)替換函數(shù)的hotpatch機(jī)制

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何縮短Vivado的運(yùn)行時(shí)

    在Vivado Implementation階段,有時(shí)是有必要分析一下什么原因?qū)е?b class='flag-5'>運(yùn)行時(shí)間(runtime)過長,從而找到一些方法來縮短運(yùn)行時(shí)間。
    的頭像 發(fā)表于 05-29 14:37 ?1.5w次閱讀
    如何縮短Vivado的<b class='flag-5'>運(yùn)行時(shí)</b>間

    函數(shù)運(yùn)行時(shí)異常

    。是否有任何機(jī)構(gòu)知道什么可能導(dǎo)致運(yùn)行時(shí)錯(cuò)誤運(yùn)行時(shí)異常@ PC地址0x9D017CA0?函數(shù):在C:/Microchip/Hyrn/V2Y03B/Frrase/GFX/LIBARARI/
    發(fā)表于 03-20 13:41

    在arm64x86服務(wù)器上運(yùn)行的耗時(shí)來發(fā)現(xiàn)Docker在arm64架構(gòu)下的性能問題

    間整理成表格。通過比較相同測試用例在arm64x86機(jī)器上的運(yùn)行時(shí)間,可以發(fā)現(xiàn)潛在的性能問題。下圖即是數(shù)據(jù)表格的一部分。“Test case”豎列是測試用例所在文件和名字,“Qualcomm”列是在
    發(fā)表于 07-12 15:48

    如何為x86_64目標(biāo)編譯88W9098?

    x86_64 目標(biāo)編譯 88W9098
    發(fā)表于 04-21 08:52

    FPGA運(yùn)行時(shí)重構(gòu)的延遲隱藏機(jī)制研究與實(shí)現(xiàn)

    FPGA運(yùn)行時(shí)重構(gòu)的延遲隱藏機(jī)制研究與實(shí)現(xiàn)_劉偉
    發(fā)表于 01-07 19:08 ?0次下載

    紫金橋組態(tài)軟件新的功能_運(yùn)行時(shí)組態(tài)

    運(yùn)行時(shí)組態(tài)是組態(tài)軟件新近提出的新的概念。運(yùn)行時(shí)組態(tài)是在運(yùn)行環(huán)境下對已有工程進(jìn)行修改,添加新的功能。它不同于在線組態(tài),在線組態(tài)是在工程運(yùn)行的同時(shí),進(jìn)入組態(tài)環(huán)境,在組態(tài)環(huán)境中對工程進(jìn)行修改
    發(fā)表于 10-13 16:17 ?2次下載
    紫金橋組態(tài)軟件新的功能_<b class='flag-5'>運(yùn)行時(shí)</b>組態(tài)

    x86_64函數(shù)調(diào)用慣例及其棧幀

    從下圖可見,x86_64架構(gòu)取消了傳統(tǒng)的中斷形式的系統(tǒng)調(diào)用,使用syscall指令實(shí)現(xiàn)系統(tǒng)調(diào)用。并且存放參數(shù)的寄存器也有所變化。execve的系統(tǒng)調(diào)用號也從0xb變?yōu)榱?x3b
    的頭像 發(fā)表于 05-01 16:41 ?5426次閱讀
    <b class='flag-5'>x86_64</b><b class='flag-5'>函數(shù)</b>調(diào)用慣例及其棧幀

    基于STM32單片機(jī)通過使用宏assert_param來實(shí)現(xiàn)運(yùn)行時(shí)間檢測

    固件函數(shù)庫通過檢查庫函書的輸入來實(shí)現(xiàn)運(yùn)行時(shí)間錯(cuò)誤偵測。通過使用宏assert_param來實(shí)現(xiàn)運(yùn)行時(shí)間檢測。所有要求輸入?yún)?shù)的函數(shù)都使用這個(gè)宏。它可以檢查輸入?yún)?shù)是否在允許的范圍之內(nèi)。
    發(fā)表于 10-22 15:12 ?1574次閱讀
    基于STM32單片機(jī)通過使用宏assert_param來實(shí)現(xiàn)<b class='flag-5'>運(yùn)行時(shí)</b>間檢測

    Xilinx SDAccel開發(fā)環(huán)境在X86_64位工作站的運(yùn)行情況

    本視頻演示了SDAccel開發(fā)環(huán)境在一個(gè)標(biāo)準(zhǔn)X86_64位工作站上運(yùn)行的情況,以展示其為您所帶來的生產(chǎn)力的提升;以及該開發(fā)環(huán)境對OpenCL,C,C ++等等支持情況。該工作站包含一個(gè) Alpha Data的ADM-PCIE-7V3加速卡。
    的頭像 發(fā)表于 11-27 06:45 ?2543次閱讀

    友善之臂T4成為計(jì)算性能與X86_64不分伯仲的ARM

    一直以來,小伙伴們都有這樣的觀念,X86_64處理器的強(qiáng)項(xiàng)是每個(gè)核心的多線程能力;ARM Cortex A系列內(nèi)核處理器的強(qiáng)項(xiàng)是堆核心,一般是依靠多核而不是單核多線程。
    發(fā)表于 04-19 15:33 ?4413次閱讀

    Go運(yùn)行時(shí):4年之后

    自 2018 年以來,Go GC,以及更廣泛的 Go 運(yùn)行時(shí),一直在穩(wěn)步改進(jìn)。近日,Go 社區(qū)總結(jié)了 4 年來 Go 運(yùn)行時(shí)的一些重要變化。
    的頭像 發(fā)表于 11-30 16:21 ?1055次閱讀

    ch32v307記錄程序運(yùn)行時(shí)

    ch32v307記錄程序運(yùn)行時(shí)間 在程序開發(fā)中,很重要的一項(xiàng)任務(wù)就是對程序的運(yùn)行時(shí)間進(jìn)行評估。對于大型的程序系統(tǒng)來說,它們通常需要處理大量的數(shù)據(jù)或進(jìn)行復(fù)雜的計(jì)算操作。因此,如果程序的運(yùn)行時(shí)間過長
    的頭像 發(fā)表于 08-22 15:53 ?1281次閱讀

    Xilinx運(yùn)行時(shí)(XRT)發(fā)行說明

    電子發(fā)燒友網(wǎng)站提供《Xilinx運(yùn)行時(shí)(XRT)發(fā)行說明.pdf》資料免費(fèi)下載
    發(fā)表于 09-14 10:01 ?0次下載
    Xilinx<b class='flag-5'>運(yùn)行時(shí)</b>(XRT)發(fā)行說明

    如何保證它們?nèi)萜?b class='flag-5'>運(yùn)行時(shí)的安全?

    緊密耦合的容器運(yùn)行時(shí)繼承了主機(jī)操作系統(tǒng)的安全態(tài)勢和攻擊面。運(yùn)行時(shí)或主機(jī)內(nèi)核中的任何漏洞及其利用都會(huì)成為攻擊者的潛在切入點(diǎn)。
    的頭像 發(fā)表于 11-03 15:24 ?990次閱讀

    jvm運(yùn)行時(shí)內(nèi)存區(qū)域劃分

    JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,它是Java編程語言的運(yùn)行環(huán)境。JVM的主要功能是將Java源代碼轉(zhuǎn)換為機(jī)器代碼,并且在運(yùn)行時(shí)管理Java程序的內(nèi)存。JVM
    的頭像 發(fā)表于 12-05 14:08 ?736次閱讀