Unix系列(15)--IFUNC机制初探
2024-4-8 17:13:37 Author: mp.weixin.qq.com(查看原文) 阅读量:29 收藏

创建: 2024-03-29 10:00
修改: 2024-04-08 15:40
https://scz.617.cn/unix/202403291000.txt

目录:

☆ 背景介绍
☆ 测试代码
    1) some.c
    2) ifunctest.c
☆ 整体流程框架
☆ liblzma后门
    2) 第一步Hook
    3) IFUNC机制的作用
☆ 参考资源

☆ 背景介绍

参看

《liblzma后门疑似国家级APT》

https://scz.617.cn/unix/202403290900.txt

某些版本liblzma.so被植入后门代码,被全世界的安全人员鞭尸式分析,目前已知其包含但不限于如下功能:

Command 0x00    Unknown
Command 0x01    SSH authentication bypass
Command 0x02    Execute shell command
Command 0x03    Execute shell command with specified UID/GID

即是说,不只是远程代码执行,也确有登录认证绕过。其后门协议涉及Ed448椭圆曲线签名算法,相应私钥只为作恶方所掌握。故,即便有暴露在公网的后门,除了作恶者,其他人无法利用该后门。已知相关PoC均需Patch恶意liblzma.so中Ed448公钥,仅有研究意义。

安全人员对后门功能研究得越来越深入、细致,围观即可。相比之下,我对后门第一步Hook如何完成更好奇些,后来ZYH、Lenny Wang分别回答了这个问题

本文从正常程序员角度初探IFUNC机制,与liblzma后门并非强相关,但也不是无关。

☆ 测试代码

1) some.c

/*
 * gcc -fPIC -shared -Wl,-soname,libsome.so -Wl,-m,elf_x86_64 -Wall -pipe -O0 -g3 -o libsome.so some.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

static void foo_0 ( void )
{
    printf( "call foo_0()\n" );
}

__attribute__((used))
static void foo_1 ( void )
{
    printf( "call foo_1()\n" );
}

__attribute__((used))
static void * foo_resolver ( void )
{
    printf( "call foo_resolver()\n" );
    return ( void * )&foo_0;
}

extern void foo( void ) __attribute__((ifunc("foo_resolver")));

__attribute__((constructor))
static void some_init ( int argc, char **argv, char **envp )
{
    printf( "call some_init()\n" );

}

some.c对应动态链接库libsome.so,只有名为foo的导出函数,其符号解析由foo_resolver完成,后者返回哪个函数指针,foo就对应哪个函数,foo_resolver这个符号并未导出。

常规导出函数是静态导出,链接时导出表已确定;IFUNC导出函数是动态导出,运行时由"ifunc resolver"决定导出谁,填写导出表。本例foo_resolver直接返回foo_0,实际中则是基于某种条件决定返回foo_0、foo_1中的某一个,后面会展示liblzma.so的"ifunc resolver"实现。

"ifunc resolver"的调用时机非常早期,其被调用时环境变量尚未就位,getenv()啥也取不到。换句话说,不要指望通过环境变量向"ifunc resolver"传递参数。

some_init与IFUNC机制无关,用于其他测试目的。

2) ifunctest.c

/*
 * gcc -Wall -pipe -O0 -g3 -o ifunctest ifunctest.c -L. -lsome
 *
 * LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./ifunctest
 */

#include <stdio.h>

extern void foo void );

int main int argc, char * argv[] )
{
    printf"call main()\n" );
    foo();
    foo();
    return 0;
}

ifunctest是主程序,会动态链接libsome.so,导入来自后者的foo函数,本例实际导入foo_0。

$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH FOO_RESOLVER=1 ./ifunctest
call foo_resolver()
call some_init()
call main()
call foo_0()
call foo_0()

从printf结果看出,foo_resolver甚至比some_init还要早调用,不只是"before main"、"before _start",更是"before .init_array"。

☆ 整体流程框架

用GDB调试ifunctest,大概有下面这些流程:

一些关键节点的执行顺序:

ld-linux.so e_entry
ifunc resolver
.init_array[]
normal e_entry
normal main

☆ liblzma后门

2) 第一步Hook

From ZYH & Lenny Wang

第一步Hook通过修改源码完成,原来的代码是:

/*
 * xz-5.6.0\src\liblzma\check\crc64_fast.c
 */

#ifdef CRC_USE_IFUNC
extern LZMA_API(uint64_t)
lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
        __attribute__((__ifunc__("crc64_resolve")))
;

static crc64_func_type
crc64_resolve(void)
{
    return is_arch_extension_supported()
            ? &crc64_arch_optimized : &crc64_generic;
}

liblzma.so动态导出符号lzma_crc64,加载时由crc64_resolve根据CPU情况决定该符号对应crc64_arch_optimized、crc64_generic中的某一个。crc64_resolve本身不是导出符号。

改过的代码是:

static crc64_func_type
crc64_resolve(void)
{
    /*
     * 前面多了个下划线
     */

    return _is_arch_extension_supported()
            ? &crc64_arch_optimized : &crc64_generic;
}

修改源码动作在injected.txt中。用了管道,改过的源码没有落盘,与恶意payload一起生成新的.o

3) IFUNC机制的作用

crc64_resolve是"ifunc resolver",加载liblzma.so时,会自动调用它,无需显式调用。其调用时机非常之早,比liblzma.so可能存在的.init_array[]还要早,在"catch load liblzma"命中之前就被调用了,这是一种超级"before _start"机制。换句话说,只要某个ELF直接、间接依赖liblzma.so,启动该ELF时,crc64_resolve就会得到执行机会。过去反入侵检测时会检查ELF的.init_array[],现在应该增加对"ifunc resolver"的检查,比如:

objdump -CT liblzma.so.5.6.0 | grep "g   iD"
nm -CD liblzma.so.5.6.0 | grep " i "
readelf -W --dyn-syms --demangle liblzma.so.5.6.0 | grep -E "IFUNC   GLOBAL DEFAULT"

可用IDA反汇编so,查看lzma_crc64,进而定位crc64_resolve。

☆ 参考资源

https://sourceware.org/glibc/wiki/GNU_IFUNC

xz/liblzma后门恶意代码注入方式分析 - Lenny Wang, UID(2045181921) [2024-04-03]
https://lennysec.github.io/xz-backdoor-code-injection-analysis/


文章来源: https://mp.weixin.qq.com/s?__biz=MzUzMjQyMDE3Ng==&mid=2247487247&idx=1&sn=1cc7219788ac5dca8cafb6b0a3bdc0b2&chksm=fab2cc30cdc54526e100f9cf35e7205829f73aeccd83e3245d177268231c116f119f10b4a196&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh