android加固函数抽取,[原创] 某类抽取加固APP的脱壳与修复

写在前面

APP来自看雪安卓2w班3月份题目,题目主要关键点在于dex的dump和恢复,但是实际上由于这个APP的壳保护较弱,实际上如果脱壳点时机稍微晚一点,就可以完全dump下来,也不需要修复。不过为了应对其他无法完整dump下来的APP,解题时还是采用了较为一般的方法。

描述

使用至少两种方法完成对dex的dump和修复

解题过程

脱壳

选取脱壳点

c66327031ad61fa4dea8b0e899b815f5.png

这里选取我之前总结的调用图中的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);

//fopen

int fd=open(dexfilepath,O_CREAT|O_RDWR,0666);

if(fd>0)

{

write(fd,base,size);

close(fd);

}

编译源码,刷机,

刷机成功后,安装并给予应用存储权限,然后运行app,并在sdcard目录下使用grep命令过滤dex,最终得到脱壳后的文件如下

4df55e60b556daee19beb1870aa30144.png

修复

dump下来之后就是修复,使用FART确认是否有抽取的dex,

修复方式1:

上fart.py,然后一一分析想要分析的方法

最终修复效果

3b192c570c53d8b9c47c554d08dd8f11.png

修复方式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,欢迎指摘。最终修复效果如下:

952800b63c924aa69a9b47b5a59439e5.png

与@hanbingle师傅的修复脚本修复后的一致。

最后,题目见附件

最后于 2020-4-1 12:00

被Simp1er编辑

,原因:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值