Linux动态库*.so函数名修改
在某些学习或者特殊需求的情况下要对linux下动态库*.so文件内部的函数名进行修改。
比如一个函数ADD(int a,int b);修改为Add(int a,int b);
通过这篇文章你将了解到在linux下动态库函数名寻址的规则,截止2024年3月linux动态库的寻址规则已经出现多种,这里不会一一介绍。这篇文章仅提供规则,并不提供修改函数名的相关代码和执行文件。如果有需要请留言沟通。
开发环境:Ubuntu20、gcc、g++、IDAPro(Windows下安装即可,版本不限)。
必备知识:ELF文件标准(linux下执行文件头)、IDApro的使用方法。
建议了解:linux 动态库加载流程(自行寻找资源,后续可能给出链接)参考文档(P73):https://paper.seebug.org/papers/Archive/refs/elf/Understanding_ELF.pdf
正文开始:
编译简单的动态库和调用代码。
以下为测试代码:其中仅有两个函数分别是ADD和MINUS的动态库代码;使用main.cpp链接api.so对这两个函数进行调用,并执行。最终再修改main.cpp对ADD的调用修改为Add,同时不编译动态库,仅对动态库的二进制文件进行修改的情况下,完成调用。
注:下列代码仅为参考,并未规范处理。编译命令见main.cpp。
//myAPI.h
//int ADD(int a, int b);
//int MINUS(int a, int b);#ifdef __cplusplus
extern "C" {
#endif// int Add(int a, int b);
int ADD(int a, int b);
int MINUS(int a, int b);#ifdef __cplusplus
}
#endif
//myAPI.cpp
#include "api.h"// int aaa(int a, int b){
int ADD(int a, int b){return a + b;
}
// int aaa(int a, int b){
// return a + b;
// }
int MINUS(int a, int b){// int c = ADD(a,b);int c = b;return a - c;
}
//main.cpp
#include "api.h"
#include <iostream>
// #include <hash.h>
// 使用hash表做编译,不写使用ELF GUN hash 或者两者兼顾// g++ -shared -fPIC -o libapi.so api.cpp -Wl,--hash-style=sysv /// -Wl,--retain-symbols-file=retain-symbols.txt
// 链接动态库生成执行文件// g++ -o main main.cpp api.h -L. -lapi
// 添加动态库路径到环境变量中// export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/.
int main(){std::cout << "1 + 1 = " << ADD(1, 1) << std::endl;std::cout << "1 - 1 = " << MINUS(1, 1) << std::endl;return 0;
}
通过上述步骤你将获得libapi.so和main两个可执行文件。并且执行main时,运行正常。
打开IDAPro,将libapi.so使用IAD进行逆向,能够查看二进制文件即可。
idx name hash_val3 __cxa_finalize 0BEA6495 000000024 _Z5MINUSii 01E5E459 000000015 _ITM_registerTMCloneTable 0B7268A5 000000016 _ITM_deregisterTMCloneTable 012F7225 000000017 _Z3ADDii 0D758CB9 000000028 __gmon_start__ 0F4D007F 00000000ida pro 提供数据如下:; ELF Hash Tableelf_hash_nbucket DCD 3elf_hash_nchain DCD 9elf_hash_bucket DCD 8, 6, 7elf_hash_chain DCD 0, 0, 0, 0, 0, 4, 5, 3, 0; ELF Symbol Table0 Elf64_Sym <0>1 Elf64_Sym <byte_300 - byte_300, 3, 0, 7, .init_proc, 0>2 Elf64_Sym <byte_300 - byte_300, 3, 0, 0x12, __dso_handle, 0>3 Elf64_Sym <aCxaFinalize - byte_300, 0x20, 0, 0, dword_0, 0> ; "__cxa_finalize"4 Elf64_Sym <aZ5minusii - byte_300, 0x12, 0, 9, _Z5MINUSii, 0x28> ; "_Z5MINUSii" ...5 Elf64_Sym <aItmRegistertmc - byte_300, 0x20, 0, 0, dword_0, 0> ; "_ITM_registerTMCloneTable"6 Elf64_Sym <aItmDeregistert - byte_300, 0x20, 0, 0, dword_0, 0> ; "_ITM_deregisterTMCloneTable"7 Elf64_Sym <aZ3addii - byte_300, 0x12, 0, 9, _Z3ADDii, 0x20> ; "_Z3ADDii" ...8 Elf64_Sym <aGmonStart - byte_300, 0x20, 0, 0, dword_0, 0> ; "__gmon_start__"; ELF String Tablebyte_300 DCB 0 ; DATA XREF: LOAD:0000000000000240↑o; LOAD:0000000000000258↑o ...aGmonStart DCB "__gmon_start__",0 ; DATA XREF: LOAD:00000000000002E8↑oaItmDeregistert DCB "_ITM_deregisterTMCloneTable",0; DATA XREF: LOAD:00000000000002B8↑oaItmRegistertmc DCB "_ITM_registerTMCloneTable",0; DATA XREF: LOAD:00000000000002A0↑oaCxaFinalize DCB "__cxa_finalize",0 ; DATA XREF: LOAD:0000000000000270↑oaZ3addii DCB "_Z3ADDii",0 ; DATA XREF: LOAD:00000000000002D0↑oaZ5minusii DCB "_Z5MINUSii",0 ; DATA XREF: LOAD:0000000000000288↑oDCB 0, 0, 0, 0, 0, 0, 0
规则:
规则:idx是直接读取 ELF Symbol Table 里面的 内容,顺序和 ELF String Table 里面的不同
hash_val 通过特定的方法计算得出。
elf_hash_nbucket 这个值编译器根据方 案计算出的,一般(总符号数/4 + 1) 在附近选择一个素数,能 够使数据更加离散。
elf_hash_nchain 这个值是符号的个数 。
elf_hash_bucket DCD 8, 6, 7
根据下表计算出的hash_val从最下面开始,第8个 0 ,接着第6个 1, 第7个是2。
elf_hash_chain DCD 0, 0, 0, 0, 0, 4, 5, 3, 0
根据下表计算出:
在计算的hash=0有 8,
计算的hash=1有 6,5,4
计算的hash=2有 7,3
因此:elf_hash_bucket[0] = 8;elf_hash_bucket[1] = 6;elf_hash_bucket[2] = 7;
elf_hash_chain[8] = 0
elf_hash_chain[6] = 5; elf_hash_chain[5] = 4; elf_hash_chain[4] = 0
elf_hash_chain[7] = 3;
对橙色部分的内容进行解释:
hash为0的只有8,结尾默认0,故hash_chain[8]=0。
hash为1的有6,5,4 结尾默认0,故hash_chain[6]=5,hash_chain[5]=4,hash_chain[4]=0
同理,hash为2的如上。
至此,你已经了解了--hash-style=sysv使用传统ELF编译动态库,hash表的生成规则了,其本质是一种快捷的链式结构。
使用十六进制编辑器,将hash表对应的函数ADD->Add,然后调整ELF hash链表。
3 __cxa_finalize 0BEA6495 000000024 _Z5MINUSii 01E5E459 000000015 _ITM_registerTMCloneTable 0B7268A5 000000016 _ITM_deregisterTMCloneTable 012F7225 000000017 _Z3Addii 0D77ACB9 000000008 __gmon_start__ 0F4D007F 00000000hash_val = 0: 8,7hash_val = 1: 6,5,4hash_val = 2: 3elf_hash_bucket DCD 8, 6, 3elf_hash_chain DCD 0, 0, 0, 0, 0, 4, 5, 0, 7
注:使用IDA获取这个表的时候,有对应值在二进制文件的偏移,可以根据偏移直接修改。这一过程修改了hash table 和 string table两部分,上面首为7的行,已经和最开始的不一致了,是通过elf_hash(string)获得到的。这个函数的实现,资源较多。稍后进行链接给出。
调整完毕,再将main.cpp和api.h两个文件的ADD->Add。如下:
//myAPI.h
//int ADD(int a, int b);
//int MINUS(int a, int b);#ifdef __cplusplus
extern "C" {
#endif// int Add(int a, int b);
int ADD(int a, int b);
int MINUS(int a, int b);#ifdef __cplusplus
}
#endif
//----------------------------------
//main.cpp
#include "api.h"
#include <iostream>
// #include <hash.h>
// 使用hash表做编译,不写使用ELF GUN hash 或者两者兼顾// g++ -shared -fPIC -o libapi.so api.cpp -Wl,--hash-style=sysv /// -Wl,--retain-symbols-file=retain-symbols.txt
// 链接动态库生成执行文件// g++ -o main main.cpp api.h -L. -lapi
// 添加动态库路径到环境变量中// export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/.
int main(){std::cout << "1 + 1 = " << Add(1, 1) << std::endl;std::cout << "1 - 1 = " << MINUS(1, 1) << std::endl;return 0;
}
此时,使用修改后的libapi.so和上述两个文件,编译,发现Add可以被正常调用。
结语:此案例中ADD->Add是函数名长度,所以可以避免下面执行的代码不做偏移修改,如果函数名长度不一致,可能导致整个动态库文件出现较大的问题。如果有兴趣,可以查找相关的资料并提交到GNU,说不定你也是对开源社区做贡献的小可爱了。这个案例对有传统ELF hash表有效,其他标准的hash表也是类似的调整方法,了解其运作原理就可以很快出结果。
参考文档(P73):https://paper.seebug.org/papers/Archive/refs/elf/Understanding_ELF.pdf
相关文章:
Linux动态库*.so函数名修改
在某些学习或者特殊需求的情况下要对linux下动态库*.so文件内部的函数名进行修改。 比如一个函数ADD(int a,int b);修改为Add(int a,int b); 通过这篇文章你将了解到在linux下动态库函数名寻址的规则,截止2024年3月linux动态库的寻址规则已经出现多种,这…...
adb shell 指令集
1.connect device连接设备: adb devices #return: List of devices attached 0123456789ABCDEF device2.连接终端 adb shell从设备拷贝文件到本地 adb pull <remote> [local] 如: adb pull /sdcard/demo.txt e:\从到本地拷贝文件到设备 adb push &…...
【电子通识】CH340C与CH340G的区别
在USB转串口电路中,网上买到的模块常常用的到是CH340或是CP2102。 但是CH340也有很多的版本,比如CH340C和CH340G,那么他们到底都有哪些差别。 环境特性 从规格书中可以看出环境特性CH340G是-40度到85度,而CH340C批号不是4开头…...
基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的吸烟检测系统(深度学习+Python代码+PySide6界面+训练数据集)
摘要:本文详细说明了如何利用深度学习开发一个用于监测吸烟行为的系统,并分享了完整的代码实现。该系统采用了先进的YOLOv8算法,同时还使用YOLOv7、YOLOv6、YOLOv5算法,并对它们进行了性能比较,呈现了不同模型的性能指…...
Apache Paimon 使用之 Lookup Joins 解析
Lookup Join 是流式查询中的一种 Join,Join 要求一个表具有处理时间属性,另一个表由lookup source connector支持。 Paimon支持在主键表和附加表上进行Lookup Join。 a) 准备 创建一个Paimon表并实时更新它。 -- Create a paimon catalog CREATE CAT…...
GO语言-切片底层探索(下)
目录 切片的底层数据结构 扩容机制 总结: 练习验证代码 这是切片的底层探索下篇,上篇地址请见:GO语言-切片底层探索(上) 在上篇我们讲解了切片的两个重要实现或者说是两个特征 切片是引用类型,会进行…...
物理隔离条件下,如何安全高效地进行内外网文件导入导出?
内外网文件导入导出通常指的是在内部网络(内网)和外部网络(外网)之间传输文件的过程。这在企业环境中尤其常见,因为内部网络通常包含敏感数据,而外部网络(如互联网)则允许更广泛的访…...
代码随想录 贪心算法-难度题目-区间问题
目录 55.跳跃游戏 45.跳跃游戏|| 452.用最少数量的箭引爆气球 435.无重叠区间 763.划分字母区间 56.合并区间 55.跳跃游戏 55. 跳跃游戏 中等 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大…...
地理数据 vs. 3D数据
在表示我们周围的物理世界时,地理空间数据和 3D 建筑数据是两个最常见的选择。 他们在各个行业和项目中发挥着至关重要的作用。 从构建数字孪生到可视化城市景观和创建沉浸式应用程序。 尽管地理空间和 3D 建筑数据有相似之处,但它们不可互换。 虽然地…...
Redis删除
一、del命令 del命令是Redis提供的一个常规的删除键的命令。它的语法如下: DEL key [key …] 其中,key是要删除的键名。可以指定多个键名,删除多个键。如果指定的键不存在,则会被忽略。 del命令会直接删除指定的键以及与之相关联…...
力扣细节题:字符串中的最大奇数
奇数只要找到第一位是奇数的即可,不是找单个数字 //即从最低位开始,找到第一位为奇数的位 //然后之前的就是需要的数字char * largestOddNumber(char * num){int i strlen(num) - 1;while(i > 0){if((num[i] - 0) % 2 1)break;i--;}//先找到低位开…...
Unity PS5开发 天坑篇 之 申请开发者与硬件部署01
腾了好几天终于把PS5开发机调试部署成功, 希望能帮到国内的开发者, 主机游戏PlayStation/Nintendo Switch都是比较闭塞的,开发者账号是必须的。 开发环境有两个部分,一是DEV Kit 开发机, TEST Kit测试机两部分组成,二是Unity的支持库(安装后…...
十四届蓝桥杯省赛Java B组 合并区域
就是将两个矩阵进行拼接,两矩阵可以旋转90 180 270 度。 因为数据比较小,所以这基本上就是一个大的枚举模拟加搜索,直接暴力求解。 import java.io.*; import java.util.*;public class Main{static int n;static int N 101;static int mo…...
SpringBoot高级
1.自动配置-Condition Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载相应的Bean 进入 SpringBoot 启动类,点击进入 run() 可以看到这个方法是有返回值的,返回值为 ConfigurableApplicationConte…...
机试:偶数分解
题目描述: 代码示例: #include <bits/stdc.h> using namespace std; int main(){ // 算法思想1:遍历小于该偶数的所有素数,存入数组中,遍历数组找出两个数之和等于偶数的数int n;cout << "输入样例" << endl;cin >> n;int nums[n];int k …...
一周学会Django5 Python Web开发-Jinja3模版引擎-安装与配置
锋哥原创的Python Web开发 Django5视频教程: 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计35条视频,包括:2024版 Django5 Python we…...
python前端开发
前端开发 快速网站开发 from flask import Flask appFlask(__name__) #创建网址/show/info 和函数index的对应关系, #访问网站,执行index()函数 app.route("/show/info") def index():return "中国联通" if __name__"__main_…...
web学习笔记(三十三)
目录 1.严格模式 1.1严格模式的概念: 1.2严格模式在语义上更改的地方: 1.3如何开启严格模式 1.4严格模式应用上的变化 2.原型链 1.严格模式 1.1严格模式的概念: 严格模式有点像es5向es6过渡而产生的一种模式,因为es6的语法…...
flask库
文章目录 flask库1. 基本使用2. 路由路径和路由参数3. 请求跳转和请求参数4. 模板渲染1. 模板变量2. 过滤器3. 测试器 5. 钩子函数与响应对象 flask库 flask是python编写的轻量级框架,提供Werkzeug(WSGI工具集)和jinjia2(渲染模板…...
专业无网设备如何远程运维?向日葵远程控制能源场景案例解析
清洁能源领域,拥有庞大的上下游产业链,涉及的相关工业设备门类多、技术覆盖全、行业应用广。在这一领域内,相关专业设备的供应商的核心竞争力除了本身产品的技术能力之外,服务也是重要的一环。 某企业作为致力于节能环保方向的气…...
AMLP框架实战:基于MACE构建高精度机器学习势函数
1. 项目概述:当机器学习势函数遇上自动化管道在计算化学和材料科学领域,我们长久以来面临着一个核心矛盾:精度与效率的权衡。密度泛函理论(DFT)能提供接近实验的精度,但计算成本高昂,通常只能处…...
【云雾效果商业级交付标准】:基于Adobe Sensei图像雾度分析报告(N=1,247张MJ生成图),锁定雾浓度≤0.38的7个关键阈值参数
更多请点击: https://intelliparadigm.com 第一章:云雾效果商业级交付标准的定义与行业意义 云雾效果在现代数字体验中已超越视觉装饰范畴,成为空间感知建模、沉浸式交互与品牌情绪传达的核心媒介。商业级交付标准并非仅关注“是否可见雾气”…...
抖音内容批量下载实战:从零开始构建个人视频资料库
抖音内容批量下载实战:从零开始构建个人视频资料库 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support.…...
Driver Store Explorer终极指南:轻松管理Windows驱动存储区,释放宝贵磁盘空间
Driver Store Explorer终极指南:轻松管理Windows驱动存储区,释放宝贵磁盘空间 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 你是否曾为Windows系统越来越慢而烦…...
独立开发者利用taotoken模型广场为不同任务选择性价比最优模型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 独立开发者利用taotoken模型广场为不同任务选择性价比最优模型 对于独立开发者而言,在有限的预算内高效完成多样化的开…...
CA-CFAR、GO-CFAR、SO-CFAR怎么选?一张图看懂三种恒虚警检测算法的适用场景与避坑指南
CA-CFAR、GO-CFAR、SO-CFAR工程选型指南:从算法原理到场景适配 雷达信号处理工程师常常面临一个经典难题:在复杂环境中如何选择合适的恒虚警检测算法?当海面杂波、多目标干扰或低信噪比条件同时出现时,CA、GO、SO三种CFAR变体的性…...
基于ESP8266与RGBDigit的Wi-Fi网络时钟:硬件设计、物联网集成与DIY实践
1. 项目概述:一个能感知环境的网络时钟如果你和我一样,对复古又带点科技感的显示设备没有抵抗力,同时又是个喜欢动手折腾的极客,那么这个项目绝对能让你在工作室或家里多一个既实用又炫酷的玩意儿。我说的就是这款基于RGBDigit数码…...
告别硬编码!在UE5 GAS中实现动态技能键位绑定:从DataAsset配置到运行时热更新的完整流程
告别硬编码!在UE5 GAS中实现动态技能键位绑定:从DataAsset配置到运行时热更新的完整流程在当代RPG游戏开发中,技能系统的灵活性和可配置性往往决定了项目的迭代效率。传统硬编码的键位绑定方式不仅增加了程序与策划的沟通成本,更在…...
yuzu模拟器:在PC上完美运行Switch游戏的终极解决方案
yuzu模拟器:在PC上完美运行Switch游戏的终极解决方案 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu 想要在电脑上体验任天堂Switch游戏的魅力吗?yuzu模拟器作为目前最成熟的开源Switch模拟…...
ComfyUI扩展生态系统的智能管家:ComfyUI-Manager全面解析
ComfyUI扩展生态系统的智能管家:ComfyUI-Manager全面解析 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various cu…...
