查看原文
其他

某类抽取加固APP的脱壳与修复

小白abc 看雪学院 2021-03-07
本文为看雪论坛优秀文章
看雪论坛作者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 原创,转载请注明来自看雪社区。


推荐文章++++

手把手教你入门V8漏洞利用

Android微信逆向--实现发朋友圈动态

病毒样本半感染型分析的方法

对宝马车载apps协议的逆向分析研究

x86_64架构下的函数调用及栈帧原理

好书推荐






公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存