Android软件安全与逆向分析——如何分析Android程序


《Android软件安全与逆向分析》之如何分析Android程序


进军安全界,找到了关于一本关于Android安全方面的书——丰生强老师的《Android软件安全与逆向分析》,是看雪的版主哦

这段时间就好好研读吧~在这里写一写过程和体会~(其实基本上都是书上的内容啦)


这一篇就是简单的入门,把注册时的跳转条件给改一下


第一步自己写一个小的验证注册码的Android工程

(然后自己破解,是不是很有自己拱了自己种的白菜的赶脚~害羞

Ok,大概界面就是下面这样子





关键的代码是验证注册码的正确性这一部分,这个方法的主要功能是计算用户名与注册码是否匹配。

计算的步骤为:使用MD5算法计算用户名字符串的Hash,将计算所得的结果转换成长度为32位的十六进制字符串,然后取字符串的所有奇数位重新组合生成新的字符串,这个字符串就是最终的注册码,最后将它与传入的注册码进行比较,如果相同表示注册码是正确的,反之注册码是错误的。


private boolean checkSN(String username,String sn) 
{
	try {
    	if((username == null) || (username.length() == 0))
    		return false;
    	if((sn == null) || (sn.length()) != 16)
    		return false;
    	//采用MD5算法进行Hash
    	MessageDigest digest = MessageDigest.getInstance("MD5");
		digest.reset();
		digest.update(username.getBytes());
		byte[] bytes = digest.digest();
		String str = bytesToHexString(bytes);
		System.out.println(str);
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < str.length(); i += 2){
			sb.append(str.charAt(i));
		}
		String userSN = sb.toString();
		if(!userSN.equals(sn))
			return false;			
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
		return false;
	} 	
	return true;
}

public static String bytesToHexString(byte[] src){  
    StringBuilder stringBuilder = new StringBuilder("");  
    if (src == null || src.length <= 0) {  
        return null;  
    }  
    for (int i = 0; i < src.length; i++) {  
        int v = src[i] & 0xFF;  
        String hv = Integer.toHexString(v);  
        if (hv.length() < 2) {  
            stringBuilder.append(0);  
        }  
        stringBuilder.append(hv);  
    }  
    return stringBuilder.toString();  
}  


下面的是onCreate()方法

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setTitle(R.string.unregister);
    
    final EditText et_username = (EditText) findViewById(R.id.edit_username);
    final EditText et_sn = (EditText) findViewById(R.id.edit_sn);
    final Button bt_register = (Button) findViewById(R.id.button_register);
    
    bt_register.setOnClickListener(new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			if(!checkSN(et_username.getText().toString().trim(), 
					et_sn.getText().toString().trim())){
				Toast.makeText(MainActivity.this, R.string.unregister, Toast.LENGTH_SHORT).show();
				setTitle(R.string.unregister);
			}else{
				Toast.makeText(MainActivity.this, R.string.success, Toast.LENGTH_SHORT).show();
				setTitle(R.string.success);
				bt_register.setEnabled(false);
			}
			
		}
	}); 
}

完成后再模拟器上运行的结果如下





第二步现在假装这颗白菜是别人家的,我们要开始拱了..... 

使用apktool反编译刚才生成的apk文件,命令为apktool d Crackme02.apk outdir




反编译的结果保存在outdir文件夹中,其中smali目录下存放了程序所有的反汇编代码,res文件夹下存放的是资源文件

注册码不正确时的错误提示“未注册”是Android程序中的字符串资源,

开发Android程序时,这些字符串可能硬编码到源码中,也可能引用自“res\values”目录下的strings.xml文件,

apk文件在打包时,strings.xml中的字符串被加密存储为resources.arsc 文件保存到apk程序包中,apk被成功反编译后这个文件也被解密出来了。

现在找到res目录下values文件夹中的strings.xml文件,用记事本打开如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Crackme0201</string>
    <string name="username">用户名:</string>
    <string name="zhucema">注册码:</string>
    <string name="action_settings">setting</string>
    <string name="title">Android程序破解演示实例</string>
    <string name="register">注 册</string>
    <string name="hint_username">请输入用户名</string>
    <string name="hint_sn">请输入16位注册码</string>
    <string name="success">注册成功</string>
    <span style="color:#ff0000;"><string name="unregister">未注册</string></span>
</resources>


String.xml文件中的所有字符串资源都在“gen// R.java”文件的String类中被标识,每个字符串都有唯一的int类型索引值,

使用Apktool反编译apk文件后,所有的索引值保存在string.xml文件同目录下的public.xml文件中。

可以看到未注册的字符名称是“unregister”


