首页
社区
课程
招聘
[求助] 想在lsp内实现soinfo断链 处理失败
发表于: 2025-4-24 14:19 2326

[求助] 想在lsp内实现soinfo断链 处理失败

2025-4-24 14:19
2326

评论区指点了

在Riru里面有demo 大家可以学习一下 能读取到so_name 但无法断链 不知道哪出问题 求大佬指点

void *read_pointer(void *addr) {
    return *(void **) addr;
}

uint64_t read_ulong(void *addr) {
    return *(uint64_t *) addr;
}

char *read_utf8_string(void *addr) {
    char *str = *(char **) addr;
    return str ? strdup(str) : nullptr;
}

void *getSoInfoHead() {
    void *handle = xdl_open(GetLinkerPath(), XDL_DEFAULT);
    void *address = xdl_dsym(handle, "__dl__ZL6solist", nullptr);
    return read_pointer(address);
}

// 定义 soinfo 结构体
typedef struct soinfo soinfo_t;

struct soinfo {
    void *soinfo_addr;          // 结构地址
    void *phdr;                // 程序头
    void *base;                // 基地址
    uint64_t size;             // 大小
    void *dynamic;             // 动态段
    void *_next;               // 下一个 soinfo 地址
    char *strtab;              // 字符串表
    void *symtab;              // 符号表
    void *plt_rela;            // PLT 重定位表
    uint64_t plt_rela_count;   // PLT 重定位计数
    void *rela;                // 重定位表
    uint64_t rela_count;       // 重定位计数
    void *init_array;          // 初始化数组
    uint64_t init_array_count; // 初始化数组计数
    void *fini_array;          // 终止数组
    uint64_t fini_array_count; // 终止数组计数
    void *init_func;           // 初始化函数
    void *fini_func;           // 终止函数
    struct {
        void *l_addr;          // 链接映射地址
        char *l_name;          // 链接映射名称
    } link_map_head;           // 链接映射头
    void *load_bias;           // 加载偏移
    void *handle_;             // 句柄
};

soinfo_t *parse_soinfo(void *soinfo_addr) {
    auto *info = (soinfo_t *) malloc(sizeof(soinfo_t));
    if (!info) return nullptr;

    info->soinfo_addr = soinfo_addr;
    info->phdr = read_pointer(soinfo_addr);
    info->base = read_pointer((char *) soinfo_addr + 16);
    info->size = read_ulong((char *) soinfo_addr + 24);
    info->dynamic = read_pointer((char *) soinfo_addr + 32);
    info->_next = (char *) soinfo_addr + 40;
    info->strtab = read_utf8_string((char *) soinfo_addr + 56);
    info->symtab = read_pointer((char *) soinfo_addr + 64);
    info->plt_rela = read_pointer((char *) soinfo_addr + 104);
    info->plt_rela_count = read_ulong((char *) soinfo_addr + 112);
    info->rela = read_pointer((char *) soinfo_addr + 120);
    info->rela_count = read_ulong((char *) soinfo_addr + 128);
    info->init_array = read_pointer((char *) soinfo_addr + 152);
    info->init_array_count = read_ulong((char *) soinfo_addr + 160);
    info->fini_array = read_pointer((char *) soinfo_addr + 168);
    info->fini_array_count = read_ulong((char *) soinfo_addr + 176);
    info->init_func = read_pointer((char *) soinfo_addr + 184);
    info->fini_func = read_pointer((char *) soinfo_addr + 192);
    info->link_map_head.l_addr = (char *) soinfo_addr + 208;
    info->link_map_head.l_name = read_utf8_string((char *) soinfo_addr + 216);
    info->load_bias = read_pointer((char *) soinfo_addr + 248);
    info->handle_ = read_pointer((char *) soinfo_addr + 420);

    return info;
}

soinfo_t *next(soinfo_t *self) {
    return parse_soinfo(read_pointer(self->_next));
}

int memory_protect(void *addr, size_t len, const char *perms) {
    if (!addr || len == 0) {
        LOGE("Invalid address or length\n");
        return -1;
    }

    // 解析权限字符串
    int prot = 0;
    if (strchr(perms, 'r')) prot |= PROT_READ;
    if (strchr(perms, 'w')) prot |= PROT_WRITE;
    if (strchr(perms, 'x')) prot |= PROT_EXEC;

    // 调用 mprotect
    if (mprotect(addr, len, prot) == -1) {
        LOGE("mprotect error\n");
        return -1;
    }

    return 0;
}
// 这里获取是因为下面的跳转逻辑出错 想着调用系统方法进行删除 实则还是不行
typedef bool (*SolistRemoveSoinfoFunc)(soinfo *);

void *handle = xdl_open(GetLinkerPath(), XDL_DEFAULT);
void *func_address = xdl_dsym(handle, "__dl__Z20solist_remove_soinfoP6soinfo", nullptr);

    soinfo_t *soInfo = parse_soinfo(getSoInfoHead());
    while (true) {
        char *realPath;
        soinfo_t *_soInfo;
        try {
            _soInfo = next(soInfo);
        } catch (...) {
            break;
        }
        realPath = _soInfo->link_map_head.l_name;
        if (strstr(realPath, "zygisk_lsposed")) {

            // 抹掉前64位
            memory_protect(_soInfo->base, 64, "rw-");
            memset(_soInfo->base, 0xFF, 64);
            memory_protect(_soInfo->base, 64, "r--");
            soinfo_t *_soInfo_;

            try {
                _soInfo_ = next(_soInfo);
            } catch (...) {
                // 这里要创建一个空的指针 因为可能扫到soinfo末尾
            }

            LOGD("prev %s", soInfo->link_map_head.l_name);
            LOGD("find %s", _soInfo->link_map_head.l_name);
            LOGD("next find %s", _soInfo_->link_map_head.l_name);

            // 下面这种方式 不管用
//            uintptr_t current_value = *(uintptr_t *) soInfo->_next;
//            LOGE("%p - %p - %p", soInfo->_next, current_value, _soInfo_->soinfo_addr);
//            memory_protect(soInfo->_next, 8, "rw-");
//            *(uintptr_t *) soInfo->_next = (uintptr_t ) _soInfo_->soinfo_addr;
//            current_value = *(uintptr_t *) soInfo->_next;
//            LOGE("%p - %p - %p", soInfo->_next, current_value, _soInfo_->soinfo_addr);
//            memory_protect(soInfo->_next, 8, "r--");
            // 然后想通过直接调用系统方法的方式进行处理 也失败
            auto so_list_remove_soinfo = reinterpret_cast<SolistRemoveSoinfoFunc>(func_address);
            so_list_remove_soinfo(soInfo);

            break;

        }
        soInfo = _soInfo;
    }



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2025-4-29 09:28 被肉蚌葱鸡编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 79
活跃值: (564)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Riru里有现成的, 抄一下
2025-4-24 15:53
0
雪    币: 19
活跃值: (1333)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
无味 Riru里有现成的, 抄一下
我去看看 谢谢????佬
2025-4-24 16:25
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
挺好的
2025-4-24 23:52
0
雪    币: 1
活跃值: (813)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不懂就问, soinfo 断链是为什么做什么?
2025-5-1 12:52
1
雪    币: 244
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
从linker里可以拿到进程加载的so,断链可以让它在soinfo链表里搜索不到
2025-6-2 14:51
0
游客
登录 | 注册 方可回帖
返回