前言
昨天又去测试了下数字公司的加固,顺便试了下脱壳。
按照以前的办法没搞定。
搜索现成的文章,
基本流程都是过反调试,找入口,找到加密后的code_item,解密code_item,
然后找到opcode的映射关系,还原出原始的opcode。
我对这种加固的理解是:类似cpu的多核执行的方式。也想过不用分析,
直接的通用的还原办法,不过目前没想到,似乎也没法,因为这个的确是在
自己实现的代码中执行dalvik opcode。除非能跟到dex_pc,
一、找入口
1.构造demo
按照官方文档写了一段这样的代码
对应的code_item是
android手机目前是andorid 5所以基于5的art来弄,
enter的值就是注册jni函数的入口了,没加固的时候是0x00
注:不同rom偏移偏移不一定是10*4,具体参考源码
原理是art_method jni 的入口entry_point_from_jni_
对应的源码在
http://androidxref.com/5.0.0_r2/xref/art/runtime/mirror/art_method.h
注:与dvm dvmUseJNIBridge 方法类似只是不用去hook
上传加固后得到的入口是0xa369415f
2.调试
目的是找opcode对照表,所以采用白盒的方式,不用启动的时候附加,
所以不过反调试。
打开app直接AS附加成功,br s -a 0xa369415e 设置断点后触发,
结果直接挂了,这里折腾半天,以为遇到了什么反调试,结果是lldb
在识别arm,thumb有问题。所以放弃AS还是用ida来调。
ida调试的时候需要先启动应用,再启动android_server
附加后成功下段到
二、找
code_item
这个地方本来不想dump so的,结果还是需要dump下方便分析
也根据前人的文章有个内存加载的so
1.dump so
找到debug006的开头,加载这个是1k对齐的,所以直接找很快。
找到这个内存加载文件的头了,直接可以肉眼解密,与或0x52
dump脚本,大小是猜就行了。
import idautils
import idc
import idaapi
import struct
def main(ea_start, ea_end, save_file):
print '[*]begin to dump segment'
count = 0
handle_f = open(save_file, 'wb')
for byte_addr in range(ea_start, ea_end):
count += 1
byte_value = idaapi.get_byte(byte_addr)
if count <= 340 :
handle_f.write(struct.pack('B',byte_value ^ 0x52))
else :
handle_f.write(struct.pack('B',byte_value))
handle_f.close()
hooks = idaapi.DBG_Hooks()
hooks.hook()
print '[*]script by freakish, enjoy~~'
print '[*]script finish'
ea_start = 0xA3687000
ea_end = 0xa3729408
save_file = 'd:/text.so'
main(ea_start, ea_end, save_file)
代码改自https://raw.githubusercontent.com/freakishfox/xAnSo/master/IDAScript/IDADumpMemory.py
另外一种办法是去/data/data/com.a360.reftest/.jiagu/classes.oat中去找,理论上是可以的。
3.找虚拟机入口
根据参数和返回值,sub_D930动态调试的时候的unk_A3694930就是这个虚拟机的入口了
这个函数有点大,折腾许久,根据调试和参考之前那三篇文章定位到sub_3FE74应该就是解释器入口
看到这个函数不管前面在干嘛,直接定位sub_3FF66函数了。
import idautils
import idc
import idaapi
import struct
def main(ea_start, ea_end, save_file):
print '[*]begin to dump segment'
count = 0
handle_f = open(save_file, 'wb')
for byte_addr in range(ea_start, ea_end):
count += 1
byte_value = idaapi.get_byte(byte_addr)
if count <= 340 :
handle_f.write(struct.pack('B',byte_value ^ 0x52))
else :
handle_f.write(struct.pack('B',byte_value))
handle_f.close()
hooks = idaapi.DBG_Hooks()
hooks.hook()
print '[*]script by freakish, enjoy~~'
print '[*]script finish'
ea_start = 0xA3687000
ea_end = 0xa3729408
save_file = 'd:/text.so'
main(ea_start, ea_end, save_file)
代码改自https://raw.githubusercontent.com/freakishfox/xAnSo/master/IDAScript/IDADumpMemory.py
另外一种办法是去/data/data/com.a360.reftest/.jiagu/classes.oat中去找,理论上是可以的。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)