打开public.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <public type="drawable" name="ic_launcher" id="0x7f020000" />
    <public type="layout" name="activity_main" id="0x7f030000" />
    <public type="dimen" name="activity_horizontal_margin" id="0x7f040000" />
    <public type="dimen" name="activity_vertical_margin" id="0x7f040001" />
    <public type="string" name="app_name" id="0x7f050000" />
    <public type="string" name="username" id="0x7f050001" />
    <public type="string" name="zhucema" id="0x7f050002" />
    <public type="string" name="action_settings" id="0x7f050003" />
    <public type="string" name="title" id="0x7f050004" />
    <public type="string" name="register" id="0x7f050005" />
    <public type="string" name="hint_username" id="0x7f050006" />
    <public type="string" name="hint_sn" id="0x7f050007" />
    <public type="string" name="success" id="0x7f050008" />
    <span style="color:#ff0000;"><public type="string" name="unregister" id="0x7f050009" /></span>
    <public type="style" name="AppBaseTheme" id="0x7f060000" />
    <public type="style" name="AppTheme" id="0x7f060001" />
    <public type="menu" name="main" id="0x7f070000" />
    <public type="id" name="edit_username" id="0x7f080000" />
    <public type="id" name="edit_sn" id="0x7f080001" />
    <public type="id" name="button_register" id="0x7f080002" />
    <public type="id" name="action_settings" id="0x7f080003" />
</resources>

unregister的ID值为0x7f050009

在smali文件夹中搜索内容中含有0x7f050009的文件(在windows下我用的是fileseek工具),发现只有MainActivity$1.smali文件有一处调用




代码如下

.class Lcom/droider/crackme0201/MainActivity$1;
.super Ljava/lang/Object;
.source "MainActivity.java"

# interfaces
.implements Landroid/view/View$OnClickListener;


# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
    value = Lcom/droider/crackme0201/MainActivity;->onCreate(Landroid/os/Bundle;)V
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x0
    name = null
.end annotation


# instance fields
.field final synthetic this$0:Lcom/droider/crackme0201/MainActivity;

.field private final synthetic val$bt_register:Landroid/widget/Button;

.field private final synthetic val$et_sn:Landroid/widget/EditText;

.field private final synthetic val$et_username:Landroid/widget/EditText;


