文档章节

逆向Android软件的步骤

henry-zhang
 henry-zhang
发布于 2015/07/23 13:30
字数 1817
阅读 473
收藏 9

逆向Android软件的步骤:

        首先使用反编译的工具对反编译,然后阅读反汇编代码,如果有必要还会对其进行动态调试,找到突破口后注入或直接修改反汇编代码,最后重新编译软件进行测试。整个过程可分为反编译、静态分析、动态调试、重编译等4个环节。

        结论:反破解技术也是从这四个方面进行的。


一、对抗反编译工具(如ApkTool、BackSmali、dex2jar),使其无法进行反编译,或者反编译后无法得到软件正确的反汇编代码。

思路是:寻找反编译工具在处理apk或dex文件时的缺陷,然后在自己的软件中加以利用。主要方法有:

1、阅读反编译工具源码,找出漏洞。

2、压力测试。测试大量apk文件,找到反编译工具反编译不了的,分析其特征。

此方法难度较大,而且反编译工具不断升级,方法容易过时,因此不太建议。(不行)


二、对抗静态分析。


1、代码混淆技术:

Android2.3的SDK中正式加入了ProGuard代码混淆工具,开发人员可以使用该工具对自己的代码进行混淆。Android2.3以前的项目同样可以使用此工具。

2、NDK保护。

NDK简介:“android原生开发套件”。他是一款功能强大的工具,可以将原生C,C++代码的强大功能和android应用的图形化界面结合到一起,解决软件的跨平台问题。通过使用该工具,一些应用程序直接通过JNI调用(ps:java native interface,允许Java代码和其他语言编写的代码进行交互)与CPU打交道使性能得到提升。同时能够将程序的核心功能封装进基于“原生开发套件”的模块中,从而大大提高性能!(PS:C/C++的抗攻击能力比Java强)

优势:逆向NDK程序是很困难和繁琐的,安全性很高。

缺点:程序员开发成本提高。


3、外壳保护。

java由于其语言自身特殊性,没有外壳保护这个概念,只能通过混淆方式对其进行保护。外壳保护重点针对使用NDK编写的Native代码,逆向Native本身就已经够困难了,如果添加了外壳保护则更是难上加难,目前已知可用于ARM Linux内核程序的加壳工具只有upx。

PS:关于upx:http://upx.sourceforge.net/    支持的平台


三、对抗动态调试。


1、检测调试器:

动态调试使用调试器来挂钩软件,获取软件运行时的数据,我们可以在软件中加入检测调试器的代码,当检测到软件被调试器连接时,中止软件的运行。

首先,在AndroidManifest.xml文件的Application标签中加入android:debuggable="false",让程序不可调试,这样,如果别人想调试该程序,就必然会修改它的值,我们在代码中检查它的值来判断程序是否被修改过。代码如下:

if (0!=(getApplicationInfo().flags&=ApplicationInfo.FLAG_DEBUGGABLE)) {  
            Log.e("DEBUG", "程序被修改为可调试状态!!!");  
            android.os.Process.killProcess(android.os.Process.myPid());  
        }

另外,Android SDK中提供了一个方法方便程序员来检测调试器是否已经连接,代码如下:

android.os.Debug.isDebuggerConnected()

如果方法返回真,说明了调试器已经连接。我们可以随机地在软件中插入这行代码来检测调试器,碰到有调试器连接就果断地结束程序运行。

PS:感觉这是个好的办法!但是不知道是否有破解的方法???如果有必要留待以后查资料

对抗检测调试器的方法:

方法1:IsDebuggerPersent()/查找PEB中BeingDebugged内容

方法2:检查是否有异常处理器

方法3:利用调试器约定特殊指令检测

方法4:查找当前硬件断点

方法5:在执行特殊函数后检查GetLastError()值

方法6:DebugPort: CheckRemoteDebuggerPresent()/NtQueryInformationProcess()

方法7:检测SetUnhandledExceptionFilter()

