-
-
[原创]堆栈别乱用
-
发表于:
2019-12-26 20:47
8497
-
在做开发中,可能根据某些特定功能的实现,需要嵌入一段shellcode的汇编代码,当然,前提是你需要有一定的汇编基础,在实际的逆向分析中,理解汇编的指令真的不是很难,无非就是读写、比较、计算数值,操作堆栈、操作寄存器的一系列的操作,如果遇见不会的指令上网查询一下就一目了然了,但是当你真正的去实现一段汇编代码的功能时,你可能会遇见一些让你头疼的坑,当然可能这个坑就是你自己挖的,没办法你挖的你就得负责填上。
实现功能:自写arm汇编指令调用dlopen函数;
问题手机:经测试vivo/oppo、CPU骁龙660、系统Android 8.1,需要同时符合这三点要求的都会中招;
最后锁定到问题点在__dl__ZN12LinkerLogger10ResetStateEv函数中的VST1.8 {D16}, [R0@64]!指令,当执行该指令时会出发"SIGBUS"错误信号导致程序崩溃;
首先看一下错误信号"SIGBUS"的含义,通过搜索得知,该错误表示"未对其的访问" ,分析调试代码,第一个想到的就是“dlopen”的第一个参数字符串文件路径,该字符串不是4字节对齐,因此把修改字符串文件路径进行对齐,但是错误继续出现,与此同时在对函数的进一步跟踪发现,出错的__dl__ZN12LinkerLogger10ResetStateEv函数,根本未使用这个字符串文件路径,所以可以肯定是问题点不在这里,失去了线索,一度陷入迷茫中......
带着一份执着,我又调试运行了几次,发现问题每次都出现在VST1.8 {D16}, [R0@64]这条指令上,这不是一条常用指令到底什么意思呢?带着疑问去找到了答案,这是arm汇编里面的VFP浮点指令操作,该条指令的意思是把D16寄存器的值赋值到R0寄存器指向的地址中,(知识点介绍:VFP指令集操作的是高精度的浮点值,所以他的寄存器是按64位8字节方式操作的,即一个“QDWORD”值,关于VFP信息参考连接:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ic/Bcfhdhgd.html )
从上图我看一下D16寄存器的值的来源,指令为VMOV.I32 D16, #0,从指令中解析出D16寄存器的值等于“0x0000000000000000”,然后在来看一下R0寄存器值的来源,指令MOV R0, R4表示R0寄存器的值是R4寄存赋值过来的,而从指令 ADD R4, SP, #8中获得R4指令是SP+8的地址,由此可见我们R0寄存器实际指向的地址是SP+8,
从图中我们可以看出R0的地址为0xFFA1660C,那执行VST1.8 {D16}, [R0@64]指令实际上就是吧地址0xFFA1660C、0xFFA16610这两个堆栈地址指向的值置0,分析到这一步,如果是聪明的人应该就知道问题点了,谁让我笨呢!没有看出来,好吧,既然没看出来我没就用笨的方法来吧,只要努力笨鸟也会先飞的,又思考了一下,决定写个demo,正常掉一下对dlopen,在用IDA逆向跟踪一下
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-12-27 11:42
被梨树生果编辑
,原因: 脱敏处理