上一期探讨了 Android安全测试工具Drozer之手机端agent源码解析 ,这一期探讨一下drozer PC端代码解析,主要是为了写自己的工具而去研究其代码,还是抛砖引玉。
它的反射框架做的确实不错。估计很多人在为它写插件,superFuzz ,intentFuzz、BinderFuzz、AIDLFUZZ等等。
在drozer中有一个重要的东西就是pydiesel,一看这个东西就想起来diesel,上网搜索一下原来是一个如下图
顾名思义,作者想搞一个I/O框架,将agent的内容映射到本地。本地用Python操作就非常方便了。
说了这么多先上重点。看图说话。 协议就是 protobuf_pb2
一看pydiesel最重要了,其中的reflector.py是反射的纽带。先上代码
一个一个解释,init自然不必说,获取会话session
def construct(self, robj,*args): 构造一个类的新实例,可选参数,返回的对象实例。原来是一个new 对象。 def delete(self, robj): 删除存储在远程对象存储的对象。 def deleteAll(self):顾名思义删除所有的。 def getProperty(self,robj, property_name): 获取的对象的属性。 def invoke(self, robj,method, *args):一看就知道是调用了。 def resolve(self, class_name):说明这个类可用,可被初始化。 def setProperty(self,robj, property_name, value): 设置的对象的属性。 def sendAndReceive(self,message_or_factory):充当通讯桥梁。
反射的类型都在这儿定义了
reflected_array 列表
reflected_binary 指的二进制,一般用base64编码
reflected_null null
reflected_object 对象
reflected_primitive基本数据类型(bool,char,int等)
reflected_string 字符串类型
第一实例:
先拿base.py 开刀,
base.py是自定义模块的一个基类,也可说是一个接口,模块自己去实现就好了。
最不可缺的就是
session.reflector反射,后面会用到。一个典型的例子就是:
getContext是agent的一个上下文。可以干好多事呢。比喻说获取所有的安装程序包。
就是通过self.reflector.resolve(class_name)实现的。
看到self.klass(‘com.mwr.dz.Agent’).getContext(),可以断定,这个东西可以直接调用java的方法了。太牛逼了。
第二例子:datetime.py模块
在直接new一个对象,完了还可以用setToNow(),time.format2445()方法,这些方法只有JAVA内可以用呀。
第三个例子:最相对于反射框架第二牛的就是classload,多少个木马后门都是用了这个东西,大部分黑客心里清楚的很呀。
工具中有classload用来做工具也是不错的,动态的换刀头嘛。
先上代码。
下面圈红就是先准备编译java文件为apk文件所需的环境,
条件如下:Android_path= android.jar的路径
dx_path=dx.bat的路径
javac_path= javac.exe的路径
先javac.exe 将java文件xxx.java 编译成class文件
在from pydiesel.reflectionimport utils 有两个文件
先获取代码文件在
先判断是java文件,还是编译好的apk文件,若是java文件就需要编译成apk来用。
进入编译环节了。跟进去。
就有2次命令执行
第一个是 javac -cp android.jarxxx.java 生成了class文件
第二波是 dx.bat –dex –outputxxx.apk 生成apk文件就完了。
上述代码中俨然是用反射生成file对象实例apk文件(其实只是一个dex文件的jar)
然后通过self.construct(“java.io.FileOutputStream”,file_path) 生成FileOutputStream对象流
最好用上了关键东西self.construct(‘dalvik.system.DexClassLoader’,file_path, self.cache_path, None, self.system_class_loader)
等价于DexClassLoader (apkPath,cache_path, classname)
就完了
调用可以看一个例子
shell.py中
看看java代码
有一个静态函数
直接调用多方便呀。
从上面反射的例子可以看出,这完全就是一个虚拟化的操作。将java的反射映射到Python。还可以用Java的方法。
例如:攻击已注册的系统服务
通过adb shell service list可以查看在context manager(或servicemanager)中注册的系统服务名称和IBinder接口。
获取了空间命名和服务名,
轻松获取Stub Proxy这些特征,便可以用反射进行fuzz操作。
*本文作者:wangshu,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)