利用DeepSeek实现调用libchdb.so动态连接库中的未公开导出函数

发布于:2025-07-20 ⋅ 阅读:(9) ⋅ 点赞:(0)

前文说到,可以用多种方法找到动态连接库中的导出函数,下面展示DeepSeek实现的两种调用方法。

方法一:用dlopen显式打开动态链接库文件,并用dlsym动态加载符号(需调用的函数)

#include <iostream>
#include <dlfcn.h>
#include <cstring>

typedef struct bignum_st BIGNUM;
typedef struct bn_ctx_st BN_CTX;

int main() {
    // 加载动态库
    void* lib = dlopen("libchdb.so", RTLD_LAZY);
    if (!lib) {
        std::cerr << "Error loading libchdb.so: " << dlerror() << std::endl;
        return 1;
    }

    // 声明函数指针变量
    BIGNUM* (*BN_new)() = nullptr;
    void (*BN_free)(BIGNUM*) = nullptr;
    int (*BN_dec2bn)(BIGNUM**, const char*) = nullptr;
    char* (*BN_bn2dec)(const BIGNUM*) = nullptr;
   // void (*OPENSSL_free)(void*) = nullptr;
    int (*BN_add)(BIGNUM*, const BIGNUM*, const BIGNUM*) = nullptr;
    int (*BN_mul)(BIGNUM*, const BIGNUM*, const BIGNUM*, BN_CTX*) = nullptr;
    BN_CTX* (*BN_CTX_new)() = nullptr;
    void (*BN_CTX_free)(BN_CTX*) = nullptr;

    // 逐个加载符号并检查
    if (!(BN_new = (decltype(BN_new))dlsym(lib, "BN_new"))) {
        std::cerr << "Failed to load symbol: BN_new (" << dlerror() << ")" << std::endl;
    } 
    else if (!(BN_free = (decltype(BN_free))dlsym(lib, "BN_free"))) {
        std::cerr << "Failed to load symbol: BN_free (" << dlerror() << ")" << std::endl;
    }
    else if (!(BN_dec2bn = (decltype(BN_dec2bn))dlsym(lib, "BN_dec2bn"))) {
        std::cerr << "Failed to load symbol: BN_dec2bn (" << dlerror() << ")" << std::endl;
    }
    else if (!(BN_bn2dec = (decltype(BN_bn2dec))dlsym(lib, "BN_bn2dec"))) {
        std::cerr << "Failed to load symbol: BN_bn2dec (" << dlerror() << ")" << std::endl;
    }
  //  else if (!(OPENSSL_free = (decltype(OPENSSL_free))dlsym(lib, "OPENSSL_free"))) {
  //      std::cerr << "Failed to load symbol: OPENSSL_free (" << dlerror() << ")" << std::endl;
  //  }
    else if (!(BN_add = (decltype(BN_add))dlsym(lib, "BN_add"))) {
        std::cerr << "Failed to load symbol: BN_add (" << dlerror() << ")" << std::endl;
    }
    else if (!(BN_mul = (decltype(BN_mul))dlsym(lib, "BN_mul"))) {
        std::cerr << "Failed to load symbol: BN_mul (" << dlerror() << ")" << std::endl;
    }
    else if (!(BN_CTX_new = (decltype(BN_CTX_new))dlsym(lib, "BN_CTX_new"))) {
        std::cerr << "Failed to load symbol: BN_CTX_new (" << dlerror() << ")" << std::endl;
    }
    else if (!(BN_CTX_free = (decltype(BN_CTX_free))dlsym(lib, "BN_CTX_free"))) {
        std::cerr << "Failed to load symbol: BN_CTX_free (" << dlerror() << ")" << std::endl;
    }
    else {
        // 所有符号加载成功,执行业务逻辑
        BN_CTX* ctx = BN_CTX_new();
        if (!ctx) {
            std::cerr << "Error creating BN context" << std::endl;
            dlclose(lib);
            return 1;
        }

        BIGNUM* a = BN_new();
        BIGNUM* b = BN_new();
        BIGNUM* result = BN_new();
        char* res_str = nullptr;

        if (a && b && result) {
            if (BN_dec2bn(&a, "12345678901234567890") && BN_dec2bn(&b, "98765432109876543210")) {
                if (BN_add(result, a, b)) {
                    res_str = BN_bn2dec(result);
                    std::cout << "Addition result: " << res_str << std::endl;
                   // OPENSSL_free(res_str);
                } else {
                    std::cerr << "BN_add operation failed" << std::endl;
                }

                if (BN_mul(result, a, b, ctx)) {
                    res_str = BN_bn2dec(result);
                    std::cout << "Multiplication result: " << res_str << std::endl;
                   // OPENSSL_free(res_str);
                } else {
                    std::cerr << "BN_mul operation failed" << std::endl;
                }
            } else {
                std::cerr << "Failed to parse numbers" << std::endl;
            }
        } else {
            std::cerr << "Failed to create BIGNUMs" << std::endl;
        }

        // 清理资源
       // if (res_str) OPENSSL_free(res_str);
        if (a) BN_free(a);
        if (b) BN_free(b);
        if (result) BN_free(result);
        if (ctx) BN_CTX_free(ctx);
    }

    // 关闭动态库
    dlclose(lib);
    return 0;
}

逐个加载符号并检查是为了确定不能加载的符号,便于排查,比如OPENSSL_free这个函数就不存在,需要去掉对它的调用。
编译命令行

g++ -o bn4 bn4.cpp -ldl
./bn4
Addition result: 111111111011111111100
Multiplication result: 1219326311370217952237463801111263526900

方法二:静态链接, 直接声明外部函数(假设这些函数在libchdb中已导出),因为这些函数与openssl中的函数同名,DeepSeek具有这方面的知识,所以它能正确声明。

#include <iostream>
#include <cstring>

// 声明BN函数(这些应该来自libchdb的头文件)
extern "C" {
    typedef struct bignum_st BIGNUM;
    typedef struct bn_ctx_st BN_CTX;
    
    BIGNUM* BN_new();
    void BN_free(BIGNUM*);
    int BN_dec2bn(BIGNUM**, const char*);
    char* BN_bn2dec(const BIGNUM*);
    int BN_add(BIGNUM*, const BIGNUM*, const BIGNUM*);
    int BN_mul(BIGNUM*, const BIGNUM*, const BIGNUM*, BN_CTX*);
    BN_CTX* BN_CTX_new();
    void BN_CTX_free(BN_CTX*);
    
    // 如果OPENSSL_free不可用,可以用系统的free代替
    void free(void*);
}

int main() {
    // 初始化上下文
    BN_CTX* ctx = BN_CTX_new();
    if (!ctx) {
        std::cerr << "Error creating BN context" << std::endl;
        return 1;
    }

    // 创建并初始化大数
    BIGNUM* a = BN_new();
    BIGNUM* b = BN_new();
    BIGNUM* result = BN_new();
    char* res_str =nullptr;
    if (!a || !b || !result) {
        std::cerr << "Error creating BIGNUM" << std::endl;
        goto cleanup;
    }

    // 设置十进制数值
    if (!BN_dec2bn(&a, "12345678901234567890") || !BN_dec2bn(&b, "98765432109876543210")) {
        std::cerr << "Error parsing numbers" << std::endl;
        goto cleanup;
    }

    // 执行加法运算
    if (!BN_add(result, a, b)) {
        std::cerr << "Addition failed" << std::endl;
        goto cleanup;
    }

    // 输出加法结果
     res_str= BN_bn2dec(result);
    std::cout << "Addition result: " << res_str << std::endl;
    free(res_str);  // 使用系统free代替OPENSSL_free

    // 执行乘法运算
    if (!BN_mul(result, a, b, ctx)) {
        std::cerr << "Multiplication failed" << std::endl;
        goto cleanup;
    }

    // 输出乘法结果
    res_str = BN_bn2dec(result);
    std::cout << "Multiplication result: " << res_str << std::endl;
    free(res_str);  // 使用系统free代替OPENSSL_free

cleanup:
    // 释放资源
    if (a) BN_free(a);
    if (b) BN_free(b);
    if (result) BN_free(result);
    if (ctx) BN_CTX_free(ctx);
    
    return 0;
}

编译命令行,需要提前设置环境变量,让它包含libchdb.so文件路径。

export LD_LIBRARY_PATH=/par:/usr/local/lib:/par/duck/build/src
export LIBRARY_PATH=/par:/usr/local/lib:/par/duck/build/src
g++ -o bn5 bn5.cpp -lchdb
./bn5
Addition result: 111111111011111111100
Multiplication result: 1219326311370217952237463801111263526900

这两种方法的执行速度差不多,主要时间都花在加载动态链接库上了。


网站公告

今日签到

点亮在社区的每一天
去签到