前言
在我之前刷CTF题的时候,曾遇到过调试so文件的题,现在看来其中的一些有关JEB动态调试的知识在这节教程之中还是用得到的,相关链接指路:[SWPU 2019]easyapp——Androidの初体验 – Xm's Blog
本教程使用的jeb需要java环境的,想起曾经写过有关Java环境与JEB的配置的教程,待会直接cv到下面
教程地址:《安卓逆向这档事》五、1000-7=?&动态调试&Log插桩 - 吾爱破解 - 52pojie.cn
环境配置
去52论坛上搜了个教程,不知道行不行,先试试看吧
JEB动态调试Smali-真机/模拟器(详细,新手必看) - 『移动安全区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
在这之前先去配置JAVA环境java 环境配置(详细教程)_java环境配置-CSDN博客
JAVA环境配置
安装jdk
先去安装jdkJava 下载 |Oracle 中国
这里我挂了梯子,不知道这个中国站点需不需要挂

进入官网下载x64安装程序,下载好之后创建应该文件夹双击进行安装

安装完成之后配置环境变量

新建

变量值为jdk安装的文件夹,再去设置Path变量

将%Java_Home%\bin;%Java_Home%\jre\bin;放到变量值最前面,点击确认保存

这样就配置好了,终端可以看见的

安装JEB

在此链接下载:百度网盘 请输入提取码 (baidu.com)
解压之后跟着教程将fix文件夹下的jeb.jar复制并替换到jeb\bin\app文件夹下
双击jeb_wincon.bat打开并激活
………………
JEB的使用
在教程demo的第四关,我们点击验证会返回一个密钥错误的结果

所以我们可以根据返回的结果去搜索字符串所在的代码行
我们使用jeb打开教程窗口
在最下面一栏可以快速搜索字符串等内容

直接可以定位到所在的类里面
package com.zj.wuaipojie.ui;
import android.content.Context;
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;
import com.zj.wuaipojie.Encode;
import com.zj.wuaipojie.util.Base64Utils;
import com.zj.wuaipojie.util.SPUtils;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.text.Charsets;
import kotlin.text.StringsKt;
@Metadata(d1 = {"\u0000$\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u000B\n\u0000\n\u0002\u0010\u000E\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u000E\u0010\u0003\u001A\u00020\u00042\u0006\u0010\u0005\u001A\u00020\u0006J\u0012\u0010\u0007\u001A\u00020\b2\b\u0010\t\u001A\u0004\u0018\u00010\nH\u0014¨\u0006\u000B"}, d2 = {"Lcom/zj/wuaipojie/ui/ChallengeFourth;", "Landroidx/appcompat/app/AppCompatActivity;", "()V", "check", "", "str", "", "onCreate", "", "savedInstanceState", "Landroid/os/Bundle;", "app_release"}, k = 1, mv = {1, 7, 1}, xi = 0x30)
public final class ChallengeFourth extends AppCompatActivity {
public final boolean check(String s) {
int v = 0;
Integer integer0 = null;
if(!StringsKt.startsWith$default(s, "flag{", false, 2, null)) {
return false;
}
if(!StringsKt.endsWith$default(s, "}", false, 2, null)) {
return false;
}
String s1 = s.substring(5, s.length() - 1);
Intrinsics.checkNotNullExpressionValue(s1, "this as java.lang.String…ing(startIndex, endIndex)");
String s2 = SPUtils.INSTANCE.getString(((Context)this), "id", "");
if(s2 != null) {
integer0 = (int)s2.length();
}
int v1 = 1000;
Intrinsics.checkNotNull(integer0);
int v2 = (int)integer0;
if(v2 >= 0) {
while(true) {
v1 += -7;
if(v == v2) {
break;
}
++v;
}
}
byte[] arr_b = Encode.encode(s2 + v1).getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(arr_b, "this as java.lang.String).getBytes(charset)");
return Intrinsics.areEqual(s1, Base64Utils.INSTANCE.encodeToString(arr_b));
}
@Override // androidx.fragment.app.FragmentActivity
protected void onCreate(Bundle bundle0) {
super.onCreate(bundle0);
this.setContentView(0x7F0B001E); // layout:activity_challenge_fourth
((Button)this.findViewById(0x7F08006B)).setOnClickListener((View view0) -> {
if(this.check(((EditText)this.findViewById(0x7F0800AC)).getText().toString())) { // id:edit_check
Context context0 = (Context)this;
Toast.makeText(context0, "恭喜你,密钥正确!", 1).show();
SPUtils.INSTANCE.saveInt(context0, "level", 3);
return;
}
Toast.makeText(((Context)this), "密钥错误哦,再想想!", 1).show();
});
}
// Detected as a lambda impl.
private static final void onCreate$lambda-0(ChallengeFourth challengeFourth0, EditText editText0, View view0) {
if(challengeFourth0.check(editText0.getText().toString())) {
Context context0 = (Context)challengeFourth0;
Toast.makeText(context0, "恭喜你,密钥正确!", 1).show();
SPUtils.INSTANCE.saveInt(context0, "level", 3);
return;
}
Toast.makeText(((Context)challengeFourth0), "密钥错误哦,再想想!", 1).show();
}
}
分析代码之后我们直接在加密值返回的地方下一个断点

接下来就是debug了,我们在cmd里面输入下面这一串就可以了
adb shell am start -D -n com.zj.wuaipojie/.ui.MainActivity
db shell am start -D -n
adb shell am start -D -n 包名/类名
am start -n 表示启动一个activity
am start -D 表示将应用设置为可调试模式
开始调试

点击下面的附上之后就开始调试了
然后回到模拟器or真机中,能看见软件已经开始运行,我们进入第四关,然后随便输点什么,点击验证,就能看见程序在我们的断点处断下来了

我们断点断在
000000E0 invoke-virtual Base64Utils->encodeToString([B)String, v1, v0这一行
F6进入方法
F7跳过方法
F8从方法中跳出来
R运行到光标处
因此可以F6步进encodeToString

这样我们就能看见encodeToString方法了
这时我们走到该方法返回值的地方

能看见左侧的变量值窗口已经显示出你所得到的密钥了

回到程序中输入之后便可得到密钥正确的返回结果
Log插桩
教程中给了大佬写的dex文件,我们可以将文件打包进apk当中进行安装

将其命名为classes2.dex添加进去
然后进入classes.dex里面定位到之前找到的encodeString

这里能看见返回值是给到v0的
所以我们将下面这一行插到move-result-object v0行的后面
invoke-static {v0}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V
再去算法助手里面把Log捕获打开

后面我们查看日志就能看见返回的结果啦

