android平台arm指令学习和调试
码,这三块数据总长度为0x29e3c,使用mmap2进行申请映射内存,如下:
然后将三块数据拷贝到映射的内存上,
在此之后,数据内存排布:
AAAAAAAAA
BBBBBBBBBB
CCCCCCCCCC
爱加密还原代码前,处理了三块数据,如上。其中,“AAAAAAAAAA”数据是一组未使用过的数据,具体功能未知,长度为0x6b0;“BBBBBBBBBB”代表的是lzma压缩过的数据;“CCCCCCCCCC”代表的是拷贝函数的数据(一共拷贝三个函数的代码)。
4)修改lr,然后刷新cache,返回到mmap2得到的堆上的函数进行执行
OAD:510A4010 01 1C MOVS R1, R0 ; r0 0x4fb83e3c
LOAD:510A4012 10 1C MOVS R0, R2 ; r2 0x4fb83bd8
LOAD:510A4014 BE 46 MOV LR, R7 ; r7 0x4fb83d91
LOAD:510A4014 ; 这里对lr寄存器进行修改
LOAD:510A4016 C3 E7 B libexec___ARM_NR_cacheflush
5)再次调用mmap2,抹掉最初的“AA”、“BB”和“CC”三块数据,这样,之前执行的代码和数据将都被清零。这三块数据就被搬运到第一次调用mmap2得到的地址上,数据在内存重新做了排布。
6)解压数据:将数据解压到第二次调用mmap2清零的地址上,偏移为0x6b0。数据的解压使用的是lzma算法,解压的代码:
上图中,r4指向的lzma的解压函数,r0是待解压的数据,r1是待解压的长度,r2是解压到的地址,r3上是保存解压到的地址空间的长度的地址。Lzma的具体实现:
7)修正指定数据:解压完的数据并不是最终的代码,还需要进行修正。修正代码如下:
修正的方法是:解压后的数据从末端开始往前,每四字节为单位,如果这四字的最高个字节是低四位是0xb,则进行移位修复。(这种方法很像pe壳中解密代码后,对0xe8、0xe9、0xff25等的修复)修复代码如下:
8)修改内存属性,代码就完全解密,并可以运行了。
解密前的导出函数代码如下:
显然上图中的代码没法运行,解码后的代码如下:
解码后的代码分析
解密后的代码上边已经给出,r0传递的就是jnienv虚表指针,gdb中显示相关api在libicuil8n.so模块中,如下:
1)动态注册接口:解密后的代码主要是动态注册用于java调用的接口,如下:
2)load的实现
3)run方法的实现
gdb调试的问题:
1)Gdb在遇到bxpc;nop指令,从thumb指令切换到arm指令时,会出错,调试无法继续进行。解决方法:
http://sourceware-org.1504.n7.nabble.com/Fix-ARM-stepping-over-Thumb-mode-quot-bx-pc-quot-or-quot-blx-pc-quot-td69213.html)
2)gdb遇到如下的拷贝指令也会退出调试,解决方法是跳过这段代码的位置下断点。
LOAD:510A3F88 loc_510A3F88 ; CODE XREF: libexec_memcopy+1Ej
LOAD:510A3F88 DC 13 B1 E8 LDMIA R1!, {R2-R4,R6-R9,R12}
LOAD:510A3F8C 01 50 55 E2 SUBS R5, R5, #1 ; 这里r5不断的减少
LOAD:510A3F90 DC 13 A0 E8 STMIA R0!, {R2-R4,R6-R9,R12}
LOAD:510A3F94 FB FF FF 1A BNE loc_510A3F88
LOAD:510A3F98 D4 03 BD E8 LDMFD SP!, {R2,R4,R6-R9}
android平台arm指令学习和调 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)