Writeup 4 NUAA 2017 robots
题目信息
- 题目名称:robots
- 所属赛事:NUAA 2017
- 题目类型:Android 逆向(Reverse Engineering)
- 附件 :
robot.apk - Flag 格式 :
flag{...}
一、前置知识
1.1 什么是 APK
APK(Android Package)是 Android 应用的安装包,本质上是一个 ZIP 压缩包,里面包含:
| 文件/目录 | 作用 |
|---|---|
AndroidManifest.xml |
应用配置(权限、Activity 等) |
classes.dex |
Dalvik 字节码(Java/Kotlin 编译后的代码) |
lib/ |
Native 库(C/C++ 编译的 .so 文件) |
res/ |
资源文件(布局、图片、字符串等) |
assets/ |
原始资源文件(数据库、配置文件等) |
META-INF/ |
签名信息 |
1.2 常用的 Android 逆向工具
| 工具 | 作用 | 安装方法 |
|---|---|---|
apktool |
反编译 APK(资源 + smali) | apt install apktool |
jadx |
反编译 APK 成 Java 代码 | GitHub 下载 |
radare2 |
反汇编 native 库 | apt install radare2 |
sqlite3 |
查看 SQLite 数据库 | apt install sqlite3 |
zsteg |
图片隐写检测(本题不用) | gem install zsteg |
二、解题步骤
第一步:确认附件类型
bash
root@Rambo:/robots# file robot.apk
命令说明:
file:检测文件类型robot.apk:附件文件名
输出:
bash
robot.apk: Android package (APK), with classes.dex, with APK Signing Block
root@Rambo:/robots#
结论:这是一个 Android APK 文件。
第二步:查看 APK 内部结构
bash
root@Rambo:/robots# unzip -l robot.apk | head -50
命令说明:
unzip -l:列出 ZIP 包内的文件(不解压)| head -50:只显示前 50 行
输出:
Archive: robot.apk
Length Date Time Name
--------- ---------- ----- ----
2128 1980-00-00 00:00 AndroidManifest.xml
765 1980-00-00 00:00 META-INF/CERT.RSA
44326 1980-00-00 00:00 META-INF/CERT.SF
44283 1980-00-00 00:00 META-INF/MANIFEST.MF
5120 1980-00-00 00:00 assets/test
2652872 1980-00-00 00:00 classes.dex
186512 1980-00-00 00:00 lib/arm64-v8a/libnative-lib.so
108192 1980-00-00 00:00 lib/armeabi-v7a/libnative-lib.so
112284 1980-00-00 00:00 lib/armeabi/libnative-lib.so
235860 1980-00-00 00:00 lib/mips/libnative-lib.so
241744 1980-00-00 00:00 lib/mips64/libnative-lib.so
181960 1980-00-00 00:00 lib/x86/libnative-lib.so
178728 1980-00-00 00:00 lib/x86_64/libnative-lib.so
396 1980-00-00 00:00 res/anim/abc_fade_in.xml
396 1980-00-00 00:00 res/anim/abc_fade_out.xml
860 1980-00-00 00:00 res/anim/abc_grow_fade_in_from_bottom.xml
512 1980-00-00 00:00 res/anim/abc_popup_enter.xml
512 1980-00-00 00:00 res/anim/abc_popup_exit.xml
860 1980-00-00 00:00 res/anim/abc_shrink_fade_out_from_bottom.xml
400 1980-00-00 00:00 res/anim/abc_slide_in_bottom.xml
400 1980-00-00 00:00 res/anim/abc_slide_in_top.xml
400 1980-00-00 00:00 res/anim/abc_slide_out_bottom.xml
400 1980-00-00 00:00 res/anim/abc_slide_out_top.xml
472 1980-00-00 00:00 res/color-v11/abc_background_cache_hint_selector_material_dark.xml
472 1980-00-00 00:00 res/color-v11/abc_background_cache_hint_selector_material_light.xml
504 1980-00-00 00:00 res/color-v23/abc_btn_colored_borderless_text_material.xml
504 1980-00-00 00:00 res/color-v23/abc_btn_colored_text_material.xml
548 1980-00-00 00:00 res/color-v23/abc_color_highlight_material.xml
628 1980-00-00 00:00 res/color-v23/abc_tint_btn_checkable.xml
1128 1980-00-00 00:00 res/color-v23/abc_tint_default.xml
672 1980-00-00 00:00 res/color-v23/abc_tint_edittext.xml
504 1980-00-00 00:00 res/color-v23/abc_tint_seek_thumb.xml
672 1980-00-00 00:00 res/color-v23/abc_tint_spinner.xml
628 1980-00-00 00:00 res/color-v23/abc_tint_switch_thumb.xml
668 1980-00-00 00:00 res/color-v23/abc_tint_switch_track.xml
608 1980-00-00 00:00 res/color/abc_btn_colored_borderless_text_material.xml
608 1980-00-00 00:00 res/color/abc_btn_colored_text_material.xml
568 1980-00-00 00:00 res/color/abc_hint_foreground_material_dark.xml
568 1980-00-00 00:00 res/color/abc_hint_foreground_material_light.xml
468 1980-00-00 00:00 res/color/abc_primary_text_disable_only_material_dark.xml
468 1980-00-00 00:00 res/color/abc_primary_text_disable_only_material_light.xml
468 1980-00-00 00:00 res/color/abc_primary_text_material_dark.xml
468 1980-00-00 00:00 res/color/abc_primary_text_material_light.xml
596 1980-00-00 00:00 res/color/abc_search_url_text.xml
468 1980-00-00 00:00 res/color/abc_secondary_text_material_dark.xml
468 1980-00-00 00:00 res/color/abc_secondary_text_material_light.xml
732 1980-00-00 00:00 res/color/abc_tint_btn_checkable.xml
root@Rambo:/robots#
关键文件:
assets/test(5120 字节):可能是数据库或配置文件classes.dex(2.6MB):Java 代码lib/arm64-v8a/libnative-lib.so:Native 库
第三步:安装反编译工具
bash
apt install apktool radare2 sqlite3 -y
命令说明:
apt install:安装软件包-y:自动确认apktool:反编译 APKradare2:反汇编 native 库sqlite3:查看 SQLite 数据库
jadx 需要从 GitHub 下载:
bash
cd /tmp
wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip
unzip jadx-1.5.0.zip -d jadx
root@Rambo:/robots# wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip
--2026-10-02 16:39:34-- https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip
Resolving github.com (github.com)... 20.205.243.166
Connecting to github.com (github.com)|20.205.243.166|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://release-assets.githubusercontent.com/github-production-release-asset/8859474/b458c7d6-0cc7-44f4-a66a-9ce2280b0d7f?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-10-02T09%3A20%3A21Z&rscd=attachment%3B+filename%3Djadx-1.5.0.zip&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-10-02T08%3A20%3A18Z&ske=2026-10-02T09%3A20%3A21Z&sks=b&skv=2018-11-09&sig=bgYWx1k7brwtj7Wka1K9mA252HkZpV3RpTL6SFKq3Xg%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc5MDkzMzk3NSwibmJmIjoxNzkwOTMwMzc1LCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.UVkdIILyMzeJaJ0b-wwjBY-AqjQf10gXaU_fLmjkB1I&response-content-disposition=attachment%3B%20filename%3Djadx-1.5.0.zip&response-content-type=application%2Foctet-stream [following]
--2026-10-02 16:39:35-- https://release-assets.githubusercontent.com/github-production-release-asset/8859474/b458c7d6-0cc7-44f4-a66a-9ce2280b0d7f?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-10-02T09%3A20%3A21Z&rscd=attachment%3B+filename%3Djadx-1.5.0.zip&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-10-02T08%3A20%3A18Z&ske=2026-10-02T09%3A20%3A21Z&sks=b&skv=2018-11-09&sig=bgYWx1k7brwtj7Wka1K9mA252HkZpV3RpTL6SFKq3Xg%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc5MDkzMzk3NSwibmJmIjoxNzkwOTMwMzc1LCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.UVkdIILyMzeJaJ0b-wwjBY-AqjQf10gXaU_fLmjkB1I&response-content-disposition=attachment%3B%20filename%3Djadx-1.5.0.zip&response-content-type=application%2Foctet-stream
Resolving release-assets.githubusercontent.com (release-assets.githubusercontent.com)... 185.199.111.133, 185.199.110.133, 185.199.108.133, ...
Connecting to release-assets.githubusercontent.com (release-assets.githubusercontent.com)|185.199.111.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 104967983 (100M) [application/octet-stream]
Saving to: 'jadx-1.5.0.zip'
jadx-1.5.0.zip 100%[=================================================>] 100.10M 71.8KB/s in 24m 20s
2026-10-02 17:04:48 (70.2 KB/s) - 'jadx-1.5.0.zip' saved [104967983/104967983]
root@Rambo:/robots#
root@Rambo:/robots# unzip jadx-1.5.0.zip -d jadx
Archive: jadx-1.5.0.zip
creating: jadx/lib/
inflating: jadx/lib/jadx-1.5.0-all.jar
creating: jadx/bin/
inflating: jadx/bin/jadx
inflating: jadx/bin/jadx-gui
inflating: jadx/bin/jadx-gui.bat
inflating: jadx/bin/jadx.bat
inflating: jadx/LICENSE
inflating: jadx/README.md
root@Rambo:/robots#
命令说明:
wget:下载文件unzip:解压 ZIP-d jadx:解压到jadx目录
第四步:解压 APK 里的关键文件
bash
mkdir robot_extracted
unzip -o robot.apk assets/test classes.dex "lib/*" -d robot_extracted
命令说明:
unzip -o:解压并覆盖已有文件assets/test classes.dex "lib/*":只解压这三个-d robot_extracted:解压到robot_extracted目录
第五步:检查 assets/test
bash
root@Rambo:/robots# file robot_extracted/assets/test
输出:
bash
robot_extracted/assets/test: SQLite 3.x database, last written using SQLite version 3008010, page size 1024, file counter 3, database pages 5, 1st free page 3, free pages 2, cookie 0x4, schema 4, UTF-8, version-valid-for 3
root@Rambo:/robots#
结论 :这是一个 SQLite 数据库。
用 sqlite3 打开:
bash
root@Rambo:/robots# sqlite3 robot_extracted/assets/test
SQLite version 3.45.1 2024-01-30 16:01:20
Enter ".help" for usage hints.
sqlite>
在 sqlite3 里执行:
sql
sqlite> .tables
输出:
只有 1 张表:
sql
user1
查看表结构:
sql
sqlite> .schema user1
输出:
sql
CREATE TABLE user1 (name STRING (32) PRIMARY KEY, secret STRING (20));
一共 2 个字段:
name 和 secret。
查看数据:
sql
sqlite> SELECT * FROM user1;
输出:
70ba592665915c3c29bd16115ce6d75e|MpJrLtNvExBzA|F~]`Zb
0733351879b2fa9bd05c7ca3061529c0|yKKHBIIBCAyslt}z~}x{
01ecd51c3cb8780d9d2138565c6b5173|DJsrwOpqJx}c`g>?h`jb
912af0dff974604f1321254ca8ff38b6|AtMNAMr~AMOAtxFzxxxx
5d41402abc4b2a76b9719d911017c592|kEvKc|roAkNADgGExUeq
退出 sqlite3:
sql
sqlite> .quit
root@Rambo:/robots#
第六步:反编译 classes.dex 成 Java
bash
root@Rambo:/robots# /jadx/bin/jadx -d robot_jadx robot.apk
INFO - loading ...
INFO - processing ...
INFO - done
root@Rambo:/robots#
命令说明:
jadx:反编译工具-d robot_jadx:输出到robot_jadx目录robot.apk:输入文件
第七步:分析 MainActivity
bash
root@Rambo:/robots# cat robot_jadx/sources/com/example/link/rev1/MainActivity.java
输出:
java
package com.example.link.rev1;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
/* loaded from: classes.dex */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button button;
private CheckAns c;
private String datebasePath;
private TextView tv;
private EditText userEdit;
public native String getSecret(String str);
@Override // android.view.View.OnClickListener
public void onClick(View v) {
String ans = getSecret(this.userEdit.getText().toString());
if (this.c.check(ans, this)) {
this.tv.setText("Well done!");
} else {
this.tv.setText("Ennnnnn........No.Right...");
}
}
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityGingerbread, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.c = new CheckAns();
this.tv = (TextView) findViewById(R.id.sample_text);
this.userEdit = (EditText) findViewById(R.id.userEdit);
this.button = (Button) findViewById(R.id.button);
this.tv.setText("can you find the secret in C?");
this.button.setOnClickListener(this);
}
static {
System.loadLibrary("native-lib");
}
}
root@Rambo:/robots#
分析:
getSecret(input)是 native 方法 (在.so库里)- 用户输入 →
getSecret(input)→ans CheckAns.check(ans)验证ans
第八步:分析 CheckAns
bash
root@Rambo:/robots# cat robot_jadx/sources/com/example/link/rev1/CheckAns.java
输出:
java
package com.example.link.rev1;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/* loaded from: classes.dex */
public class CheckAns {
private String name = "aGVsbG8=";
public boolean check(String ans, Context t) {
SQLiteDatabase db = new SQLAm().openDatabase(t);
byte[] decodeString = Base64.decode(this.name, 0);
String realName = md5(new String(decodeString));
Cursor cr = db.rawQuery("SELECT * FROM user1 WHERE name='" + realName + "'", null);
cr.moveToNext();
String secret = cr.getString(cr.getColumnIndex("secret"));
return ans.length() == 20 && secret.equals(ans);
}
public static String md5(String string) {
if (TextUtils.isEmpty(string)) {
return "";
}
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bytes = md5.digest(string.getBytes());
String result = "";
for (byte b : bytes) {
String temp = Integer.toHexString(b & 255);
if (temp.length() == 1) {
temp = "0" + temp;
}
result = result + temp;
}
return result;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
}
}
}
root@Rambo:/robots#
分析:
name = "aGVsbG8="→ Base64 解码 →hellomd5("hello")=5d41402abc4b2a76b9719d911017c592- 从数据库查
name = '5d41402abc4b2a76b9719d911017c592'的记录 - 取出对应的
secret:kEvKc|roAkNADgGExUeq7 - 检查
ans == secret且ans.length() == 20
验证 MD5:
bash
root@Rambo:/robots# echo -n "hello" | md5sum
命令说明:
echo -n:输出不带换行md5sum:计算 MD5
输出:
5d41402abc4b2a76b9719d911017c592 -
root@Rambo:/robots#
确认 5d41402abc4b2a76b9719d911017c592 = md5("hello")。
第九步:用 radare2 反汇编 libnative-lib.so
bash
root@Rambo:/robots# r2 -A robot_extracted/lib/arm64-v8a/libnative-lib.so
命令说明:
r2:radare2 启动-A:自动分析robot_extracted/lib/arm64-v8a/libnative-lib.so:目标文件
输出:
radare2
Warning: run r2 with -e bin.cache=true to fix relocations in disassembly
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Finding and parsing C++ vtables (avrr)
[x] Finding xrefs in noncode section (e anal.in=io.maps.x)
[x] Analyze value pointers (aav)
[x] Value from 0x00000000 to 0x0002a7cc (aav)
[x] 0x00000000-0x0002a7cc in 0x0-0x2a7cc (aav)
[x] Emulate functions to find computed references (aaef)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information (aanr)
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x000076e0]>
在 r2 提示符下:
[0x000076e0]> afl~getSecret
命令说明:
afl:列出所有函数~getSecret:过滤包含getSecret的函数
输出:
0x000077e0 27 944 -> 844 sym.Java_com_example_link_rev1_MainActivity_getSecret
[0x000076e0]>
结论 :getSecret 函数地址是 0x77e0。
反编译这个函数:
[0x000076e0]> s 0x77e0
[0x000077e0]> pdc
命令说明:
s 0x77e0:跳转到地址pdc:输出伪 C 代码
输出(关键部分):
c
// 字符集
x1 = 0x221b0; // "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!{|}~"
// memcpy 拷贝整数数组
x0 = 0x221f4; // [0, 1, 2, ..., 49]
memcpy(s1, 0x221f4, n);
// 第一个循环
for (i = 0; i < len(s1); i++) {
s1[i] = (s1[i] + 16) % len(s1);
}
// 第二个循环
for (j = 0; j < len(input); j++) {
for (k = 0; k < len(s1); k++) {
if (input[j] == charset[s1[k]]) {
input[j] = charset[s1[k]];
break;
}
}
}
// 第三个循环
for (i = 0; i < len(input); i++) {
input[i] = (input[i] XOR i) % 128;
}
第十步:查看关键数据
在 r2 里查看字符集:
[0x000077e0]> px 100 @ 0x221b0
命令说明:
px:十六进制显示100:显示 100 字节@ 0x221b0:从地址0x221b0开始
输出:
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x000221b0 3031 3233 3435 3637 3839 6162 6364 6566 0123456789abcdef
0x000221c0 6768 696a 6b6c 6d6e 6f70 7172 7374 7576 ghijklmnopqrstuv
0x000221d0 7778 797a 4142 4344 4546 4748 494a 4b4c wxyzABCDEFGHIJKL
0x000221e0 4d4e 4f50 5152 5354 5556 5758 595a 217b MNOPQRSTUVWXYZ!{
0x000221f0 7c7d 7e00 0000 0000 0100 0000 0200 0000 |}~.............
0x00022200 0300 0000 0400 0000 0500 0000 0600 0000 ................
0x00022210 0700 0000 ....
[0x000077e0]>
字符集 :0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!{|}~
查看整数数组:
[0x000077e0]> px 200 @ 0x221f4
输出:
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x000221f4 0000 0000 0100 0000 0200 0000 0300 0000 ................
0x00022204 0400 0000 0500 0000 0600 0000 0700 0000 ................
0x00022214 0800 0000 0900 0000 0a00 0000 0b00 0000 ................
0x00022224 0c00 0000 0d00 0000 0e00 0000 0f00 0000 ................
0x00022234 1000 0000 1100 0000 1200 0000 1300 0000 ................
0x00022244 1400 0000 1500 0000 1600 0000 1700 0000 ................
0x00022254 1800 0000 1900 0000 1a00 0000 1b00 0000 ................
0x00022264 1c00 0000 1d00 0000 1e00 0000 1f00 0000 ................
0x00022274 2000 0000 2100 0000 2200 0000 2300 0000 ...!..."...#...
0x00022284 2400 0000 2500 0000 2600 0000 2700 0000 $...%...&...'...
0x00022294 2800 0000 2900 0000 2a00 0000 2b00 0000 (...)...*...+...
0x000222a4 2c00 0000 2d00 0000 2e00 0000 2f00 0000 ,...-......./...
0x000222b4 3000 0000 3100 0000 0...1...
[0x000077e0]>
结论 :整数数组是 [0, 1, 2, ..., 49],共 50 个元素。
第十一步:编写逆向脚本
根据分析,getSecret 的加密逻辑是:
正向(加密):
- 生成
s1 = [0, 1, ..., 49] s1[i] = (s1[i] + 16) % 50- 第二个循环:字符替换(无操作)
- 第三个循环:
input[i] = (input[i] XOR i) % 128
逆向(解密):
- 逆向第三个循环:
input[i] = (i XOR input[i]) % 128 - 逆向第二个循环:字符替换(反向)
- 逆向第一个循环:
s1[i] = (s1[i] - 16) % 50
Python 脚本:
python
def rc4x(plain_text, secret_key):
# 第一步:反向 XOR i 和 % 128
plain_list = list(plain_text)
for m in range(len(plain_list)):
plain_list[m] = chr((m ^ ord(plain_list[m])) % 128)
# 第二步:生成 dest 数组
dest = [0] * 70
for i in range(len(secret_key)):
dest[i] = (i + 16) % len(secret_key)
# 第三步:字符替换(反向)
for j in range(len(plain_list)):
# 找到 plain_list[j] 在 secret_key 里的索引
first_idx = secret_key.index(plain_list[j])
# 找到 dest 里值为 first_idx 的索引
df_idx = dest.index(first_idx)
plain_list[j] = secret_key[df_idx]
return ''.join(plain_list)
# 数据库里的 secret
secret = "kEvKc|roAkNADgGExUeq"
# 字符集
charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!{|}~"
result = rc4x(secret, charset)
print(result)
运行:
bash
python3 exp.py
输出:
4ndr0id1s!ntr3st1ng!
第十二步:拼接 flag
Flag 格式 :flag{...}
内容 :4ndr0id1s!ntr3st1ng!
最终 Flag:
flag{4ndr0id1s!ntr3st1ng!}
三、这道题的解题思路总结
3.1 整体流程
APK
├── assets/test(SQLite 数据库)
│ └── user1 表:name(MD5)+ secret(加密的 flag)
├── classes.dex(Java 代码)
│ ├── MainActivity.getSecret(input) → ans
│ └── CheckAns.check(ans) → 比较 ans == secret
└── lib/arm64-v8a/libnative-lib.so(Native 库)
└── getSecret 的加密逻辑
3.2 关键步骤
- 反编译 APK → 得到 Java 代码和资源
- 分析
CheckAns→ 找到数据库查询逻辑 - 破解 MD5 →
hello对应的 MD5 是5d41402... - 查数据库 → 得到
secret = kEvKc|roAkNADgGExUeq7 - 分析
getSecret→ 在 native 库里,是 RC4 变种 - 逆向算法 → 用 Python 复现逆操作
- 得到 flag →
flag{4ndr0id1s!ntr3st1ng!}
3.3 关键技巧
| 技巧 | 说明 |
|---|---|
| APK 是 ZIP | 可以直接 unzip 查看内部文件 |
assets/ 藏数据 |
数据库、配置文件常放这里 |
classes.dex 是 Java |
用 jadx 反编译 |
lib/ 是 Native |
用 radare2/IDA 反汇编 |
| MD5 可反查 | 用 crackstation.net 或字典 |
| RC4 变种 | 注意 s1 数组的初始化和修改 |
四、附录:MD5 破解结果
| MD5 | 明文 |
|---|---|
5d41402abc4b2a76b9719d911017c592 |
hello |
912af0dff974604f1321254ca8ff38b6 |
player |
01ecd51c3cb8780d9d2138565c6b5173 |
nuaactf |
0733351879b2fa9bd05c7ca3061529c0 |
(未破解) |
70ba592665915c3c29bd16115ce6d75e |
warawara |
Flag 对应的是 hello 的 secret:
kEvKc|roAkNADgGExUeq7 → 逆向 → 4ndr0id1s!ntr3st1ng!
Rambo
2026年10月02日
🎉🎉🎉