逆向libbaiduprotect(二)
首先要确保你所使用的gdb和gdbserver是配对的,最好(或必须)是sdk内相同platform(api level)下的gdb和gdbserver。否则你使用的gdb可能与运行测试机上的gdbserver,因为协议不兼容,而不能正常调试。

gdb 连接后提示,"Argument to arithmetic operation not a number or boolean."
gdbserver 连接后提示,“Unable to get location for thread creation breakpoint: requested event is not supported."
这种情况下,gdb是没法正常使用的,你将会在后续的调试中,不同情况地收到”Remote 'g' packet reply is too long:"

因为这个问题可能会耗费掉了你不少的时间和注意力。这时候最好就是去将你使用的gdb配对的gdbserver从sdk放到测试机去使用。
在测试机中默认有一个远程调试服务程序/system/bin/gdbserver,如果有上面的情况出现,至少使用绝对路径下的你所安排的gdbserver。
参数传递方式:
在x86下,要清楚特殊的传参行为。android的x86 gcc对静态函数的传参规则是,前面两个参数分别应用%eax和%edx,第三个参数开始应用参数栈。而this指针不是我们熟知的vc下应用ecx,gun gcc应用%ebx,而ndk是应用%eax。
下面回到百度加固平台的libbaiduprotect.so逆向。
libbaiduprotect_x86.so是对目标app的dex进行了加固,并且它自身也是加壳了的。下面是以加壳方式存储文件和脱壳后运行在内存映像的dump对比。

壳程序一般都安排在elf格式文件的.init_array section,由linker加载时最先执行。linker有这样的执行流程:
dl_open -> do_open -> soinfo::CallConstructors
只要通过中断linker的soinfo::CallConstructors方法,就可以将加载动态库之初使用程序中断。

中断后,我们通过%eax查看this指针的对象内容,soinfo::CallConstructors是成员方法,指针的对象类型是soinfo,这个结构体包含了加载后section信息。
这个结构的第一个结构成员是不同gcc平台下的linker都一样的,so文件名,查看结果与我调试加载的库名一致,libbaiduproctect_x86.so。后面的结构组织,不同版本的linker各不相同。在这里我懒得去配对正确的版本代码,也就不去搞清它的结构。但是可以通过运行时映射信息,以及readelf查看到的section信息,清楚看到.init_array和.fini_array的section信息加载到soinfo结构了。.init_array section一共0x14字节加载在0xadfa5464。
本例中so映射在0xadf16000,.text段偏移0x2bc0,也就说在0xadf8bc0。而JNI_OnLoad函数偏移量是0x3060,位于0xadf19060。

不用翻查代码,通过查看.init_array段0x14字节的内容,可以大至清楚这个段约等同一个函数指针数组,以空指针结尾。第一个函数指针位于.text的末端,后面三个函数指针位于.text段的开端。linker将按顺序去执行这四个函数。也就是说脱壳程序的其中一个入口就在这四个函数中。

现在我们的程序中断在soinfo::CallConstructors的入口,还没有执行so文件中任何的程序,我们如果反汇编JNI_OnLoad地址的话,就只能得到无法解释的加壳内容。

而so文件.init_array段的函数指针指向的函数则是怎么也就能是加壳的,或者至少保证前面的一个函数可以被执行脱壳出后面的函数。一般地,程序在对代码段进行脱壳,都必须要修改该段的内存访问属性,从只读变为可写才能将脱壳后的代码更新上去,也就说我们只要中断mprotect同样也会将脱壳程序中断到。
libbaiduprotect_x86.so并没有对所有.text段的代码进行脱壳,只是脱壳了一部分,并且在这阶段创建了6个线程,其中包含了反调试的监控线程。由于现在程序的运行被一步步掌控,所以可以将这些线程冻结然后进行后面的调试。
在这里我将被部分脱壳后的so映像dump出来,尝试用ida来静态分析,结果发现ida对x86指令支持并不好,一些原本在gdb能够反汇编的代码,不ida却识别不了。

