参考: http://www.itdadao.com/articles/c15a190757p0.html

一. 为什么要调试init_array

init_array的用途

1. 一些全局变量的初始化 (我这里试过, 一些全局变量的初始化,会统一用一个init_array表项来完成初始化)

2. 通过__attribute__ ((constructor)) 声明的函数 (可以定义n个)

通过so加载流程来看,init_array是我们程序代码可以控制的最早的时机了, 其次才加载Jni_onload

所以有些样本会在init_array做一些反调试和相关环境检测的活, 所以我们需要在init_array中和对方兵戎相见

当然网上已有很多教我们如何在init_array下断的函数, 但是却都只教了方法, 没有细说原理, 最后我们可能只学会了几个快捷键, 空有招式却无内功, 知其然却不知其所以然, 下面我们就姿势和知识这2方面来进行讨论

二. 断init_array的姿势

1. 定位调试进程中linker的dlopen函数地址

把调试机器中的linker拷贝出来, 路径为/system/bin/linker, 然后开一个IDA分析

在Shift+F12在字符串窗口中查找"dlopen", 跟踪引用到一个函数, 如下图

得到其文件偏移为0xF30

附加上调试器后, 我们得到linker加载到内存的起始地址为400BD000

所以我们在代码窗口Go过去看看400BD000 + F30 = 400BDF30

发现全部是DCB形式的代码(代码没有解析出来), 这个时候我们需要对linker进行分析, 操作如下: 右键->Analyze Module

go过去我们发现和静态分析中的一样,  在函数头部下一个断点


2. 定位到calling相关代码

同样在拷贝出来的ida搜索字符串calling

同样定位到代码,得到文件偏移 2720

那么我们内存中的地址就是 400BD000 + 2720 = 400BF720

同样在调试的ida中下好断点, 第2个断点就是调用.init_array数组的代码

然后按F9,注意观察寄存器窗口, 当有显示调试的是你想要断的so的时候开始注意

当断点断在BLX R4的时候,下一步就是调用init_array数组了, 所以F7跟进去

在直接把我们想要分析的so拖到ida分析进行验证, 代码一样, 说明我们成功的断点在了init_array数组

二. 断init_array的知识

通过上面的操作我们学会了招式, 内功心法却不见修习, 下面我们通过Android的系统源码来一探究竟

环境介绍

源码环境: Android 6.0.1

没有下载源码的同学可以去androidxref在线看源码也很方面

http://androidxref.com/

1. 回到源头看问题

我们都知道我们要在apk中要加载一个so我们可以通过

System.loadLibrary("libname");

System.load("lib_path");

这2者区别如下:

(1). System.load参数必须为库文件的绝对路径,可以是任意路径;

(2). System.loadLibrary参数为库文件名,不包含库文件的扩展名,必须是在JVM属性Java.library.path所指向的路径中,路径可以通过System.getProperty('java.library.path')

2. java层到native层的过程

我们把android_source\libcore\luni部分的源码作为单独的部分丢进Source Insight进行分析

定位到android_source\libcore\luni\src\main\java\java\lang\System.java, 搜索loadLibrary, 就可以开始分析了

java层代码主要是一些路径, 和标记值的初始化

最后比较关键的函数是JavaVMExt.LoadNativeLibrary, 该函数主要完成如下事情

1. 调用linker的dlopen完成加载

2. 调用dlsym获取目标so的JniOnload地址并调用

3. 初始化SharedLibrary对象并添加到表中, 下次加载相同的so则不在重复加载

linker之前的函数调用流程图如下:

3. linker的dlopen简易分析

android系统通过调用linker的dlopen来完成so的转载

把aosp\bionic目录添加到source insight中进行分析

配合AndroidXref站点我们找到, dlopen定义在dlfcn.cpp中

dlopen函数定义如下, 只是简单的调用了dlopen_ext

跟进dlopen_ext函数, 该函数返回一个soinfo的结构体指针
而且这个指针最后作为函数返回值返回了

do_dlopen简单的判断了一下参数, 然后调用find_library进行转载链接so文件

加载成功后,返回soinfo对象指针,同时调用soinfo的成员函数call_constructors来调用so中的init_array

call_constructors先完成其他模块的加载,然后调用call_array()来调用init_array数组的调用

call_array循环调用call_funtion来进行加载

最后call_function只是简单的调用传进来的函数指针, 可以看到我们上面的下断点的字符串就来自于下面 
 

由于篇幅问题,大致介绍下linker的调用流程, 函数调用流程如下:

1. 在do_dlopen中通过find_library进行加载so

在加载完so后通过call_constructors完成init_array的加载

2. find_library最后调用load_libray完成so的转载

3. 最后通过load_library的elf_reader.load完成so的装载

四.总结

由于android是开源的操作系统, android中的很多问题我们都可以通过分析源码来了解细节, 解决问题, 并知其所以然

同时我们还可以通过编译源码来定制我们想要的功能, 达到我们想要的目的

IDA调试android so的.init_array数组的更多相关文章

  1. IDA调试android so文件.init_array和JNI_OnLoad

    我们知道so文件在被加载的时候会首先执行.init_array中的函数,然后再执行JNI_OnLoad()函数.JNI_Onload()函数因为有符号表所以非常容易找到,但是.init_array里的 ...

  2. ida 调试 android fork

    在使用ida 调试android native代码时经常会碰见fork子进程的情况出现,而运行一个 android_server只能对一个进程进行调试或者attach,而ida 默认端口是23946, ...

  3. IDA 调试 Android 方法及简单的脱壳实现

    IDA 调试 Android 方法及简单的脱壳实现 标签: android原创逆向调试dalvik 2016-05-24 14:24 9286人阅读 评论(3) 收藏 举报 分类: 原创(25) An ...

  4. IDA 调试 Android

    最近都在学一些反编译安卓相关的东西,其实网上有很多教程关于用 IDA 调试 Android 的过程,主要记录一下我遇到的坑 首先 Android手机要是root过的 还要注意的一点是apk中的 And ...

  5. 【转】IDA 调试 Android

    最近都在学一些反编译安卓相关的东西,其实网上有很多教程关于用 IDA 调试 Android 的过程,主要记录一下我遇到的坑 首先 Android手机要是root过的 还要注意的一点是apk中的 And ...

  6. ida调试 android so

    C:\Documents and Settings\Administrator>adb shellshell@htc_v2_dtg:/ $ susushell@htc_v2_dtg:/ # cd ...

  7. ida 调试android之路

    系统: Mac OSX 调试环境:IDA7.0,  adb 手机环境:红米手机 android 4.4.4 前提条件: 红米手机root之路:https://www.cnblogs.com/dzqdz ...

  8. IDA动态调试Android的DEX文件

    Android程序的dex文件的动态调试确实是个大问题,网上也有一些教程但是不是特别的详细,今天用到了IDA动态调试Android的DEX文件,特此记录一下. IDA 6.6新添加了对dex文件的调试 ...

  9. Android动态方式破解apk进阶篇(IDA调试so源码)

    一.前言 今天我们继续来看破解apk的相关知识,在前一篇:Eclipse动态调试smali源码破解apk 我们今天主要来看如何使用IDA来调试Android中的native源码,因为现在一些app,为 ...

随机推荐

  1. Linux下测试PHP和MySQL是否正确安装

    测试PHP: 本打算这样配置: 1.拷贝PHP配置文件 cd /usr/local/php/etc cp php.ini /usr/local/php/lib/php.ini 2.修改apache配置 ...

  2. OSG(OpenSceneGraphic) 渲染引擎架构--整体认识 [转]

    原文:http://blog.csdn.net/zangle260/article/details/41123067?utm_source=tuicool 本文参考<<osg最长一帧> ...

  3. 使用Django快速搭建简单的数据管理后台

    使用Django快速搭建简单的数据管理后台 概述 需求描述: 数据表已建好,能可视化操作增删改查,避免直接操作数据库 简版的管理系统 环境 Windows 10 x64 Python 3.6.3 (A ...

  4. Linux多线程编程-信号量

    在Linux中.信号量API有两组.一组是多进程编程中的System V IPC信号量.另外一组是我们要讨论的POSIX信号量. 这两组接口类似,但不保证互换.POSIX信号量函数都已sem_开头,并 ...

  5. 使用Hadoop自己的类操作HDFS

    package hdfs; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.I ...

  6. SharePoint 的PowerShell命令之获取所有网站模版

    Get-SPWebTemplate | select Name, Title

  7. 用C语言解决迷宫问题

    #include <stdio.h> #include <stdlib.h> #define ROW 10 #define COL 10 /*迷宫中位置信息*/ typedef ...

  8. mysql忘记password

    有时候突然忘记MySQL的password会真的不爽,这里介绍一种MySQLpassword忘记时重置password的方法,操作系统win8,MySql version:5.6.10 1 在任务管理 ...

  9. Bootstrap学习速查表(四) 栅格系统

    Bootstrap框架的网格系统工作原理如下: 1.数据行(.row)必须包含在容器(.container)中,以便为其赋予合适的对齐方式和内距(padding).如: 2.在行(.row)中可以添加 ...

  10. sphinx PDF 中文

    使用reST撰写文档时,需要分多个文档时,就必须使用sphinx了,sphinx说起来很简单的,但是默认是不是支持中文的.幸好我出生的晚,sphinx现在已经支持xelatex了^_^ 安装 除了pa ...