0%

Android逆向:初探Android逆向

逆向工程

逆向工程(又称逆向技术),是一种产品设计技术再现过程,即对一项目标产品进行逆向分析及研究,从而演绎并得出该产品的处理流程、组织结构、功能特性及技术规格等设计要素,以制作出功能相近,但又不完全一样的产品。逆向工程源于商业及军事领域中的硬件分析。其主要目的是在不能轻易获得必要的生产信息的情况下,直接从成品分析,推导出产品的设计原理。
逆向工程可能会被误认为是对知识产权的严重侵害,但是在实际应用上,反而可能会保护知识产权所有者。例如在集成电路领域,如果怀疑某公司侵犯知识产权,可以用逆向工程技术来寻找证据。

这里我们以安卓项目开始探索逆向工程之路

逆向工具

工欲善其身,必先利其器。

反编译代码的工具下载:

反编译资源的工具:

  • APKTool: 本文重要工具,APK逆向工具,使用简单下载地址: http://ibotpeaches.github.io/Apktool/install/
    这里简单介绍下大概流程,首先把后缀为.apk的文件改为.zip的一个压缩文件,方便解压。dex2jar和jd-gui配套使用,用于逆向代码部分,APKTool用于逆向res文件夹下的图片布局等部分。

新建一个简单的项目

新建一个项目,名字是 Androidrefirst,实现的逻辑是在输入框内填写 2019之后 点击按钮跳转到成功页面。

主要代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.androidrefirst;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
private EditText code;
private Button btn_verify;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}

private void init() {
code = findViewById(R.id.editText);
btn_verify = findViewById(R.id.button);
btn_verify.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String verifyCode=code.getText().toString().trim();
if(verifyCode.equals("2019")){
Intent intent=new Intent(MainActivity.this,SuccessActivity.class);
startActivity(intent);
}else {
Toast.makeText(MainActivity.this,"验证码错误!", Toast.LENGTH_LONG).show();
}
}
});
}
}

生成 apk安装包 app-release.apk

逆向 apk

解压apk得到 classes.dex 文件

需要用到的是dex2jar包里面的三个文件(当前是在windows环境下,Mac环境用对应的.sh文件):

d2j_invoke.bat
d2j-dex2jar.bat
lib
将这三个文件复制到一个空的文件夹内,将刚才.apk解压后的classes.dex文件也一起复制到这里

使用命令 d2j-dex2jar.bat classes.dex 得到 jar文件

使用 jd-gui.exe 打开jar文件看到代码

可以看到我们的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.example.androidrefirst;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
private Button btn_verify;

private EditText code;

private void init() {
this.code = (EditText)findViewById(2131230782);
this.btn_verify = (Button)findViewById(2131230755);
this.btn_verify.setOnClickListener(new View.OnClickListener() {
public void onClick(View param1View) {
if (MainActivity.this.code.getText().toString().trim().equals("2019")) {
Intent intent = new Intent((Context)MainActivity.this, SuccessActivity.class);
MainActivity.this.startActivity(intent);
} else {
Toast.makeText((Context)MainActivity.this, ", 1).show();
}
}
});
}

protected void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
setContentView(2131427356);
init();
}
}

对照着自己的手写的代码,已经差不离十了,对于想要代码思路的我们来说,到这里已经基本可以摸透他的逻辑。

反编译res资源部分

apktool下载后会有两个文件,一个.jar(例如apktool_2.3.3.jar 需要把名字改成apktool.jar) 一个apktool.bat 。

apktool d

同刚才一样在cmd命令下进入刚才文件夹(同样可以新建一个),连同我们刚才那个后缀为apk的安装包一起放入,输入如下命令

1
apktool d app-release.apk  # 此处app-release为apk名称

得到一个新的app-release(对应apk名称)文件夹

这个app-release文件夹下会得到若干文件,主要内容介绍如下:

  • AndroidManifest.xml:描述文件
  • res:资源文件
  • smail:反编译出来的所有代码,语法与java不同,类似汇编,是Android虚拟机所使用的寄存器语言
    到此我们想要的都有了。下一步就是实现我们想法的时候了。

修改原代码逻辑

我们只需要修改if后面的判断条件,设置为否即可if (!MainActivity.this.code.…),这样就成功绕过了条件约束。

接下来还有一部很重要那就是修改smali文件,找到MainActivity$1.smali这个文件用代码查看工具打开

找到这个if-eqz 修改成if-nez (nez对应为非,符号“!”),到这里要修改的部分都成功了,最后一步要做的就是重新打包了。当然对smali语法感兴趣的可以一起探讨学习。

重新打包

在apktool文件夹路径的cmd下输入:

1
2
apktool b [文件夹] -o test2.apk   #(test2为新apk名称,[文件夹]为对应的有修改需要打包的文件夹)
#例如:我当前就可以这样写 apktool b [E:\tools\apktool\app-release] -o test2.apk

至此,我们的目标apk文件已经生成,当然如果你想装到你自己手机上还需要重新签名一下。

重新签名

首先我们需要一个用于签名的.keystore文件,生成命令如下(这里我们假设生成的是demo.keystore)。

1
2
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
# (cmd到apktool文件夹下跟待签名的apk放同个文件夹内便于操作)

这里我们利用Java JDK提供的一个jarsigner进行签名,在刚才的cmd下继续操作,输入:

1
jarsigner -verbose -keystore demo.keystore test2.apk demo.keystore

以上。我们目的apk已经可以投入使用,如果需要更快更好的体验还需要进行一次字节对齐的操作(后续分析)。

参考:

https://blog.csdn.net/micaaa/article/details/82426710