Android 注入原理介绍


Android注入原理介绍 鲶鱼团队 Orlando Agenda • 为什么需要注入 • 什么是注入 • 怎么注入 为什么需要注入 什么是注入 注入的概念 B A (1)增强B (2)控制B (3)窃取B信息 a 一段代码 静态与动态注入 B A a 怎么注入 注入基本原理:修改PC 注入过程 B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 注入过程 B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 注射器: ptrace • Linux系统下用于调试 的系统调用 int ptrace(int request, int pid, int addr, int data); • ptrace的功效: 1. 跟踪目标进程:PTRACE_ATTACH 注入过程 B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 加载so • libdl.so:dlopen • 在内存中定位libdl.so地址 • 在libdl.so中定位dlopen地址 • 设置SP,传入参数(so的路径) • 将PC指向dlopen地址 注射器: ptrace • Linux系统下用于调试 的系统调用 int ptrace(int request, int pid, int addr, int data); • ptrace的功效: 1. 跟踪目标进程:PTRACE_ATTACH 2. 读取内存:PTRACE_PEEKTEXT 3. 写寄存器:PTRACE_SETREGS 注入过程 B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 执行so中方法 • libdl.so:dlsym • 定位dlsym函数 • 利用dlsym找出目标so中的目标函数地址 • 设置SP,传入(目标函数的)参数 • 将PC指向目标函数地址 注入过程 B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 注入过程 B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 注射器: ptrace • Linux系统下用于调试 的系统调用 int ptrace(int request, int pid, int addr, int data); • ptrace的功效: 1. 跟踪目标进程:PTRACE_ATTACH 2. 读取内存:PTRACE_PEEKTEXT 3. 写寄存器:PTRACE_SETREGS 4. 解除跟踪:PTRACE_DETACH 总结 • 获取root权限 • ptrace: 1. 跟踪目标进程 2. 读取内存(dlopen, dlsym) 3. 执行dlopen加载目标so 4. 执行dlsym找到目标so中某方法 5. 执行so中某方法 6. 解除跟踪 Android的hook介绍 鲶鱼团队 orlando Agenda • 什么是hook • 在哪里hook • Java hook实现方式 什么是hook 加入修改参数逻辑 在前后插入代码 加入修改返回值逻辑 不执行原有代码 开始 传入参数 执行代码 返回结果 结束 传入参数 执行代码 返回结果 在哪里hook B A 跟踪目标进程 等待 修改PC指针,控制B加载目标so库 继续执行暂停前程序 执行so中某方法 修改PC指针,控制B执行so库某方法 a 解除跟踪 hook实现方式一 替换对象 替换对象 objProxy 开始 obj 调用方法 调用方法 替换对象 • 继承父类 • 重写父类方法 • 实例化 • 替换父类对象 替换对象条件一:有可继承父类 com.a.a.a.b 构造子类一:编译后移除父类 JarJar Ant 构造子类二:动态生成 struct ClassObject : Object { …… ClassObject* super; Object* classLoader; InitiatingLoaderList initiatingLoaderList; int interfaceCount; ClassObject** interfaces; int directMethodCount; Method* directMethods; int virtualMethodCount; Method* virtualMethods; int vtableCount; Method** vtable; int iftableCount; InterfaceEntry* iftable; …… }; 构造子类二 Tips: dvmMalloc(); // 开辟ClassObject内存 DVM_OBJECT_INIT(); //init为Class dvmSetFieldObject(); //设superclass 实现重写方法:设置nativeFunc,然后本地方法回调java代码 初始化内存 设置父类 从父类查找需 要重写的方法 开辟内存 开辟Method内 存 实现重写方法 dvmLinkClass struct Method { ClassObject* clazz; u4 accessFlags; u2 methodIndex; u2 registersSize; /* ins + locals */ u2 outsSize; u2 insSize; const char* name; DexProto prototype; const char* shorty; const u2* insns; /* instructions, in memory-mapped .dex */ int jniArgInfo; DalvikBridgeFunc nativeFunc; bool fastJni; bool noRef; bool shouldTrace; const RegisterMap* registerMap; bool inProfile; }; 调用流程 Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck) { ...... if (dvmIsNativeMethod(method)) { TRACE_METHOD_ENTER(self, method); /* * Because we leave no space for local variables, "curFrame" points * directly at the method arguments. */ (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval, method,self); TRACE_METHOD_EXIT(self, method); } else { dvmInterpret(self, method, &retval); } ...... } 替换对象条件二:对象存在 hook实现方式二 直接hook某类的方法 struct Method { ClassObject* clazz; u4 accessFlags; u2 methodIndex; u2 registersSize; /* ins + locals */ u2 outsSize; u2 insSize; const char* name; DexProto prototype; const char* shorty; const u2* insns; /* instructions, in memory-mapped .dex */ int jniArgInfo; DalvikBridgeFunc nativeFunc; bool fastJni; bool noRef; bool shouldTrace; const RegisterMap* registerMap; bool inProfile; }; 代码片段 总结 • 替换对象 优点:在可以获得父类的情况下,实现很简单 缺点: 没有父类的情况下,实现复杂; 必须已经有对象存在 可能要涉及替换多处对象 • 直接hook 某类的方法 优点:实现较简单;没有对象也可以hook 缺点:影响范围过大 谢谢大家 QQ群: 321150823 新浪博客:鲶鱼团队 微信公众号:鲶鱼
还剩41页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

tianzhidao

贡献于2014-08-31

下载需要 6 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf