Python项目练习阶段总结
前言
看了别人关于恶意代码特征提取的python程序,想自己写一个,于是有了这篇文章。
通过 apktool 可以对 apk 进行反编译,反编译后得到的目录如下图:
我们要做的是分析其中的 smali 文件并从中提取特征。
什么是smali文件
smali 文件与 Java 代码中的类有一一对应的关系(包括内部类和匿名内部类),smali 文件由Dalvik指令构成,有自己的一套规则,它的指令均是以 .开头的,一个方法由 .method开头,.end结尾。
这里是一个很详细的关于apk逆向的参考博客。
我完成的
1.重命名APK
我要做的第一步是将样本apk全部按顺序重新命名(因为在程序中调用cmd命令运行apktool对apk进行反编译时,执行反编译加壳的apk会报错,而我要删除这些apk,暂时还没有考虑用代码直接删除)。
这里导入使用了 os 模块,用到了os.path.rename()的方法。
2.反编译
然后是运行写好的反编译程序对所有样本apk进行反编译。
使用了 subprocess 模块,用到了 subprocess.call() 方法。
3.将smali文件内容汇总
一个smali文件中可能包含多个文件夹和.smali文件,其深度各不同。
一个示例如下:
对于遇到的smali文件,需要汇总到另一个指定路径的文件夹,对于非smali文件(即图中所示a b c等文件夹),接着访问此文件夹下的目录,遇到.smali文件就将其内容追加,遇到文件夹则重复上述操作。
用正则表达式去匹配.smali文件,对于遇到的文件夹,重复上述操作其实是一个递归的过程。
写一个函数递归遍历这棵树,需要传递的参数就是当前节点的路径。
起初写这个函数时遇到的问题及解决:
- 报错:NotADirectoryError: [WinError 267] 目录名称无效
原因:到达递归边界时没有直接判断是否smali文件,而是对该文件的listdir()进行遍历
解决:加上边界判断 - 情况:写这种目录访问的代码一头雾水
原因:我创建的目录层太多,导致乱了套
解决:写代码前先静下心写出大概步骤,对于目录访问,可以先在纸上画出目录的层级图,再写伪代码,最终可以写出正确的代码 - 情况:smali文件夹没有完全遍历完
原因:我在循环遍历的条件判断中加了return,最初的目的只是为了截止当前循环,并希望下一次循环还能正常进行
解决:不要轻易在函数中return,除非你想让这个函数直接返回到调用层
代码
递归部分
def recursion(from_file, to_file):
# TODO(cui) 如果能匹配上,直接写入,避免无法进入循环
if re.match(r".*\.smali$", from_file):
readAndWrite(from_file, to_file)
return
for file in os.listdir(from_file):
if re.match(r".*\.smali$", file):
readAndWrite(from_file+'\\'+file, to_file)
# return
else:
recursion(from_file +'\\'+ file, to_file)