方法8:ThreadHideFromDebugger

方法9:进程遍历

方法10:父进程检查

方法11:SeDebugPrivilege()

方法12:FindWindow

方法13:STARTUPINFO

方法14:timecheck

...

方法N:利用调试器漏洞



(未扩展   但是不知道能不能在android上实现这些对抗)


2、检测模拟器。(ps:只是增加了逆向的成本,必须有一台android机器)

软件发布后会安装到用户的手机中运行,如果有发现软件运行在模拟器中,很显然不合常理,可能是有人试图破解或分析它,这种情况我们必须予以阻止。

模拟器与真实的Android手机有许多差异,我们可以在命令提示符下执行"adb shell getprop"查看并对比它们的属性值,经过对比发现如下几个属性值可以用来判断软件是否运行在模拟器中:

ro.product.model、ro.build.tag、ro.kernel.qemu。

编写检测代码如下:

boolean isRunningInEmualtor() {  
        boolean qemuKernel = false;  
        Process process = null;  
        DataOutputStream os = null;  
        try{    
            process = Runtime.getRuntime().exec("getprop ro.kernel.qemu");    
            os = new DataOutputStream(process.getOutputStream());  
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK"));  
            os.writeBytes("exit\n");    
            os.flush();  
            process.waitFor();  
            qemuKernel = (Integer.valueOf(in.readLine()) == 1);  
            Log.d("com.droider.checkqemu", "检测到模拟器:" + qemuKernel);               
        } catch (Exception e){    
            qemuKernel = false;  
            Log.d("com.droider.checkqemu", "run failed" + e.getMessage());   
        } finally {  
            try{    
                if (os != null) {    
                    os.close();    
                }    
                process.destroy();    
            } catch (Exception e) {  
                  
            }    
            Log.d("com.droider.checkqemu", "run finally");   
        }  
        return qemuKernel;  
    }  
      
    public static String getProp(Context context, String property) {  
        try {  
            ClassLoader cl = context.getClassLoader();  
            Class SystemProperties = cl.loadClass("android.os.SystemProperties");  
            Method method = SystemProperties.getMethod("get", String.class);  
            Object[] params = new Object[1];  
            params[0] = new String(property);  
            return (String)method.invoke(SystemProperties, params);  
        } catch (Exception e) {  
            return null;  
        }  
    }

四、防止重编译。


1、检查签名。

每一个软件在发布时都需要开发人员对其进行签名,而签名使用的密钥文件是开发人员所独有的,破解者通常不可能拥有相同的密钥文件,因此,签名成了Andriod软件一种有效的身份标识,如果软件运行时的签名与自己发布时的不同,说明软件被篡改过,这个时候我们就可以让软件中止运行。

获取签名hash值的代码如下:

public int getSignature(String packageName) {        
        PackageManager pm = this.getPackageManager();  
        PackageInfo pi = null;  
        int sig = 0;  
        try {  
            pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);  
            Signature[] s = pi.signatures;  
            sig = s[0].hashCode();    
        } catch (Exception e1) {  
            sig = 0;  
            e1.printStackTrace();  
        }  
        return sig;  
    }

可使用Eclipse自带的调试版密钥文件生成的apk文件的hash值,与上面的函数获取的hash比较,可以判断签名是否一致。


2、校验保护。(PS:通过联网的方式检验)

重编译Andriod软件的实质是重新编译classes.dex文件,代码经过重新编译后,生成的classes.dex文件的hash值已经改变,我们可以检查程序安装后classes.dex文件的Hash值,来判断软件是否被重打包过。

private boolean checkCRC() {  
    boolean beModified = false;  
    long crc = Long.parseLong(getString(R.string.crc));  
    ZipFile zf;  
try {  
    zf = new ZipFile(getApplicationContext().getPackageCodePath());  
    ZipEntry ze = zf.getEntry("classes.dex");  
    Log.d("com.droider.checkcrc", String.valueOf(ze.getCrc()));  
    if (ze.getCrc() == crc) {  
        beModified = true;  
    }   
} catch (IOException e) {  
    e.printStackTrace();  
    beModified = false;  
}  
return beModified;  
  }

