文章总结: 本文介绍了对某类抽取加固APP的脱壳与修复方法,作者使用DexFileVerifier::Verify等函数作为脱壳点进行dexdump,并提供了两种修复方式:使用FART工具和自编脚本。文章包含详细的代码示例和修复效果截图,证明了方法的有效性。这些技术对于移动安全研究和逆向工程具有实用价值,特别是针对无法完整dump的App场景。
综合评分: 87
文章分类: 逆向分析,移动安全,二进制安全,安全工具,实战经验
某类抽取加固APP的脱壳与修复
小白abc
看雪学苑
2020年4月6日 18:02
本文为看雪论坛优秀文章
看雪论坛作者ID:小白abc
写在前面
APP来自看雪安卓2w班3月份题目,题目主要关键点在于dex的dump和恢复,但是实际上由于这个APP的壳保护较弱,实际上如果脱壳点时机稍微晚一点,就可以完全dump下来,也不需要修复。
不过为了应对其他无法完整dump下来的App,解题时还是采用了较为一般的方法。
描述
使用至少两种方法完成对dex的dump和修复。
解题过程
>>>> 脱壳
#
选取脱壳点:
这里选取我之前总结的调用图(https://bbs.pediy.com/thread-258243.htm)中的DexFileVerifier::Verify和DexFileVerifier以及OpenFile函数与DexFile::DexFile函数作为脱壳点,在函数中插入以下dump dex的代码:
char dexfilepath[100]={0};int pid=getpid();sprintf(dexfilepath,"/sdcard/%d_%d_OpenFile.dex",(int)(size),pid);//fopenint fd=open(dexfilepath,O_CREAT|O_RDWR,0666);if(fd>0){ write(fd,base,size); close(fd);}
编译源码,刷机。
刷机成功后,安装并给予应用存储权限,然后运行App,并在sdcard目录下使用grep命令过滤dex,最终得到脱壳后的文件如下。
#
#
>>>> 修复
dump下来之后就是修复,使用FART确认是否有抽取的dex。
修复方式1
上fart.py,然后一一分析想要分析的方法。
最终修复效果:
#
#
修复方式2
我自己写了一个脚本,关键代码如下:
# -*- coding: utf-8 -*- def delblankline(): global insfilename infopen = open(insfilename, 'r',encoding="utf-8") outfopen = open(insfilename + '_out', 'w',encoding="utf-8") db = infopen.read() outfopen.write(db.replace(';','\n')) outfopen.close() infopen.close() f.close() def read_one_line(line): #print(line) frags = line.split(',') if len(frags) == 5: _name = frags[0].split(':')[1] _method_idx = int(frags[1].split(':')[1]) _offset = int(frags[2].split(':')[1]) _code_item_len = int(frags[3].split(':')[1]) _ins = frags[4].split(':')[1].replace("}\n", "") return _name,_method_idx,_offset,_code_item_len,_ins else: return '',-1,-1,-1,'' #print(dex.base64_decode()) #data = json.loads(line,encoding = 'utf-8') #print(data) class dex_method: name = '' method_idx = 0 offset = 0 code_item_len = 0 ins_raw = '' ins = b'' def __init__(self,_name,_method_idx,_offset,_code_item_len,_ins): self.ins_raw = _ins self.name,self.method_idx,self.offset,self.code_item_len,self.ins = _name,_method_idx,_offset,_code_item_len,base64.b64decode(_ins) #print(_name,_method_idx,_offset,_code_item_len,self.ins_raw) def repair_dex(self,fd): if self.offset > 0: fd.seek(self.offset, 0) if len(self.ins) == self.code_item_len: #print('reapir method = ',self.name,'repair code = ',self.ins_raw) fd.write(self.ins) def main(): init() global filename global insfilename global method_name global all_methods delblankline() dex_file = open(filename,'rb+') #bin_file = if all_methods: with open(insfilename + '_out',encoding='utf-8') as f: for line in f: _name,_method_idx,_offset,_code_item_len,_ins = read_one_line(line) method = dex_method(_name, _method_idx, _offset, _code_item_len, _ins) method.repair_dex(dex_file) else: found = False with open(insfilename + '_out',encoding='utf-8') as f: for line in f: _name,_method_idx,_offset,_code_item_len,_ins = read_one_line(line) if method_name in _name: found = True method = dex_method(_name, _method_idx, _offset, _code_item_len, _ins) print('find method = ' + method.name) method.repair_dex(dex_file) else: pass if found == False: print('don\'t find method = ',method_name) #break if __name__ == '__main__': main()
这个脚本是实现的抽取壳中空间不变的情况,使用方法和完整代码见here,程序个人完成,如果有bug,欢迎指摘。最终修复效果如下:
与@hanbingle师傅的修复脚本修复后的一致。
最后,题目见附件(附件可点击阅读原文下载)
- End –
看雪ID:小白abc
https://bbs.pediy.com/user-715334.htm
*本文由看雪论坛 小白abc 原创,转载请注明来自看雪社区。
推荐文章++++
好书推荐
﹀
﹀
﹀
公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]
戳“阅读原文”一起来充电吧!
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:看雪学苑 小白abc《某类抽取加固APP的脱壳与修复》