<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Linux內核跟蹤:ftrace hook入門手冊(上)

    VSole2022-05-13 13:49:55

    一、什么是ftrace

    ftrace(FunctionTracer)是Linux內核的一個跟蹤框架,它從2008年10月9日發布的內核版本2.6.27開始并入Linux內核主線[1]。官方文檔[2]中的描述大致翻譯如下:

    ftrace是一個內部跟蹤程序,旨在幫助系統的開發人員和設計人員弄清楚內核內部發生的情況。它可以用于調試或分析在用戶空間之外發生的延遲和性能問題。雖然ftrace通常被認為是函數跟蹤程序,但它實際上是幾個不同的跟蹤實用程序的框架。…

    圖1:ftrace是一個功能強大的內核函數追蹤框架[3]

    使用ftrace需要目標Linux操作系統在編譯時啟用CONFIG_FUNCTION_TRACER內核配置選項(該選項默認啟用)。此時大部分非內聯內核函數的開頭會出現一個對mcount函數(或__fentry__函數,若gcc>=4.6且為x86架構)的調用。mcount函數本身只是一個簡單的返回指令,并沒有什么實際意義,但動態ftrace框架會在啟動時將所有對mcount的調用位置都填充為nop指令,這樣一來就在這些內核函數的開頭產生了足以容納一個call指令的空白區。這個空白區可以在需要的時候被替換為對ftrace相關函數的調用,從而實現對特定內核函數的調用追蹤,而不會過度影響其它內核函數的運行性能。

    關于ftrace的詳細內部機制,受限于篇幅,本文不詳細介紹。但總之,通過ftrace框架,我們得以對大部分內核函數(尤其是各種系統調用)進行劫持,從而實現各種各樣的主機側訪問控制功能。由于不同版本的Linux內核機制差異較大,筆者在多個不同版本的CentOS和Ubuntu環境中進行了測試。如果您在實踐過程中遇到了其它環境適配的問題,不妨在評論區留言補充。

    二、經典Hook方案

    目前網絡上大多數公開的ftracehook實現方案原理上大同小異。感興趣的讀者可以參考以下鏈接:

    https://www.apriorit.com/dev-blog/546-hooking-linux-functions-2

    https://xcellerator.github.io/posts/linux_rootkits_02/

    https://github.com/ilammy/ftrace-hook/

    圖2:經典ftrace hook方案中的執行流程[4]

    適當建議有余力的讀者首先了解一下上述經典方案,但跳過這個步驟并不會過多地影響您閱讀本文的其它內容。

    三、環境準備

    開始前請注意,安裝和卸載內核模塊通常需要root權限。以下所有操作方法默認都是在root用戶下進行的,如有需要請自行添加sudo或su -c。

    3.1 安裝編譯環境

    通過yum源進行安裝:

    yum install gcc kernel-devel-$(uname -r)
    

    成功安裝后,會在/usr/src/kernels/目錄內出現一個以當前內核版本和架構命名的子目錄,內含大量的C語言頭文件:

    圖3:正確安裝情況下的kernels目錄

    由于目前部分Linux內核函數/結構體的系統性文檔比較少,必要時可以在這里直接閱讀頭文件源碼。

    另外推薦一個網站https://elixir.bootlin.com/linux/latest/source,可以非常方便直觀地閱讀和搜索各個版本的Linux內核源碼(該網站還有glibc、grab等源碼,如果需要的話)。

    3.2 一個簡單的內核模塊

    要制作一個Linux內核模塊,項目目錄需要至少兩個文件:一個.c文件,一個Makefile文件:

    圖4:一個最簡單的Linux內核模塊項目目錄

    HelloWorld.c:

    #include static int __init Initialize(void){    pr_info("Hello, world!");    return 0;}static void __exit Finalize(void){    pr_info("Bye, world!");}module_init(Initialize);module_exit(Finalize);
    

    內核模塊并沒有一般意義上的主函數,module_init和module_exit分別設置了模塊加載和卸載時所執行的函數。

    需要注意,內核模塊應當盡量實現并設置module_init和module_exit函數,即使它們不包含實質上的業務邏輯。雖然不設置它們也可以正常構建得到.ko文件,但這可能產生一些預期之外的問題(例如,一個不定義/不設置module_exit函數的內核模塊,可能無法被正常卸載)。

    Makefile:

    obj-m += HelloWorld.oall:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    

    上文中的文件名前綴必須與.c文件一致(嚴格來說,是必須與gcc編譯所產生的.o文件名一致)。如果源文件位于子目錄內,此處也需要加上目錄前綴。

    接下來我們切換到項目目錄內,執行構建:

    make
    

    正常運行會得到如下結果:

    圖5:構建命令輸出

    此時應該會產生一個.ko文件,就是我們剛剛制作的內核模塊的可執行文件了:

    圖6:構建完畢的內核模塊

    接下來我們安裝這個新的內核模塊:

    insmod HelloWorld.ko
    

    這個命令正常運行時不會產生任何輸出。

    隨后,我們可以列出內核模塊:

    lsmod
    

    如果此前已經安裝成功,應該可以在列表中看到它:

    圖7:列出內核模塊

    類似地,我們也可以卸載已安裝的內核模塊:

    rmmod HelloWorld
    

    這個命令正常運行時也不會產生任何輸出。

    特別注意,這個命令中并不包含“.ko”后綴,也不要求必須在項目目錄內執行。此外,一個正在使用中的內核模塊是不能被卸載的(比如,某個用戶進程打開了一個通往該內核模塊的Netlink連接)。

    那么,此前代碼中通過pr_info輸出的信息跑到哪里去了呢?答案是位于Linux內核中的環緩沖區(ring buffer)。我們可以通過下面的命令訪問它:

    dmesg            /*一次性打印整個緩沖區*/dmesg --follow    /*持續打印緩沖區,直到Ctrl+C中斷*/dmesg --clear     /*清空緩沖區*/
    

    就可以看到我們的模塊此前在加載和卸載時所產生的輸出信息了:

    圖8:查看調試輸出

    除了dmesg命令外,您也可以在/var/log/messages文件中找到這些輸出。

    至此,我們就實現了一個簡單的內核模塊。

    3.3 在內核模塊中包含多個源文件

    實際操作中,我們的項目可能同時包含多個.c文件,例如這樣:

    圖9:包含多個源文件的內核模塊項目

    entry.c:

    # include "function.h"static int __init Initialize(void){    pr_info("3+5=%d!",Add(3,5));    return 0;}static void __exit Finalize(void){}module_init(Initialize);module_exit(Finalize);
    

    function.c:

    #include "function.h"int Add(int a,int b){    return a+b;}
    

    function.h:

    #ifndef LIB_FUNCTION#define LIB_FUNCTION#include int Add(int a,int b);#endif
    

    以上三個文件的內容都沒有什么特別之處。但下面的Makefile文件需要進行一些特別的調整。

    Makefile:

    obj-m += MultipleCFiles.oMultipleCFiles-objs := entry.o function.o
    all:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    clean:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    

    接下來在工作目錄內正常使用make命令進行構建,即可得到MultipleCFiles.ko:

    圖10:多個源文件構建內核模塊的運行結果

    此處需要注意以下三點:

    1、Makefile第一行“obj-m”后面的應當是一個存在對應.c文件的名稱,它將成為最終構建輸出的.ko文件的名稱。如果使用實際存在的.c文件的名稱,make命令雖然也可能不報錯,但產生的.ko模塊會無法正常運行;

    2、Makefile第二行“MultipleCFiles-objs”中“-objs”前面的部分應當與第一行中配置的名稱一致,否則make命令會報錯而無法生成.ko模塊;

    3、如果希望將函數的聲明和定義分別放置在.h文件和.c文件中(就像上面例子中的Add函數一樣),那么該函數應當加static修飾,否則它們無法被編譯器正確鏈接起來。此時雖然能夠產生.ko模塊但可能無法正常運行:

    圖11:不正確的函數static修飾導致模塊無法安裝

    四、Hook案例完整源代碼

    FTraceHook.h:

    #ifndef LIB_FTRACE_HOOK#define LIB_FTRACE_HOOK
    #include #include #include #include #include 
    //關于系統調用符號解析的版本差異處理#if LINUX_VERSION_CODE>=KERNEL_VERSION(5,7,0)static size_t kallsyms_lookup_name(const char *name){    struct kprobe kp = { .symbol_name = name };    size_t retval;
        if (register_kprobe(&kp) < 0)        return 0;    retval = (size_t)kp.addr;    unregister_kprobe(&kp);    return retval;}#endif
    //關于ftrace框架的版本差異處理#if LINUX_VERSION_CODE#define FTRACE_OPS_FL_RECURSION 0#define ftrace_regs pt_regsstatic __always_inline struct pt_regs *ftrace_get_regs(struct ftrace_regs *fregs){    return fregs;}#endif
    //關于系統調用函數簽名的版本差異處理#if defined(CONFIG_X86_64)&&(LINUX_VERSION_CODE>=KERNEL_VERSION(4,17,0))#define PTREGS_SYSCALL_STUBS 1#define SYSCALL_NAME(name) ("__x64_" name)#else#define PTREGS_SYSCALL_STUBS 0#define SYSCALL_NAME(name) (name)#endif
    //關于ret指令機器碼的架構差異處理#if defined(CONFIG_X86_64)||defined(CONFIG_X86_32)#define RET_CODE 0xC3#else#error Unsupported architecture config?#endif
    struct FTraceHook;struct FTraceHookContext;
    struct FTraceHook{    const char *Symbol;    bool (*Handler)(struct FTraceHookContext *);    size_t SysCallEntry;    struct ftrace_ops FTraceOPS;};struct FTraceHookContext{    struct FTraceHook *const Hook;    struct pt_regs *const KernelRegisters;    struct pt_regs *const UserRegisters;    size_t *const SysCallNR;    const size_t *const Arguments[6];    size_t *const ReturnValue;};
    #define FTRACE_HOOK(_symbol,_handler) {.Symbol=SYSCALL_NAME(_symbol),.Handler=(_handler)}
    struct pt_regs *GetUserRegisters(struct task_struct *task);size_t FTraceHookCallOriginal(struct FTraceHookContext *context);int FTraceHookInstall(struct FTraceHook *hook);int FTraceHookUninstall(struct FTraceHook *hook);int FTraceHookInitialize(struct FTraceHook *hooks, size_t hooks_size);int FTraceHookFinalize(struct FTraceHook *hooks, size_t hooks_size);
    #endif
    

    FTraceHook.c:

    #include "FTraceHook.h"
    static size_t RET_ADDRESS;
    //獲取用戶線程原本的寄存器保存位置struct pt_regs *GetUserRegisters(struct task_struct *task){    //用戶線程原本的寄存器保存在內核棧地址最高處,為pt_regs結構體    //實際上,我們只是想要unwind_state里面的stack_info,但有些編譯環境中不知為何會報錯:ERROR: modpost: "get_stack_info" undefined!,有知情的讀者還請不吝賜教,非常感謝    struct unwind_state state;    task = task ? : current;    unwind_start(&state, task, NULL, NULL);    return (struct pt_regs *)(((size_t)state.stack_info.end) - sizeof(struct pt_regs));}
    //代理調用原始函數size_t FTraceHookCallOriginal(struct FTraceHookContext *context){#if PTREGS_SYSCALL_STUBS    return ((asmlinkage size_t (*)(struct pt_regs *)) context->Hook->SysCallEntry)(context->UserRegisters);#else    //asmlinkage的參數,傳多了似乎沒什么影響,有switch的功夫還不如多push幾個參數咧    return ((asmlinkage size_t (*)(size_t, size_t, size_t, size_t, size_t, size_t)) context->Hook->SysCallEntry)(*context->Arguments[0], *context->Arguments[1], *context->Arguments[2], *context->Arguments[3], *context->Arguments[4], *context->Arguments[5]);#endif}
    static void notrace FTraceHookHandler(size_t ip, size_t parent_ip, struct ftrace_ops *ops, struct ftrace_regs *fregs){    struct pt_regs *kernel_regs = ftrace_get_regs(fregs);    struct pt_regs *user_regs = GetUserRegisters(NULL);#if PTREGS_SYSCALL_STUBS#define argument_regs user_regs#else#define argument_regs kernel_regs#endif#if defined(CONFIG_X86_64)#define INSTRUCTION_POINTER kernel_regs->ip    struct FTraceHookContext context =    {        .Hook = container_of(ops, struct FTraceHook, FTraceOPS),        .KernelRegisters = kernel_regs,        .UserRegisters = user_regs,        .SysCallNR = &argument_regs->ax,        .Arguments =        {            &argument_regs->di,            &argument_regs->si,            &argument_regs->dx,            &argument_regs->r10,            &argument_regs->r8,            &argument_regs->r9        },        .ReturnValue = &argument_regs->ax    };#elif defined(CONFIG_X86_32)#define INSTRUCTION_POINTER kernel_regs->ip    struct FTraceHookContext context =    {        .Hook = container_of(ops, struct FTraceHook, FTraceOPS),        .KernelRegisters = kernel_regs,        .UserRegisters = user_regs,        .SysCallNR = &argument_regs->ax,        .Arguments =        {            &argument_regs->bx,            &argument_regs->cx,            &argument_regs->dx,            &argument_regs->si,            &argument_regs->di,            &argument_regs->bp        },        .ReturnValue = &argument_regs->ax    };#else#error Unsupported architecture config?#endif    if (!context.Hook->Handler(&context)) //返回false則阻止原始函數執行(直接返回到原始函數的調用方),其余情況不需要特殊操作,任由ftrace框架恢復執行流程即可        INSTRUCTION_POINTER = RET_ADDRESS;}
    int FTraceHookInstall(struct FTraceHook *hook){    int err;
        //使用kallsyms_lookup_name()在內核內存中查找地址。    hook->SysCallEntry = kallsyms_lookup_name(hook->Symbol);    if (!hook->SysCallEntry)    {        pr_err("[FTraceHook] Unresolved symbol: %s", hook->Symbol);        return ENOENT;    }    //我們的hook子程并不是通過修改ip跳轉過去的,可以使用ftrace自帶的防遞歸,而且實測效率還不錯    hook->FTraceOPS.func = FTraceHookHandler;    hook->FTraceOPS.flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY | FTRACE_OPS_FL_RECURSION;
        err = ftrace_set_filter_ip(&hook->FTraceOPS, hook->SysCallEntry, 0, 0);    if (err)    {        pr_err("[FTraceHook] ftrace_set_filter_ip() failed: %d", err);        return err;    }
        err = register_ftrace_function(&hook->FTraceOPS);    if (err)    {        pr_err("[FTraceHook] register_ftrace_function() failed: %d", err);        return err;    }
        pr_info("[FTraceHook] Installed hook '%s': %d", hook->Symbol, err);    return err;}
    int FTraceHookUninstall(struct FTraceHook *hook){    int err;
        //注意與安裝過程相反的順序    err = unregister_ftrace_function(&hook->FTraceOPS);    if (err)    {        pr_err("[FTraceHook] unregister_ftrace_function() failed: %d", err);        return err;    }
        err = ftrace_set_filter_ip(&hook->FTraceOPS, hook->SysCallEntry, 1, 0);    if (err)    {        pr_err("[FTraceHook] ftrace_set_filter_ip() failed: %d", err);        return err;    }
        pr_info("[FTraceHook] Uninstalled hook '%s': %d", hook->Symbol, err);    return err;}
    int FTraceHookInitialize(struct FTraceHook *hooks, size_t hooks_size){    int err = 0;    size_t i;
        //隨便找一個ret指令的地址,基本上就用當前函數尾部的ret就好;如果求穩(比如擔心當前函數內存在復雜的跳轉等),可以另外定義一個空函數,注意避免選取內聯函數    RET_ADDRESS = (size_t)FTraceHookInitialize;    while (* (unsigned char *) RET_ADDRESS != RET_CODE)        ++RET_ADDRESS;
        //安裝鉤子    for (i = 0; i < hooks_size && !err; ++i)        err = FTraceHookInstall(hooks + i);
        return err;}int FTraceHookFinalize(struct FTraceHook *hooks, size_t hooks_size){    int err = 0;    size_t i;
        for (i = 0; i < hooks_size; ++i)        err = FTraceHookUninstall(hooks + i);
        return err;}
    

    Entry.c:

    #include #include 
    #include "FTraceHook.h"
    MODULE_LICENSE("GPL");//使用ftrace的模塊必須是GPL License,不然不能編譯MODULE_VERSION("0.01");
    static int ReturnSwitch = 0;static bool MySysExecve(struct FTraceHookContext *context){    char filename[256];//用kmalloc+kfree也是可以的,但棧容量允許的情況下,時間效率還是局部變量比較快        //輸出第一個參數值    if (strncpy_from_user(filename, (char *)*context->Arguments[0], sizeof(filename)) >= 0)        pr_info("[FTraceHook] PID %u calling sys_execve: %s", current->pid, filename);
        //輪流測試兩種方法來恢復原系統調用流程    if (++ReturnSwitch % 2)    {        //模擬經典方案的機制,代理調用原始函數        *context->ReturnValue = FTraceHookCallOriginal(context);        pr_info("[FTraceHook] execve() return: %ld", *context->ReturnValue);        return false;//中止系統調用    }    else    {        //優化方案的新機制,不重新push參數而直接恢復原系統調用流程,但此時無法獲取原系統調用流程的返回值        return true;    }}
    static struct FTraceHook GlobalHooks[] ={    FTRACE_HOOK("sys_execve", MySysExecve)};
    static int __init Initialize(void){    int err = FTraceHookInitialize(GlobalHooks, ARRAY_SIZE(GlobalHooks));    if(err)        pr_err("[FTraceHook] Failed to initialize ftrace hooks...");    return err;}static void __exit Finalize(void){    if(FTraceHookFinalize(GlobalHooks, ARRAY_SIZE(GlobalHooks)))        pr_err("[FTraceHook] Failed to finalize ftrace hooks...");}
    module_init(Initialize);module_exit(Finalize);
    

    Makefile:

    obj-m += FTraceHookExample.oFTraceHookExample-objs := Entry.o FTraceHook.o
    all:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    clean:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    

    運行效果:

    圖12:完整運行效果展示

    五、對經典方案的優化

    實際上,上面的代碼也參考自經典方案[4][5][6]中的內容,但進行了一些優化,比較重要的部分包括:

    1. 由于Linux內核4.17版本前后的系統調用函數簽名不同,經典方案中需要通過條件編譯的方式為每個hook定義兩個功能相同但簽名不同的hook子程:
    2. 如果hook子程本身邏輯簡單、數量少倒還好,否則每個hook子程都要寫兩份,實際使用中非常不便;
    3. 經典方案(至少前述三個參考鏈接實現)中大多沒有考慮不同位寬/架構的寄存器差異:
    4. 例如,hook子程中始終讀取pt_regs的成員di作為第一個參數,這在x86_64架構下沒有問題,但對x86_32(應為bx)、arm(應為uregs[0])等架構則是不適用的;
    5. 但是,如果在每個hook子程中都進行條件編譯,實際使用中也是非常不便的;
    6. 經典方案通過在回調函數(ftrace_set_filter_ip的第二個參數)中修改原始系統調用的ip(x86架構的指令指針寄存器,不是網際協議,后文皆同不再另行說明)來使得執行流程跳轉到hook子程,因此hook子程的函數簽名必須與原始系統調用一致:
    7. 這導致hook子程中需要系統調用參數之外的信息時邏輯變得很復雜,hook子程通常需要提前將一些必要的信息(例如,原始函數的真實地址等)通過另外的機制保存或傳遞,而無法封裝框架統一提供;
    8. 除此之外,對多個不同的系統調用使用同一個hook子程也會比較麻煩(因為不易確定原始系統調用函數的地址以進行代理,可能需要通過系統調用號重新查表等),尤其是對于業務上希望監控大量系統調用的場景;
    9. 如果hook子程中需要調用原始函數,通常需要將調用參數重新入棧(Linux系統調用多有asmlinkage修飾,即全部參數通過堆棧傳遞而不使用fastcall),而不易讓執行流程直接恢復到原始函數中。這將導致少許額外開銷,尤其是對于4.17以前的內核版本。
    10. 修改ip的跳轉方法導致經典方案中對hook子程的執行發生在ftrace相關函數返回之后(而非ftrace相關函數棧內),因此ftrace自帶的防遞歸功能無法作用于經典方案。為此,經典方案中自行實現了兩套防遞歸方法,但它們看上去都不是非常完善:
    11. 第一種方法通過within_module檢查直接調用方是否位于當前模塊中,這對于涉及多個模塊的調用(hook子程位于模塊A中,A調用了模塊B的函數,而模塊B嘗試調用被hook的原始函數)可能是不完善的;
    12. 第二種方法在執行遞歸調用時跳過系統調用開頭的“空白區”,這意味著需要對于所有調用原始函數的代碼進行修改。這不僅實現起來比較麻煩,而且同樣面臨多個模塊間調用時可能不完善的問題(因為難以修改其它模塊對原始函數的調用);
    13. (實現細節)關于FTRACE_OPS_FL_RECURSION標志的使用可能有誤
    14. ftrace框架的防遞歸選項在內核版本5.11前后發生了變化:
    15. 在5.10.113及以前版本中,默認會添加防遞歸檢查,除非ftrace_ops.flags設置了FTRACE_OPS_FL_RECURSION_SAFE標志;
    16. 而從5.11rc1開始,默認不會添加防遞歸檢查,除非ftrace_ops.flags設置了FTRACE_OPS_FL_RECURSION標志;
    17. 因此,這實際上是兩個功能相反的標志選項。第一個經典方案[4]中“#define FTRACE_OPS_FL_RECURSIONFTRACE_OPS_FL_RECURSION_SAFE”的寫法可能是不正確的,而第二個經典方案[5]沒有對這個標志進行版本差異處理;
    18. 不過,因為經典方案并不需要ftrace框架提供防遞歸檢查,所以這個錯誤應該不會造成什么實質上的影響。

    連同這些優化的細節在內,本系列的下一篇文章中會著重講解上述代碼實現的各個細節原理。

    六、后記

    更多前沿資訊,還請繼續關注綠盟科技研究通訊。

    如果您發現文中描述有不當之處,還請留言指出。在此致以真誠的感謝~

    參考文獻

    1. KERNELNEWBIES.ORG. Linux kernel 2.6.27 [J/OL]2008,
    2. https://kernelnewbies.org/Linux_2_6_27.
    3. ROSTEDT S. ftrace - Function Tracer [J/OL]2008,
    4. https://www.kernel.org/doc/Documentation/trace/ftrace.txt.
    5. YEMELIANOV A. Kernel Tracing with Ftrace[J/OL] 2017,
    6. https://blog.selectel.com/kernel-tracing-ftrace/.
    7. ALEXEY LOZOVSKY S S. Hooking Linux KernelFunctions, Part 2: How to Hook Functions with FtraceIt [J/OL] 2018,
    8. https://www.apriorit.com/dev-blog/546-hooking-linux-functions-2.
    9. PHILLIPS H. Linux Rootkits Part 2: Ftrace and Function Hooking [J/OL] 2020,
    10. https://xcellerator.github.io/posts/linux_rootkits_02/.
    11. OLEKSII LOZOVSKYI M G, KRZYSZTOF ZDULSKI.ftrace-hook [J/OL] 2021,
    12. https://github.com/ilammy/ftrace-hook/.
    函數調用linux系統
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    又一天,又一個針對 Linux 系統的惡意軟件威脅!NoaBot和Mirai之間的一個顯著區別是,僵尸網絡不是針對DDoS攻擊,而是針對連接SSH連接的弱密碼來安裝加密貨幣挖掘軟件。
    陳馳 ,2017年加入美團,目前主要負責IDC服務器的檢測防御產品研發,完善服務器側縱深防御體系建設。 楊一 ,2017年加入美團,目前主要負責HIDS主機安全產品研發工作。 胡鑫博 ,2021年加入美團,目前主要負責HIDS Agent的研發。 前言
    RCE系統交互條件與受限環境下的利用
    Shawn the R0ck 寫道:我們很高興地介紹 VED-eBPF,這是一種創新的概念驗證實現,展示了 eBPF(擴展伯克利數據包過濾器)技術在為 Linux 系統提供強大的內核安全監控和漏洞檢測方面的能力。VED-eBPF 利用 eBPF 的功能,提供對內核漏洞和 Rootkit 的運行時分析和檢測。開源版本使用 AGPLv3 許可證發布。
    Seccomp BPF與容器安全
    2022-07-17 10:07:03
    本文詳細介紹了關于seccomp的相關概念,包括seccomp的發展歷史、Seccomp BPF的實現原理以及與seccomp相關的一些工具等。此外,通過實例驗證了如何使用seccomp bpf 來保護Docker的安全。
    文中使用的示例代碼可以從 這里 獲取。的功能是在終端打印出hello這6個字符(包括結尾的?編譯它們分別生成libtest.so和?存在嚴重的內存泄露問題,每調用一次say_hello函數,就會泄露1024字節的內存。
    隨著智能家居技術的廣泛應用,智能家居作為物聯網技術在家居領域的典型應用得到了迅速的發展。然而,智能家居設備中存在的安全缺陷將直接威脅用戶的隱私安全甚至是生命財產安全,因此,針對智能家居的安全分析技術逐漸成為當前研究熱點。
    前言最近一段時間在研究Android加殼和脫殼技術,其中涉及到了一些hook技術,于是將自己學習的一些hook技術進行了一下梳理,以便后面回顧和大家學習。主要是進行文本替換、宏展開、刪除注釋這類簡單工作。所以動態鏈接是將鏈接過程推遲到了運行時才進行。
    在當前CTF比賽中,“偽造IO_FILE”是pwn題里一種常見的利用方式,并且有時難度還不小。
    不可中斷狀態實際上是系統對進程和硬件設備的一種保護機制。當負載存在明顯升高趨勢時,及時進行分析和調查。系統調用過程中并不會涉及虛擬內存等進程用戶態資源,也不會切換進程。因此系統調用通常稱為特權模式切換。進程是由內核管理和調度的,進程上下文切換只能發生在內核態。因此相比系統調用來說,在保存當前進程的內核狀態和CPU寄存器之前,需要先把該進程的虛擬內存,棧保存下來。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类