五:动态修改dalvik字节码 增加逆向分析的难度,这个技术比较新 搜不到相应的比较详细的技术介绍


六:将核心代码隐藏,增加分析的难度,这个技术有待查询



转载自梦想天涯的博客:http://blog.csdn.net/viviwen123/article/details/9117589


本文转载自:

henry-zhang
粉丝 2
博文 62
码字总数 1431
作品 0
海淀
私信 提问
转载:最强最全干货分享:Android开发书籍、教程、工具等

最全干货分享,本文收集整理了Android开发所需的书籍、教程、工具、资讯和周刊各种资源,它们能让你在Android开发之旅的各个阶段都受益。 入门 《Learning Android(中文版)》 本书为Andro...

拉偶有所依
2015/01/09
203
3
最强最全干货分享:Android开发书籍、教程、工具等

最全干货分享,本文收集整理了Android开发所需的书籍、教程、工具、资讯和周刊各种资源,它们能让你在Android开发之旅的各个阶段都受益。 入门 《Learning Android(中文版)》 本书为Andro...

拉偶有所依
2015/01/09
502
2
Android应用程序逆向入门

  我们每天都会在Google Play商店看到一系列新的Android应用程序,从游戏到公用设施,再到物联网设备客户端等等,几乎我们生活中的每一个方面都可以通过一个app以某种方式进行控制。我们有...

FreeBuf
2018/04/27
0
0
如何开始对Android应用的逆向分析?

  本文是我的关于如何开始Android逆向系列文章的第一部分。在文末提供了一个文档,你可以根据该文档说明部署同我一样的实验环境。   在了解android应用的逆向之前,你必须对android平台及...

FreeBuf
2018/08/20
0
0
Android ***测试学习手册(二)准备实验环境

在上一章中,我们了解了 Android 安全性及其体系结构的基础知识。 在本章中,我们将了解如何建立 Android ***测试实验环境,其中包括下载和配置 Android SDK 和 Eclipse。 我们将深入了解 AD...

老鹰a
2018/06/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

观点 | 用 MySQL 数据库,到底会不会被“卡脖子”?

>作者:明溪源 **用 MySQL 数据库,到底会不会被“卡脖子”?** 在近期不明朗的贸易形势下,一些正在规划数据库选型、迁移的用户,纷纷询问我们对 MySQL 未来前景的看法。那么使用 MySQL 数据...

爱可生
8分钟前
1
0
千万级流量架构下的负载均衡解析

一、负载均衡 负载均衡算法 转发实现 二、集群下的 Session 管理 Sticky Session Session Replication Session Server 一、负载均衡 集群中的应用服务器(节点)通常被设计成无状态,用户可以...

李红欧巴
12分钟前
9
0
一元建站-基于函数计算 + wordpress 构建 serverless 网站

前言 本文旨在通过 快速部署一个 wordpress 网站到阿里云函数计算平台 这个示例来展示 serverless web 新的开发模式, 包括 FUN 工具一键初始化 NAS, 同步网站到 NAS, 一键部署等能力, 展现函...

阿里云官方博客
14分钟前
1
0
Spring Security 整合JWT(四)

一、前言 本篇文章将讲述Spring Security 简单整合JWT 处理认证授权 基本环境 spring-boot 2.1.8 mybatis-plus 2.2.0 mysql 数据库 maven项目 Spring Security入门学习可参考之前文章: Spri...

郑清
15分钟前
1
0
零基础怎么玩转可视化大屏?这个工具只需5步!

大屏可视化怎么这么火?领导天天要,业务人员、开发人员、IT页面师就得一块熬夜加班,要是不会做大屏,都不好意思说自己做报表、做IT。 也许有人会告诉你,可视化大屏可以用JS+Ecahrts编程实...

朕想上头条
17分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部