一、逆向第一个软件
—— 《Android软件安全权威指南》读书笔记
1 搭建环境
1.1 安装jdk
安装JDK并配置环境变量
1.2 安装AndroidStudio
下载链接:http://www.android-studio.org/
1.3 安装反编译工具ApkTool
下载链接:https://ibotpeaches.github.io/Apktool
1.4 安装签名工具ApkSign
下载链接:http://www.top139.com/diy/25.html
2 创建一个Android程序
→NEXT
MainActivity代码
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MainActivity extends AppCompatActivity {
private EditText edit_userName;
private EditText edit_sn;
private Button btn_register;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle(R.string.unregister);
edit_userName = (EditText) findViewById(R.id.edit_username);
edit_sn = (EditText) findViewById(R.id.edit_sn);
btn_register = (Button) findViewById(R.id.button_register);
btn_register.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (!checkSN(edit_userName.getText().toString().trim(),
edit_sn.getText().toString().trim())) {
Toast.makeText(MainActivity.this,
R.string.unsuccessed, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this,
R.string.successed, Toast.LENGTH_SHORT).show();
btn_register.setEnabled(false);
setTitle(R.string.registered);
}
}
});
}
private boolean checkSN(String userName, String sn) {
try {
if ((userName == null) || (userName.length() == 0))
return false;
if ((sn == null) || (sn.length() != 16))
return false;
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.reset();
digest.update(userName.getBytes());
byte[] bytes = digest.digest();
String hexstr = toHexString(bytes, "");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hexstr.length(); i += 2) {
sb.append(hexstr.charAt(i));
}
String userSN = sb.toString();
//Log.d("crackme", hexstr);
//Log.d("crackme", userSN);
if (!userSN.equalsIgnoreCase(sn))
return false;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return false;
}
return true;
}
private static String toHexString(byte[] bytes, String separator) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex).append(separator);
}
return hexString.toString();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/info"
android:textSize="20dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/username" />
<EditText
android:id="@+id/edit_username"
android:hint="@string/hint_username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:ems="10" >
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sn" />
<EditText
android:id="@+id/edit_sn"
android:hint="@string/hint_sn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:ems="10" >
</EditText>
</LinearLayout>
<Button
android:id="@+id/button_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_gravity="right"
android:text="@string/register" />
</LinearLayout>
strings.xml
<resources>
<string name="app_name">Crackme0201</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_main">Crackme0201</string>
<string name="info">Android程序破解演示实例</string>
<string name="username">用户名:</string>
<string name="sn">注册码:</string>
<string name="register">注 册</string>
<string name="hint_username">请输入用户名</string>
<string name="hint_sn">请输入16位的注册码</string>
<string name="unregister">程序未注册</string>
<string name="registered">程序已注册</string>
<string name="unsuccessed">无效用户名或注册码</string>
<string name="successed">恭喜您!注册成功</string>
</resources>
3 创建APK
在虚拟机运行,发现注册失败
4 反编译分析
4.1进入release目录输入cmd
反编译命令是 apktool d ./app-release.apk -o outdir
找到反编译后的代码
if-nez改为if-eqz保存,准备重新编译
5 重新编译
cmd中输入apktool b outdir
此时产生的文件还需要进行签名
签名参照https://blog.csdn.net/lishuai05251986/article/details/84914608
最后把新的APK文件拖入模拟器,或者使用adb命令(参照https://blog.csdn.net/songzi1228/article/details/82746086)下载到模拟器
6 “破解”第一个程序成功
发现已经可以注册成功了
7 后记
这是我的第一篇博客,希望在这一段时间可以把这本大书学习完毕,并坚持写读书笔记。
Markdown的语法还不熟悉,排版也不是很好。
移动安全方面刚刚起步,技术问题可能会很多,感谢交流。