# direct methods
.method constructor <init>(Lcom/droider/crackme0201/MainActivity;Landroid/widget/EditText;Landroid/widget/EditText;Landroid/widget/Button;)V
    .locals 0
    .parameter
    .parameter
    .parameter
    .parameter

    .prologue
    .line 1
    iput-object p1, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;

    iput-object p2, p0, Lcom/droider/crackme0201/MainActivity$1;->val$et_username:Landroid/widget/EditText;

    iput-object p3, p0, Lcom/droider/crackme0201/MainActivity$1;->val$et_sn:Landroid/widget/EditText;

    iput-object p4, p0, Lcom/droider/crackme0201/MainActivity$1;->val$bt_register:Landroid/widget/Button;

    .line 26
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 6
    .parameter "v"

    .prologue
    const v5, 0x7f050009

    const v4, 0x7f050008

    const/4 v3, 0x0

    .line 30
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;

    iget-object v1, p0, Lcom/droider/crackme0201/MainActivity$1;->val$et_username:Landroid/widget/EditText;

    invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;

    move-result-object v1

    invoke-interface {v1}, Landroid/text/Editable;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/String;->trim()Ljava/lang/String;

    move-result-object v1

    .line 31
    iget-object v2, p0, Lcom/droider/crackme0201/MainActivity$1;->val$et_sn:Landroid/widget/EditText;

    invoke-virtual {v2}, Landroid/widget/EditText;->getText()Landroid/text/Editable;

    move-result-object v2

    invoke-interface {v2}, Landroid/text/Editable;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/String;->trim()Ljava/lang/String;

    move-result-object v2

    .line 30
    #calls: Lcom/droider/crackme0201/MainActivity;->checkSN(Ljava/lang/String;Ljava/lang/String;)Z
    invoke-static {v0, v1, v2}, Lcom/droider/crackme0201/MainActivity;->access$0(Lcom/droider/crackme0201/MainActivity;Ljava/lang/String;Ljava/lang/String;)Z

    move-result v0

    .line 31
    if-nez v0, :cond_0

    .line 32
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;

    invoke-static {v0, v5, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;->show()V

    .line 33
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;

    invoke-virtual {v0, v5}, Lcom/droider/crackme0201/MainActivity;->setTitle(I)V

    .line 40
    :goto_0
    return-void

    .line 35
    :cond_0
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;

    invoke-static {v0, v4, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;->show()V

    .line 36
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;

    invoke-virtual {v0, v4}, Lcom/droider/crackme0201/MainActivity;->setTitle(I)V

    .line 37
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->val$bt_register:Landroid/widget/Button;

    invoke-virtual {v0, v3}, Landroid/widget/Button;->setEnabled(Z)V

    goto :goto_0
.end method


Smali代码中添加的注释使用井号“#”开头,“.line 31”行调用了checkSN()函数进行注册码的合法检查,代码:


.line 30
    #calls: Lcom/droider/crackme0201/MainActivity;->checkSN(Ljava/lang/String;Ljava/lang/String;)Z
    invoke-static {v0, v1, v2}, Lcom/droider/crackme0201/MainActivity;->access$0(Lcom/droider/crackme0201/MainActivity;Ljava/lang/String;Ljava/lang/String;)Z
    move-result v0
    .line 31
    if-nez v0, :cond_0


在“.line 30”下面的注释可以看到这一段调用了checkSN方法,接着“.line 31”前后的两行代码的作用就是检查checkSN()函数返回Boolean类型的值

第一行代码将返回的结果保存到v0寄存器中,

第二行代码对v0进行判断,如果v0的值不为零,即条件为真的情况下,跳转到cond_0标号处,反之,程序顺利向下执行。

如果代码不跳转,即注册码不正确的时候,会执行如下几行代码:


.line 32
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;
    invoke-static {v0, v5, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
    move-result-object v0
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V
    .line 33
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;
    invoke-virtual {v0, v5}, Lcom/droider/crackme0201/MainActivity;->setTitle(I)V
    .line 40
    :goto_0
    return-void


“.line 32”行使用iget-object指令获取MainActivity实例的引用。代码中的->this$0是内部类MainActivity$1中的一个synthetic字段,存储的是父类MainActivity的引用,这是Java语言的一个特性
“.line 35”行向v0寄存器传入unsuccessed字符串(v5)的id值,接着调用Toast;->makeText()创建字符串,然后调用Toast;->show()V方法弹出提示,最后.line 40行调用return-void函数返回。

如果代码跳转,即注册码正确时,会执行如下代码:


 :cond_0
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;
    invoke-static {v0, v4, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
    move-result-object v0
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V
    .line 36
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;
    invoke-virtual {v0, v4}, Lcom/droider/crackme0201/MainActivity;->setTitle(I)V
    .line 37
    iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->val$bt_register:Landroid/widget/Button;
    invoke-virtual {v0, v3}, Landroid/widget/Button;->setEnabled(Z)V


这段代码的功能是弹出注册成功提示,也就是说,上面的跳转如果成功意味着程序会成功注册。

经过上一小节的分析可以发现,“.line 31”行的代码“if-nez v0, :cond_0”是程序的破解点。

if-nez是Dalvik指令集中的一个条件跳转指令,类似的还有if-eqz、if-gez、if-lez等。

这里只需要知道,与if-nez指令功能相反的指令为if-eqz,表示比较结果为0或相等时进行跳转。

用任意一款文本编辑器打开MainActivity$1.smali文件,将“.line 31”行的代码“if-nez v0, :cond_0”修改为“if-eqz v0, :cond_0”,保存后退出,代码就算修改完成了。


第三步好不容易费劲拱完了白菜,我们还要把白菜恢复原样....

现在需要将修改后的文件重新进行编译打包成apk文件。

编译apk文件的命令格式为“apktool b[uild] [OPTS] [<app_path>] [<out_file>]”,

打开CMD命令提示符窗口,进入到outdir同目录,执行以下命令。




编译成功后会在outdir目录下生成dist目录,里面存放着编译成功的apk文件。

编译生成的crackme02.apk没有签名,还不能安装测试,接下来需要使用signapk.jar工具对apk文件进行签名。

signapk.jar是Android源码包中的一个签名工具。

代码位于Android源码目录下的/build/tools/signapk/SignApk.java文件中,源码编译后可以在/out/host/linux- x86/framework目录中找到它。

使用signapk.jar签名时需要提供签名文件,我们在此可以使用Android源码中提供的签名文件testkey.pk8与testkey.x509.pem,

它们位于Android源码的build/target/product/security目录。

新建signapk.bat文件,内容为:

<span style="font-size:14px;">java -jar "%~dp0signapk.jar" "%~dp0testkey.x509.pem" "%~dp0testkey.pk8" %1 signed.apk</span>

将signapk.jar、signapk.bat、testkey.x509.pem、testkey.pk8等4个文件放到同一目录并添加到系统PATH环境变量中,

然后在命令提示符下输入如下命令对APK文件进行签名。


signapk crackme02.apk




签名成功后会在同目录下生成signed.apk文件。

如果不行的话,将Crackme02.apk和上面的四个文件放在同一个文件夹中,在控制台进入该层目录后再执行签名命令即可。


第四步咱们要把白菜再种回地里,看看长出来是不是咱们想要的样子....羡慕

把签名好的apk安装在虚拟机或者真机上

任意输入注册码即可验证




总结


这个实例只是介绍了Android程序的一般分析与破解流程。

在实际的分析过程中,接触到的代码远比这些要复杂得多,有些代码甚至经过混淆处理过,很难阅读,这样就需要使用其它手段如动态调试结合一些其它的技巧来辅助分析。

路漫漫其修远兮啊,Fighting,Kiya!


惊讶


相关推荐
Android软件安全逆向分析》由浅入深、循序渐进地讲解了Android系统的软件安全逆向分析加密解密技术。包括Android软件逆向分析和系统安全方面的必备知识及概念、如何静态分析Android软件如何动态调试Android 软件Android 软件的破解反破解技术的探讨,以及对典型Android病毒的全面剖析。 作者简介:丰生强(网名非虫),Android软件安全专家,看雪论坛Android安全版版主,安卓巴士开发交流版版主。 目录 第1章  Android程序分析环境搭建 1.1  Windows分析环境搭建 1.1.1  安装JDK 1.1.2  安装Android SDK 1.1.3  安装Android NDK 1.1.4  Eclipse集成开发环境 1.1.5  安装CDT、ADT插件 1.1.6  创建Android Virtual Device 1.1.7  使用到的工具 1.2  Linux分析环境搭建 1.2.1  本书的Linux环境 1.2.2  安装JDK 1.2.3  在Ubuntu上安装Android SDK 1.2.4  在Ubuntu上安装Android NDK 1.2.5  在Ubuntu上安装 Eclipse集成开发环境 1.2.6  在Ubuntu上安装CDT、ADT插件 1.2.7  创建Android Virtual Device 1.2.8  使用到的工具 1.3  本章小结 第2章  如何分析Android程序 2.1  编写第一个Android程序 2.1.1  使用Eclipse创建Android工程 2.1.2  编译生成APK文件 2.2  破解第一个程序 2.2.1  如何动手? 2.2.2  反编译APK文件 2.2.3  分析APK文件 2.2.4  修改Smali文件代码 2.2.5  重新编译APK文件并签名 2.2.6  安装测试 2.3  本章小结 第3章  进入Android Dalvik虚拟机 3.1  Dalvik虚拟机的特点--掌握Android程序的运行原理 3.1.1  Dalvik虚拟机概述 3.1.2  Dalvik虚拟机Java虚拟机的区别 3.1.3  Dalvik虚拟机是如何执行程序的 3.1.4  关于Dalvik虚拟机JIT(即时编译) 3.2  Dalvik汇编语言基础为分析Android程序做准备 3.2.1  Dalvik指令格式 3.2.2  DEX文件反汇编工具 3.2.3  了解Dalvik寄存器 3.2.4  两种不同的寄存器表示方法--v命名法p命名法 3.2.5  Dalvik字节码的类型、方法字段表示方法 3.3  Dalvik指令集 3.3.1  指令特点 3.3.2  空操作指令 3.3.3  数据操作指令 3.3.4  返回指令 3.3.5  数据定义指令 3.3.6  锁指令 3.3.7  实例操作指令 3.3.8  数组操作指令 3.3.9  异常指令 3.3.10  跳转指令 3.3.11  比较指令 3.3.12  字段操作指令 3.3.13  方法调用指令 3.3.14  数据转换指令 3.3.15  数据运算指令 3.4  Dalvik指令集练习--写一个Dalvik版的Hello World 3.4.1  编写smali文件 3.4.2  编译smali文件 3.4.3  测试运行 3.5  本章小结 第4章  Android可执行文件 4.1  Android程序的生成步骤 4.2  Android程序的安装流程 4.3  dex文件格式 4.3.1  dex文件中的数据结构 4.3.2  dex文件整体结构 4.3.3  dex文件结构分析 4.4  odex文件格式 4.4.1  如何生成odex文件 4.4.2  odex文件整体结构 4.4.3  odex文件结构分析 4.5  dex文件的验证优化工具dexopt的工作过程 4.6  Android应用程序另类破解方法 4.7  本章小结 第5章  静态分析Android程序 5.1  什么是静态分析 5.2  快速定位Android程序的关键代码 5.2.1  反编译apk程序 5.2.2  程序的主Activity 5.2.3  需重点关注的Application类 5.2.4  如何定位关键代码--六种方法 5.3  smali文件格式 5.4  Android程序中的类 5.4.1  内部类 5.4.2  监听器 5.4.3  注解类 5.4.4  自动生成的类 5.5  阅读反编译的smali代码 5.5.1  循环语句 5.5.2  
Android软件安全逆向分析》由浅入深、循序渐进地讲解了Android系统的软件安全逆向分析加密解密技术。包括Android软件逆向分析和系统安全方面的必备知识及概念、如何静态分析Android软件如何动态调试Android 软件Android 软件的破解反破解技术的探讨,以及对典型Android病毒的全面剖析。   《Android软件安全逆向分析》适合所有Android 应用开发者、Android 系统开发工程师、Android系统安全工作者阅读学习。 作者简介   丰生强(网名非虫),Android软件安全专家。看雪论坛Android安全版版主;安卓巴士开发交流版版主。   对Android软件系统安全有狂热的爱好和独到的见解,对Android系统的全部源代码进行过深入地研究和分析逆向分析实战经验丰富。   在国内信息安全杂志上发表过多篇有价值的软件安全文章,目前就职于国内某Android开发企业,常年混迹于看雪论坛(ID非虫)。 目录 第1章  Android程序分析环境搭建 1.1  Windows分析环境搭建 1.1.1  安装JDK 1.1.2  安装Android SDK 1.1.3  安装Android NDK 1.1.4  Eclipse集成开发环境 1.1.5  安装CDT、ADT插件 1.1.6  创建Android Virtual Device 1.1.7  使用到的工具 1.2  Linux分析环境搭建 1.2.1  本书的Linux环境 1.2.2  安装JDK 1.2.3  在Ubuntu上安装Android SDK 1.2.4  在Ubuntu上安装Android NDK 1.2.5  在Ubuntu上安装Eclipse集成开发环境 1.2.6  在Ubuntu上安装CDT、ADT插件 1.2.7  创建Android Virtual Device 1.2.8  使用到的工具 1.3  本章小结 第2章  如何分析Android程序 2.1  编写第一个Android程序 2.1.1  使用Eclipse创建Android工程 2.1.2  编译生成APK文件 2.2  破解第一个程序 2.2.1  如何动手? 2.2.2  反编译APK文件 2.2.3  分析APK文件 2.2.4  修改Smali文件代码 2.2.5  重新编译APK文件并签名 2.2.6  安装测试 2.3  本章小结 第3章  进入Android Dalvik虚拟机 3.1  Dalvik虚拟机的特点--掌握Android程序的运行原理 3.1.1  Dalvik虚拟机概述 3.1.2  Dalvik虚拟机Java虚拟机的区别 3.1.3  Dalvik虚拟机是如何执行程序的 3.1.4  关于Dalvik虚拟机JIT(即时编译) 3.2  Dalvik汇编语言基础为分析Android程序做准备 3.2.1  Dalvik指令格式 3.2.2  DEX文件反汇编工具 3.2.3  了解Dalvik寄存器 3.2.4  两种不同的寄存器表示方法--v命名法p命名法 3.2.5  Dalvik字节码的类型、方法字段表示方法 3.3  Dalvik指令集 3.3.1  指令特点 3.3.2  空操作指令 3.3.3  数据操作指令 3.3.4  返回指令 3.3.5  数据定义指令 3.3.6  锁指令 3.3.7  实例操作指令 3.3.8  数组操作指令 3.3.9  异常指令 3.3.10  跳转指令 3.3.11  比较指令 3.3.12  字段操作指令 3.3.13  方法调用指令 3.3.14  数据转换指令 3.3.15  数据运算指令 3.4  Dalvik指令集练习--写一个Dalvik版的Hello World 3.4.1  编写smali文件 3.4.2  编译smali文件 3.4.3  测试运行 3.5  本章小结 第4章  Android可执行文件 4.1  Android程序的生成步骤 4.2  Android程序的安装流程 4.3  dex文件格式 4.3.1  dex文件中的数据结构 4.3.2  dex文件整体结构 4.3.3  dex文件结构分析 4.4  odex文件格式 4.4.1  如何生成odex文件 4.4.2  odex文件整体结构 4.4.3  odex文件结构分析 4.5  dex文件的验证优化工具dexopt的工作过程 4.6  Android应用程序另类破解方法 4.7  本章小结 第5章  静态分析Android程序 5.1  什么是静态分析 5.2  快速定位Android程序的关键代码 5.2.1  反编译apk程序 5.2.2  程序的主Activity 5.2.3  需重点关注的Application类 5.2.4  如何定位关键代码--六种方法 5.3  smali文件格式 5.4  Android程序中的类 5.4.1  内部类 5.4.2  监听器 5.4.3  注解类 5.4.4  自动生成的类 5.5  阅读反编译的smali代码 5.5.1  循环语句 5.5.2  switch分支语句 5.5.3  try/catch语句 5.6  使用IDA Pro静态分析Android程序 5.6.1  IDA Pro对Android的支持 5.6.2  如何操作 5.6.3  定位关键代码--使用IDA Pro进行破解的实例 5.7  恶意软件分析工具包--Androguard 5.7.1  Androguard的安装配置 5.7.2  Androguard的使用方法 5.7.3  使用Androguard配合Gephi进行静态分析 5.7.4  使用androlyze.py进行静态分析 5.8  其他静态分析工具 5.9  阅读反编译的Java代码 5.9.1  使用dex2jar生成jar文件 5.9.2  使用jd-gui查看jar文件的源码 5.10  集成分析环境--santoku 5.11  本章小结 第6章  基于Android的ARM汇编语言基础--逆向原生! 6.1  AndroidARM处理器 6.1.1  ARM处理器架构概述 6.1.2  ARM处理器家族 6.1.3  Android支持的处理器架构 6.2  原生程序ARM汇编语言--逆向你的原生Hello ARM 6.2.1  原生程序逆向初步 6.2.2  原生程序的生成过程 6.2.3  必须了解的ARM知识 6.3  ARM汇编语言程序结构 6.3.1  完整的ARM汇编程序 6.3.2  处理器架构定义 6.3.3  段定义 6.3.4  注释标号 6.3.5  汇编器指令 6.3.6  子程序参数传递 6.4  ARM处理器寻址方式 6.4.1  立即寻址 6.4.2  寄存器寻址 6.4.3  寄存器移位寻址 6.4.4  寄存器间接寻址 6.4.5  基址寻址 6.4.6  多寄存器寻址 6.4.7  堆栈寻址 6.4.8  块拷贝寻址 6.4.9  相对寻址 6.5  ARMThumb指令集 6.5.1  指令格式 6.5.2  跳转指令 6.5.3  存储器访问指令 6.5.4  数据处理指令 6.5.5  其他指令 6.6  用于多媒体编程浮点计算的NEONVFP指令集 6.7  本章小结 第7章  Android NDK程序逆向分析 7.1  Android中的原生程序 7.1.1  编写一个例子程序 7.1.2  如何编译原生程序 7.2  原生程序的启动流程分析 7.2.1  原生程序的入口函数 7.2.2  main函数究竟何时被执行 7.3  原生文件格式 7.4  原生C程序逆向分析 7.4.1  原生程序分析方法 7.4.2  for循环语句反汇编代码的特点 7.4.3  if...else分支语句反汇编代码的特点 7.4.4  while循环语句反汇编代码的特点 7.4.5  switch分支语句反汇编代码的特点 7.4.6  原生程序的编译时优化 7.5  原生C++程序逆向分析 7.5.1  C++类的逆向 7.5.2  Android NDK对C++特性的支持 7.5.3  静态链接STL动态链接STL的代码区别 7.6  Android NDK JNI API逆向分析 7.6.1  Android NDK提供了哪些函数 7.6.2  如何静态分析Android NDK程序 7.7  本章小结 第8章  动态调试Android程序 8.1  Android动态调试支持 8.2  DDMS的使用 8.2.1  如何启动DDMS 8.2.2  使用LogCat查看调试信息 8.3  定位关键代码 8.3.1  代码注入法--让程序自己吐出注册码 8.3.2  栈跟踪法 8.3.3  Method Profiling 8.4  使用AndBug调试Android程序 8.4.1  安装AndBug 8.4.2  使用AndBug 8.5  使用IDA Pro调试Android原生程序 8.5.1  调试Android原生程序 8.5.2  调试Android原生动态链接库 8.6  使用gdb调试Android原生程序 8.6.1  编译gdbgdbserver 8.6.2  如何调试 8.7  本章小结 第9章  Android软件的破解技术 9.1  试用版软件 9.1.1  试用版软件的种类 9.1.2  实例破解--针对授权KEY方式的破解 9.2  序列号保护 9.3  网络验证 9.3.1  网络验证保护思路 9.3.2  实例破解--针对网络验证方式的破解 9.4  In-app Billing(应用内付费) 9.4.1  In-app Billing原理 9.4.2  In-app Billing破解方法 9.5  Google Play License保护 9.5.1  Google Play License保护机制 9.5.2  实例破解--针对Google Play License方式的破解 9.6  重启验证 9.6.1  重启验证保护思路 9.6.2  实例破解--针对重启验证方式的破解 9.7  如何破解其他类型的Android程序 9.7.1  Mono for Android开发的程序及其破解方法 9.7.2  Qt for Android开发的程序及其破解方法 9.8  本章小结 第10章  Android程序的反破解技术 10.1  对抗反编译 10.1.1  如何对抗反编译工具 10.1.2  对抗dex2jar 10.2  对抗静态分析 10.2.1  代码混淆技术 10.2.2  NDK保护 10.2.3  外壳保护 10.3  对抗动态调试 10.3.1  检测调试器 10.3.2  检测模拟器 10.4  防止重编译 10.4.1  检查签名 10.4.2  校验保护 10.5  本章小结 第11章  Android系统攻击防范 11.1  Android系统安全概述 11.2  手机ROOT带来的危害 11.2.1  为什么要ROOT手机 11.2.2  手机ROOT后带来的安全隐患 11.2.3  Android手机ROOT原理 11.3  Android权限攻击 11.3.1  Android权限检查机制 11.3.2  串谋权限攻击 11.3.3  权限攻击检测 11.4  Android组件安全 11.4.1  Activity安全及Activity劫持演示 11.4.2  Broadcast Receiver 安全 11.4.3  Service安全 11.4.4  Content Provider安全 11.5  数据安全 11.5.1  外部存储安全 11.5.2  内部存储安全 11.5.3  数据通信安全 11.6  ROM安全 11.6.1  ROM的种类 11.6.2  ROM的定制过程 11.6.3  定制ROM的安全隐患 11.6.4  如何防范 11.7  本章小结 第12章  DroidKongFu变种病毒实例分析 12.1  DroidKongFu病毒介绍 12.2  配置病毒分析环境 12.3  病毒执行状态分析 12.3.1  使用APIMonitor初步分析 12.3.2  使用DroidBox动态分析 12.3.3  其他动态分析工具 12.4  病毒代码逆向分析 12.4.1  Java层启动代码分析 12.4.2  Native层启动代码分析 12.4.3  Native层病毒核心分析 12.5  DroidKongFu病毒框架总结 12.6  病毒防治 12.7  本章小结
1-12章节,完整版 目 录 第1 章 ANDROID 程序分析环境搭建................................1 1.1 Windows 分析环境搭建...................................... 1 1.1.1 安装JDK..................................................1 1.1.2 安装Android SDK..........................................3 1.1.3 安装Android NDK..........................................5 1.1.4 Eclipse 集成开发环境.....................................6 1.1.5 安装CDT、ADT 插件........................................6 1.1.6 创建Android Virtual Device...............................8 1.1.7 使用到的工具.............................................9 1.2 Linux 分析环境搭建........................................ 9 1.2.1 本书的Linux 环境.........................................9 1.2.2 安装JDK..................................................9 1.2.3 在Ubuntu 上安装Android SDK..............................10 1.2.4 在Ubuntu 上安装Android NDK .............................11 1.2.5 在Ubuntu 上安装Eclipse 集成开发环境.....................12 1.2.6 在Ubuntu 上安装CDT、ADT 插件............................13 1.2.7 创建Android Virtual Device..............................13 1.2.8 使用到的工具............................................15 1.3 本章小结..................................................15 第2 章 如何分析ANDROID 程序...................................16 2.1 编写第一个Android 程序....................................16 2.1.1 使用Eclipse 创建Android 工程............................16 2.1.2 编译生成APK 文件........................................19 2.2 破解第一个程序............................................20 2.2.1 如何动手?..............................................20 2.2.2 反编译APK 文件..........................................20 2.2.3 分析APK 文件............................................21 2.2.4 修改Smali 文件代码......................................26 2.2.5 重新编译APK 文件并签名..................................26 2.2.6 安装测试................................................27 2.3 本章小结..................................................28 第3 章 进入ANDROID DALVIK 虚拟机..............................29 3.1 Dalvik 虚拟机的特点——掌握Android 程序的运行原理...........29 3.1.1 Dalvik 虚拟机概述.......................................29 3.1.2 Dalvik 虚拟机Java 虚拟机的区别........................29 3.1.3 Dalvik 虚拟机是如何执行程序的...........................34 3.1.4 关于Dalvik 虚拟机JIT(即时编译)........................36 3.2 Dalvik 汇编语言基础为分析Android 程序做准备...............37 3.2.1 Dalvik 指令格式.........................................37 3.2.2 DEX 文件反汇编工具......................................39 3.2.3 了解Dalvik 寄存器.......................................40 3.2.4 两种不同的寄存器表示方法——v 命名法p 命名法............42 3.2.5 Dalvik 字节码的类型、方法字段表示方法.................43 3.3 Dalvik 指令集.............................................44 3.3.1 指令特点................................................45 3.3.2 空操作指令..............................................45 3.3.3 数据操作指令............................................46 3.3.4 返回指令................................................46 3.3.5 数据定义指令............................................46 3.3.6 锁指令..................................................47 3.3.7 实例操作指令............................................47 3.3.8 数组操作指令............................................48 3.3.9 异常指令................................................48 3.3.10 跳转指令...............................................48 3.3.11 比较指令...............................................49 3.3.12 字段操作指令...........................................50 3.3.13 方法调用指令...........................................50 3.3.14 数据转换指令...........................................51 3.3.15 数据运算指令...........................................51 3.4 Dalvik 指令集练习——写一个Dalvik 版的Hello World...........52 3.4.1 编写smali 文件..........................................52 3.4.2 编译smali 文件..........................................54 3.4.3 测试运行................................................54 3.5 本章小结..................................................55 第4 章 ANDROID 可执行文件.....................................56 4.1 Android 程序的生成步骤....................................56 4.2 Android 程序的安装流程....................................59 4.3 dex 文件格式..............................................66 4.3.1 dex 文件中的数据结构....................................66 4.3.2 dex 文件整体结构........................................68 4.3.3 dex 文件结构分析........................................71 4.4 odex 文件格式.............................................80 4.4.1 如何生成odex 文件.......................................80 4.4.2 odex 文件整体结构.......................................81 4.4.3 odex 文件结构分析.......................................83 4.5 dex 文件的验证优化工具dexopt 的工作过程.................88 4.6 Android 应用程序另类破解方法..............................91 4.7 本章小结..................................................93 第5 章 静态分析ANDROID 程序...................................94 5.1 什么是静态分析............................................94 5.2 快速定位Android 程序的关键代码............................94 5.2.1 反编译apk 程序..........................................94 5.2.2 程序的主Activity........................................95 5.2.3 需重点关注的Application 类..............................95 5.2.4 如何定位关键代码——六种方法..............................96 5.3 smali 文件格式............................................97 5.4 Android 程序中的类.......................................100 5.4.1 内部类.................................................100 5.4.2 监听器.................................................102 5.4.3 注解类.................................................105 5.4.4 自动生成的类...........................................108 5.5 阅读反编译的smali 代码...................................110 5.5.1 循环语句...............................................110 5.5.2 switch 分支语句........................................115 5.5.3 try/catch 语句.........................................121 5.6 使用IDA Pro 静态分析Android 程序.........................127 5.6.1 IDA Pro 对Android 的支持...............................127 5.6.2 如何操作...............................................128 5.6.3 定位关键代码——使用IDA Pro 进行破解的实例...............132 5.7 恶意软件分析工具包——Androguard ..........................135 5.7.1 Androguard 的安装配置................................135 5.7.2 Androguard 的使用方法..................................137 5.7.3 使用Androguard 配合Gephi 进行静态分析..................144 5.7.4 使用androlyze.py 进行静态分析..........................148 5.8 其它静态分析工具.........................................152 5.9 阅读反编译的Java 代码....................................152 5.9.1 使用dex2jar 生成jar 文件...............................152 5.9.2 使用jd-gui 查看jar 文件的源码..........................153 5.10 集成分析环境——santoku ..................................154 5.11 本章小结................................................156 第6 章 基于ANDROID 的ARM 汇编语言基础逆向原生! .............157 6.1 Android ARM处理器......................................157 6.1.1 ARM 处理器架构概述.....................................157 6.1.2 ARM 处理器家族.........................................158 6.1.3 Android 支持的处理器架构...............................159 6.2 原生程序ARM 汇编语言——逆向你的原生Hello ARM ...........160 6.2.1 原生程序逆向初步.......................................160 6.2.2 原生程序的生成过程.....................................162 6.2.3 必须了解的ARM 知识.....................................164 6.3 ARM 汇编语言程序结构.....................................166 6.3.1 完整的ARM汇编程序......................................166 6.3.2 处理器架构定义.........................................167 6.3.3 段定义.................................................168 6.3.4 注释标号.........................................,,,,169 6.3.5 汇编器指令.............................................169 6.3.6 子程序参数传递.......................................170 6.4 ARM 处理器寻址方式.......................................170 6.4.1 立即寻址...............................................170 6.4.2 寄存器寻址.............................................171 6.4.3 寄存器移位寻址.........................................171 6.4.4 寄存器间接寻址.........................................171 6.4.5 基址寻址...............................................171 6.4.6 多寄存器寻址...........................................171 6.4.7 堆栈寻址...............................................172 6.4.8 块拷贝寻址.............................................172 6.4.9 相对寻址...............................................172 6.5 ARMThumb 指令集........................................173 6.5.1 指令格式...............................................173 6.5.2 跳转指令...............................................174 6.5.3 存储器访问指令.........................................175 6.5.4 数据处理指令...........................................177 6.5.5 其它指令...............................................184 6.6 用于多媒体编程浮点计算的NEON VFP 指令集..............185 6.7 本章小结.................................................186
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页