Python项目练习阶段总结

Python项目练习阶段总结

前言

看了别人关于恶意代码特征提取的python程序,想自己写一个,于是有了这篇文章。
通过 apktool 可以对 apk 进行反编译,反编译后得到的目录如下图:
Python项目练习阶段总结
我们要做的是分析其中的 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文件,其深度各不同。
一个示例如下:
Python项目练习阶段总结
对于遇到的smali文件,需要汇总到另一个指定路径的文件夹,对于非smali文件(即图中所示a b c等文件夹),接着访问此文件夹下的目录,遇到.smali文件就将其内容追加,遇到文件夹则重复上述操作。
用正则表达式去匹配.smali文件,对于遇到的文件夹,重复上述操作其实是一个递归的过程。
写一个函数递归遍历这棵树,需要传递的参数就是当前节点的路径。
起初写这个函数时遇到的问题及解决:

  1. 报错:NotADirectoryError: [WinError 267] 目录名称无效
    原因:到达递归边界时没有直接判断是否smali文件,而是对该文件的listdir()进行遍历
    解决:加上边界判断
  2. 情况:写这种目录访问的代码一头雾水
    原因:我创建的目录层太多,导致乱了套
    解决:写代码前先静下心写出大概步骤,对于目录访问,可以先在纸上画出目录的层级图,再写伪代码,最终可以写出正确的代码
  3. 情况: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)