逆向libbaiduprotect(二)的更多相关文章
- 逆向libbaiduprotect(四)
百度加固libbaiduprotect.so自身对只读字符串进行了加密保护,防止成为破解和逆向的切入口.一般地认为,只要找出这个解密算法就可以对.rodata段的只读字符串进行破解,从而窥探程序的意图 ...
- OD 实验(二十一) - 对反调试程序的逆向分析(二)
程序: 运行程序 点击“Verify” 关闭该程序,启动 OD 再运行程序 逆向: 用 OD 载入程序 按 F8 往下走 执行完这个 call 指令就弹出了对话框 这个 call 指令调用了 Dial ...
- 逆向libbaiduprotect(三)- 移植python操作dalvik虚拟机c++函数,配合gdb控制程序运行流程
python编译移植到测试机,并且移植ctypes模块.利用ctypes代替c程序,利用dalvik内部c++函数,在运行过程中手动命令操控dalvik虚拟机,并结合gdb进行调试.绕过zygote和 ...
- Python逆向(二)—— pyc文件结构分析
一.前言 上一节我们知道了pyc文件是python在编译过程中出现的主要中间过程文件.pyc文件是二进制的,可以由python虚拟机直接执行的程序.分析pyc文件的文件结构对于实现python编译与反 ...
- 从零开始Android逆向教程(二)——什么是Xposed
前言在阅读本文之前,假设你的手机已经root,并且已经成功安装好了 XposedInstaller. Xposed是什么? Xposed 是一个 Android 平台上的动态劫持框架,通过 ...
- x32下PsSetLoadImageNotifyRoutine的逆向
一丶简介 纯属兴趣爱好.特来逆向玩玩. PsSetLoadImageNotifyRoutine 是内核中用来监控模块加载.操作系统给我们提供的回调. 我们只需要填写对应的回调函数原型即可进行加监控. ...
- x32下逆向 PsSetCreateProcessNotifyRoutine 进程钩子
目录 一丶前言 二丶逆向过程 1.windbg挂载 win7 32位.定位到函数反汇编位置 2.逆向 PspSetCreateProcessNotifyRoutine 3.逆向 ExReference ...
- Python逆向(一)—— 前言及Python运行原理
一.前言 最近在学习Python逆向相关,涉及到python字节码的阅读,编译及反汇编一些问题.经过长时间的学习有了一些眉目,为了方便大家交流,特地将学习过程整理,形成了这篇专题.专题对python逆 ...
- Mysql高可用
一.二进制日志 二进制日志,记录所有对库的修改,如update.修改表结构等等 需要开启二进制日志的原因: 1.主从复制都是通过二进制日志进行.主库写二进制日志,传输到从库,从库replay二进制日志 ...
随机推荐
- 详解 Redis 内存管理机制和实现
Redis是一个基于内存的键值数据库,其内存管理是非常重要的.本文内存管理的内容包括:过期键的懒性删除和过期删除以及内存溢出控制策略. 最大内存限制 Redis使用 maxmemory 参数限制最大可 ...
- JAVA实现扫描线算法
首先说一下,教科书上的扫描线算法确实是用c++很好实现,而且网上有很多源码,而java实现的基本没有(可能是我没看到),所以肖先生还是打算自己码(实验作业写这个而自己又个是写java的猿0.0). 对 ...
- Excel接口导出,导入数据库(.Net)
public ActionResult TestExcel(string filePath) { return View(); } /// <summary> /// 根据Excel列类型 ...
- 你真的了解 volatile 关键字吗?
今天,让我们一起来探讨 Java 并发编程中的知识点:volatile 关键字 本文主要从以下三点讲解 volatile 关键字: volatile 关键字是什么? volatile 关键字能解决什么 ...
- python-从文件中读取数据
一.读取整个文件 learnFile.py 绝对路径 # coding=UTF-8 import sys reload(sys) with open(r'C:\Users\zhujiachun\Des ...
- js循环和调用
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Hibernate---快速入门
Hibernate简介 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可 ...
- Django学习day4——视图和URL配置
创建一个简单的hello world 在day3中我们第一次运行了服务器,里面是一个django的欢迎页面,那是因为我们没有配置URL和视图,django在底层会自动跳转这个页面上 我们在mysite ...
- 深度学习tensorflow实战笔记(2)图像转换成tfrecords和读取
1.准备数据 首选将自己的图像数据分类分别放在不同的文件夹下,比如新建data文件夹,data文件夹下分别存放up和low文件夹,up和low文件夹下存放对应的图像数据.也可以把up和low文件夹换成 ...
- [考试反思]0825NOIP模拟测试30:没落
AB卷,15人. Lrefrain rank#1 179 skyh rank#2 122 116 108 54 42虽说还是不怎么样,但是有好转的迹象. 开卷审题,T1是个(假)期望,感觉也许还可做. ...