问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

二进制固件函数锁定术-DYNAMIC

发布网友 发布时间:2024-09-29 01:37

我来回答

1个回答

热心网友 时间:2024-10-04 08:21

背景介绍

固件系统中的二进制文件依赖于特定的系统环境执行,针对固件的研究在没有足够的资金的支持下需要通过固件的模拟来执行二进制文件程序。依赖于特定硬件环境的固件无法完整模拟,需要hook掉其中依赖于硬件的函数。

LD_PRELOAD的锁定

对于特定函数的锁定技术分为动态注入锁定和静态注入锁定两种。静态注入指的是通过修改静态二进制文件中的内容来实现对特定函数的注入。动态注入则指的是在运行的过程中对特定的函数进行锁定,动态注入锁定一方面可以通过锁定PLT表或者GOT表来实现,另一方面可以通过环境变量LD_PRELOAD来实现。

在《揭秘家用路由器0dayCVE挖掘》中作者针对D-linkDIR-605L(FW_113)路由器中的Web应用程序boa,通过hook技术锁定apmib_init()和apmib_get()函数修复boa对硬件的依赖,使得qemu-static-mips可以模拟执行,在文中作者通过LD_PRELOAD环境变量实现对函数的锁定。网上针对LD_PRELOAD的锁定也有大量的描述。但是LD_PRELOAD仍旧不是普适的。

存在的问题

LD_PRELOAD环境变量的开关在编译生成ulibc的时候指定,当关闭该选项的时候,无法使用LD_PRELOAD来预加载指定的动态链接库文件。

固件的二进制文件中会将二进制文件中的Section信息去除掉,只保留下Segment的信息,使得无法通过patchelf来增加动态链接库实现锁定。patchelf支持对二进制文件的patch修改,或者添加执行过程中的链接lib。

本文方案思路

在ELF文件中,存在DYNAMICSegment,ld.so通过该段内容来加载程序运行过程中需要的lib文件,图1为在IDA中反编译后查看的DYNAMIC段的内容。

?

图1Elf32_Dyn结构体数组

DYNAMIC段介绍

dynamic段开头包含了由N个Elf32_Dyn组成的结构体,该结构体的D_tag代表了结构体的类型。d_un为通过union联合的指针d_ptr或者对应的结构体的值d_val。

typedefstruct{Elf32_Swordd_tag;union{Elf32_Wordd_val;Elf32_Addrd_ptr;}d_un;}Elf32_Dyn;

d_tag字段保存了类型的定义参数,详见ELF(5)手册。下面列出了动态链接器常用的比较重要的类型值

1-DT_NEEDED该类型的数据结构保存了程序所需要的共享库的名字相对字符串表的偏移量

2-DT_SYMTAB动态符号表的地址,对应的节名为.dynsym

3-DT_HASH符号散列表的名称,对应的节名为.hash又称为.gnu.hash

4-DT_STRTAB符号字符串表的地址,对应的节名为.dynstr

5-DT_PLTGOT全局偏移表的地址

如上各个字段对应到IDA中显示如下,d_tag字段代表了动态段的类型,当该值为1的时候。表示程序依赖的共享库的名字,其对应的d_val表示了是要加载的lib的名称在stringtable中的偏移。

共享库文件名对应的结构体的类型值为0x01,如图2所示,0x4001C4-0x4001E4保存有5个二进制文件所依赖的共享库名字,其D_VAL的值是指向stringtable的偏移量。

?

图2DT_NEEDED共享库依赖图

DYNAMIC段的定位

从二进制文件头起始定位DYNAMIC段的流程如下:

ELF_HEADER->ProgramHeader->DYNAMICProgram

ELF_HEADER中保存有ProgramHeader的偏移

?

图3ELFHeader

ProgramHeader中保存有DynamicSegment的相关结构体信息

?

图4ProgramHeader

展开该结构体,可以找到Dynamic段在文件中的偏移量0x140h

ProgramHeader结构体

DT_NEEDED伪造

动态段由dynamic的结构体数组组成,dynamic的结构体定义如下:

?

在dynamic和elf_hash之间仍存在一段空余空余可填充空间。本文利用该段空间填充,实现特定lib的加载。

?

【----帮助网安学习,所有资料加weixin:yj009991,备注“掘金”获取!】

①网安学习成长路径思维导图②60+网安经典常用工具包③100+SRC分析报告④150+网安攻防实战技术电子书⑤最权威CISSP认证考试指南+题库⑥超1800页CTF实战技巧手册⑦最新网安大厂面试题合集(含答案)⑧APP客户端安全检测指南(安卓+IOS)

本文方案实验与测试

利用dynamic和elf_hash之间的空余区域,在该区域伪造出新的dynamic的一个数组。如下图,不修改二进制文件大小,伪造增添ibcjson.so,使得二进制文件加载ibcjson.so。在ibcjson.so中编写对应的锁定函数。

?

思路:将原有的Elf32_Dyn数组元素依次后移,并在该数组的首部添加伪造的ibcjson.so,该lib的命名可以选用stringtable中的任一字符串即可。

?

核心移动代码,将Elf32_Dyn中的元素依次后移一个,dynamic段dynamic[0]元素作为要伪造填充的数据,在本文的实验中,将dynamic[0]中的value值加1。由于在MIPS下存在大小端两种架构,在小端机器上的代码解决大端架构的填充伪造时要注意大小端的转换问题。

voidmove_dynamic(char*buf){intx=0;Elf32_Dyn*dyn=(Elf32_Dyn*)buf;while(1){if(dyn[x].d_tag==0&&dyn[x].d_un.d_ptr==0){break;}x++;if(x>100){printf("Errorbreak\n");break;}}while(x--){//printf("theindexxis%x\n",x);mem_cpy(&dyn[x],&dyn[x+1],8);}dyn[x+1].d_un.d_val=b2l(l2b(dyn[x+1].d_un.d_val)+1);}

测试环境

TOTOLinkN210RE中boa程序,锁定函数参考DIR605A,锁定apmib_init以及apmib_get

该固件的ld,关闭了LD_PRELOAD程序选项,未提供/etc/ld.preload

锁定函数代码,采用了《揭秘家用路由器CVE挖掘》提供的示例代码如下,在原有的基础上,增加printf来查看显示是否锁定成功。

#include<stdio.h>#defineMIB_HW_VER0x250#defineMIB_IP_ADDR170#defineMIB_CAPTCHA0x2C1intapmib_init(void){printf("helllo");return1;}intfork(void){return0;}voidapmib_get(intcode,int*value){switch(code){caseMIB_HW_VER:*value=1;break;caseMIB_IP_ADDR:*value=1;break;caseMIB_CAPTCHA:*value=1;break;}return;}

通过mips-linux-gcc进行编译,这里注意mips-linux-gcc在编译过程中的编译文件的位置要位于参数之后(踩坑了!!!!)

mips-linux-gcc-Wall-fPIC-sharedapmib.c-oibcjson.so

通过如下代码,给原有的boa二进制文件添加一个dynamic

#include<stdio.h>#include<stdio.h>#include<stdlib.h>#include"elf.h"#definePATCH"boa_patch"intb2l(intbe){return((be>>24)&0xff)|((be>>8)&0xFF00)|((be<<8)&0xFF0000)|((be<<24));}char*buf=NULL;intl2b(intle){return(le&0xff)<<24|(le&0xff00)<<8|(le&0xff0000)>>8|(le>>24)&0xff;}staticchar*_get_interp(char*buf){intx;//CheckfortheexistenceofadynamicloaderElf_Ehdr*hdr=(Elf_Ehdr*)buf;Elf_Phdr*phdr=(Elf_Phdr*)(buf+l2b(hdr->e_phoff));printf("thephdraddressis:0x%x0x%x0x%x0x%x\n",phdr,l2b(hdr->e_phoff),buf,sizeof(hdr->e_phoff));for(x=0;x<hdr->e_phnum;x++){if(l2b(phdr[x].p_type)==PT_DYNAMIC){//Thereisadynamicloaderpresent,soloaditreturnbuf+l2b(phdr[x].p_offset);}}returnNULL;}intmem_cpy(char*src,char*dst,intlen){printf("thesrcaddris%x,%x\n",src-buf,dst-buf);for(intx=0;x<len;x++){dst[x]=src[x];}return0;}/*1234temp=2strcpy(1,2)12strcpy()*/voidmove_dynamic(char*buf){intx=0;Elf32_Dyn*dyn=(Elf32_Dyn*)buf;//Elf32_Dyntmp_dyn;//mem_cpy()while(1){if(dyn[x].d_tag==0&&dyn[x].d_un.d_ptr==0){printf("thexis%d\n",x);break;}x++;if(x>100){printf("Errorbreak\n");break;}}while(x--){//printf("theindexxis%x\n",x);mem_cpy(&dyn[x],&dyn[x+1],8);}dyn[x+1].d_un.d_val=b2l(l2b(dyn[x+1].d_un.d_val)+1);//FILE*fw=fopen("")}voidanalyse(char*buf){char*phdr_address=NULL;phdr_address=_get_interp(buf);printf("phdraddress:0x%x\n",phdr_address-buf);move_dynamic(phdr_address);}voidsave_binary(char*buf,intsize){FILE*fw=fopen(PATCH,"wb");fwrite(buf,size,1,fw);fclose(fw);}intmain(intargc,char*argv[],char*envp[]){if(argc<2){printf("notenoughargc\n");}FILE*fp=fopen(argv[1],"rb");fseek(fp,0,SEEK_END);intsize=ftell(fp);fseek(fp,0L,SEEK_SET);buf=malloc(size);fread(buf,size,1,fp);analyse(buf);save_binary(buf,size);free(buf);return0;}

Makefile如下

all:elf.hanalyse_ph.cgccanalyse_ph.c-m32-g3-oanalyse./analyseboa_real_n210

针对N210RE的测试截图如下,通过exportLD_LIBRARY_PATH使得程序加载ibcjson.so,成功锁定boa,输出helllo

?

Ubuntu下rand函数锁定测试

rand函数的头文件是stdlib.h

编写rand.c

#include<stdio.h>#include<stdlib.h>intmain(){inta=0;a=rand()%100;printf("theais%d\n",a);return0;}//gcc-m32rand.c-orand

编写rand_hook.so

#include<stdio.h>intrand(){printf("hook!\n");return100;}//gcc-fPIC-Wall-shared-m32rand_hook.c-orand_hook.so

使用LD_PRELOAD测试,成功实现对该函数的锁定

?

使用patch,针对dynamic段元素添加伪造,测试rand_patch,依赖的库文件增加ibc.so.6,ibc.so.6需要通过exportLD_LIBRARY_PATH导入ibc.so.6的文件路径

?

实现对rand的锁定

?

总结

本文通过研究二进制文件中的dynamic段,通过修改二进制文件增加依赖共享库,可以解决在模拟固件的过程时,固件缺少节信息且固件函数无法通过LD_PRELOAD锁定的问题。该方案仍有不足之处,对于ld加载共享库的依赖顺序、共享库锁定的底层原理尚未深入探究。

参考

《揭秘家用路由器0day挖掘技术》

《二进制分析实战》

更多靶场实验练习、网安学习资料,请点击这里>>

原文:https://juejin.cn/post/7104190931556892679
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
锅炉切圆直径调整 为什么我打开excel后是灰色的? 有没有什么值得推荐的投资港股的QDII基金? - 知乎 win10电脑屏幕亮度调不了怎么办 考焊工证具体怎么操作 广汽传祺是丰田技术吗 广汽传祺与广汽丰田有关系吗 怎样才能让不愿写作业的孩子听话? 上初中不写作业不想学习的孩子应该如何管教? 出生在2020年农历七月十二日的宝宝怎么取名有内涵? 多哈回合谈判各方呼吁 ctf exp是什么意思? ...时为什么把R1忽视了 也就是说和电容器串联的电阻难道不分压么?再... ...电压为什么不变?与它串联的电阻有多少个他的电压也不变吗?电阻不... 电容的电压和电流有关吗? 佳能500/4is是什么时候生产的 ...300mm f/4-5.6 III USM/DC和佳能EF-S55-250mm f/4-5.6 IS这俩个镜 ... 这三个镜头中选一款EF-S55-250mm f/4-5.6 IS II、EF70-300mm f/4-5... 佳能EF-S55-250/4-5.6 IS 镜头好?还是适马 APO AF 70-300/4-5.6 DG... EF-S 55-250mm f/4-5.6 IS可以用在500D吗? 条件成熟事情自然__会成功,写成语,是成语,急!急! 干凉皮怎么保鲜存放好一些 干凉皮如何保鲜存放好一些 自制的凉皮怎么存放不易变质? 快讯|主打潮玩科技 纯电哪吒V正式上市 售价5.99万-7.59万元 失恋痛苦难过久久走不出来的人是不是很没有出息? 你觉得你的财富在社会中处于什么水平? 如何找到年薪30万工作 数值分析原理内容简介 因为我想考厦门大学的研究生,所以想问一下有人知道厦门大学数学科学学 ... 数值分析方法基本信息 是不是中间的甲床被破坏了? 【web安全】SSRF的各种利用方式 2024年宪法学与行政法学在职研究生好考吗? 谁能帮我翻译一下这句话,(用英文说) 大王不高兴魔童哪吒怎么样 魔童哪吒技能属性详解-新手攻略-安族网 英语翻译过来的唯美句子(诗情画意,尽在短句之间) 哪吒汽车app怎么看到费充电的度数 大王不高兴手游哪吒阵容搭配推荐 哪吒属性及出装推荐-新手攻略-安族网... 大王不高兴手游哪吒装备怎么选择 哪吒装备选择推荐-新手攻略-安族网 帮忙翻译~"只有你才能让我感到安稳"翻译成英文,谢谢! 大王不高兴手游火队阵容怎么搭配 火队阵容搭配推荐-新手攻略-安族网 大王不高兴护法厉害吗 护法作用详解-高手进阶-安族网 大王不高兴太乙真人怎么样 太乙真人技能属性详解-新手攻略-安族网 大王不高兴手游敖丙技能是什么 敖丙技能属性详解-高手进阶-安族网 圆周率是怎么记住小数点后面很多位? 求《圆周率之歌》完整版... 圆周率如何记忆更方便 屋顶老是漏水,找清楚原因轻松解决 冷冻帝王蟹和活的帝王蟹区别 阿拉斯加帝王蟹的口感特点是什么? 帝王蟹的口感怎么样?