《安卓逆向这档事》第五节课后小作业贴
本帖最后由 正己 于 2022-12-29 10:41 编辑# 一.目录
---
[《安卓逆向这档事》一、模拟器环境搭建](https://www.52pojie.cn/thread-1695141-1-1.html)
[《安卓逆向这档事》二、初识APK文件结构、双开、汉化、基础修改](https://www.52pojie.cn/thread-1695796-1-1.html)
[《安卓逆向这档事》三、初识smail,vip终结者](https://www.52pojie.cn/thread-1701353-1-1.html)
[《安卓逆向这档事》四、恭喜你获得广告&弹窗静默卡](https://www.52pojie.cn/thread-1706691-1-1.html)
[《安卓逆向这档事》五、1000-7=?&动态调试&Log插桩](https://www.52pojie.cn/thread-1714727-2-1.html)
# 二.前言
---
为了提高大家的积极性,特意开了这个作业贴。
编程这件事,一定要做好笔记,并且关掉视频自己动手实操一遍,这样效果最佳!!!
**帖子我设置只有我可见,等一周后取消,切记不要回复和作业无关内容,否则会被扣分,前50个名交作业的同学有奖励。**
交作业啦方法一:
第一步:定位提示关键字“无效用户名”,并搜索,定位到OnClick,发现调用checkSN方法做判断。
第二步:双击进入checkSN方法,在return处下断
第三步:进入调试模式,跟踪寄存器V5的值,得到SN码,注册完成
方法二:
直接在return处Log插桩打印
正己 发表于 2023-2-4 20:56
这个注册的字符串其实是写在arsc里的string,他有一个对应的id,jeb在反编译的时候会工具这个id自动生成 ...
尝试了下:
1)在arsc中搜索字符串“注册”,出来一条,点击进去发现“successed”表示“恭喜您!注册成功”;
2)再返回搜索“successed”,出来两条,其中string是刚才的,点击type-info进去,发现“0x7f05000c”表示“successed”,中间转了一次。
3)最后再回到classes.dex中搜索代码“0x7f05000c”,可以定位到关键判断。
之前对于这一个知识学的不仔细,一直不明白,终于搞懂了,谢谢正己大神。
方法三:Log插桩
1、安装完作业apk,然后进入classes.dex文件内,搜索0x7F05000B定位到代码
2、找到checkSN方法,长按跳转进方法,简单分析一下smali代码
.method private checkSN(Ljava/lang/String;Ljava/lang/String;)Z
.registers 13
.param p1, "userName"# Ljava/lang/String; 参数寄存器 p1 保存的是用户名 userName
.param p2, "sn"# Ljava/lang/String; 参数寄存器 p2 保存的是注册码 sn
.prologue
const/4 v7, 0x0# 将 0x0 存入寄存器 v7
.line 45
if-eqz p1, :cond_9# 如果 p1,即 userName 等于 0,跳转到 cond_9
:try_start_3
invoke-virtual {p1}, Ljava/lang/String;->length()I# 调用 userName.length()
move-result v8 # 将 userName.length() 的执行结果存入寄存器 v8
if-nez v8, :cond_a# 如果 v8 不等于 0,跳转到 cond_a
.line 69
:cond_9
:goto_9
return v7
.line 47
:cond_a
if-eqz p2, :cond_9 # 如果 p2,即注册码 sn 等于 0,跳转到 cond_9
invoke-virtual {p2}, Ljava/lang/String;->length()I # 执行 sn.length()
move-result v8# 将 sn.length() 执行结果存入寄存器 v8
const/16 v9, 0x10# 将 0x10 存入寄存器 v9
if-ne v8, v9, :cond_9 # 如果 sn.length != 0x10 ,跳转至 cond_9
.line 49
const-string v8, "MD5"# 将字符串 "MD5" 存入寄存器 v8
# 调用静态方法 MessageDigest.getInstance("MD5")
invoke-static {v8}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;
move-result-object v1 # 将上一步方法的返回结果赋给寄存器 v1,这里是 MessageDigest 对象
.line 50
.local v1, "digest":Ljava/security/MessageDigest;
invoke-virtual {v1}, Ljava/security/MessageDigest;->reset()V # 调用 digest.reset() 方法
.line 51
invoke-virtual {p1}, Ljava/lang/String;->getBytes()[B# 调用 userName.getByte() 方法
move-result-object v8 # 上一步得到的字节数组存入 v8
invoke-virtual {v1, v8}, Ljava/security/MessageDigest;->update() 方法
.line 52
invoke-virtual {v1}, Ljava/security/MessageDigest;->digest()[B# 调用 digest.digest() 方法
move-result-object v0 # 上一步的执行结果存入 v0,是一个 byte[] 对象
.line 53
.local v0, "bytes":[B
const-string v8, ""# 将字符串 "" 存入 v8
# 调用 MainActivity 中的 toHexString(byte[] b,String s) 方法
invoke-static {v0, v8}, Lcom/droider/crackme0201/MainActivity;->toHexString([BLjava/lang/String;)Ljava/lang/String;
move-result-object v3 # 上一步方法返回的字符串存入 v3
.line 54
.local v3, "hexstr":Ljava/lang/String;
new-instance v5, Ljava/lang/StringBuilder; # 新建 StringBuilder 对象
3、分析在第117行可知v6为最终真实的的sn注册码,只需在后面添加如下代码并保存
invoke-static {v6}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V
4、然后将log插桩dex文件放入包内并改名为classes2.dex,并打包重新安装
5、LSPosed 选中程序,算法助手开启应用总开关、Log捕获不在赘述
6、运行后随便输入用户名和注册码,翻看日志,可以看到用户名对应正确的注册码
7、进行验证,注册成功
因为最近还在学习xposed,所以就尝试写了个模块,嘿嘿
功能:输入用户名后直接点击“注册”就可以注册成功啦
```
/**
* 破解题目
*/
class HookCrackMe {
/**
* 计算注册码
*
* @Param userName 用户名
* @Return 注册码
*/
public String calculateSn(String userName) {
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("MD5");
digest.reset();
digest.update(userName.getBytes());
byte[] bytes = digest.digest();
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(b & 255);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex).append("");
}
String hexstr = hexString.toString();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hexstr.length(); i += 2) {
sb.append(hexstr.charAt(i));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public void hookCrackMe() {
XposedHelpers.findAndHookMethod("com.droider.crackme0201.MainActivity", lpparam.classLoader, "onClick", android.view.View.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// 获取“用户名”控件
EditText edit_userName = (EditText) XposedHelpers.getObjectField(param.thisObject, "edit_userName");
// 获取用户输入的用户名
String userName = edit_userName.getText().toString();
// 判断用户名是否为空
if (!"".equals(userName)) {
// 获取“注册码”控件
EditText edit_sn = (EditText) XposedHelpers.getObjectField(param.thisObject, "edit_sn");
// 计算注册码
String sn = calculateSn(userName);
if (sn != null) {
// 设置注册码
edit_sn.setText(sn);
}
}
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Button btn_register = (Button) XposedHelpers.getObjectField(param.thisObject, "btn_register");
btn_register.setEnabled(true);
btn_register.setText("已破解");
}
});
}
}
``` {:301_997:} 用户名:苏紫方璇
注册码:bf68a45158fb4f77
算法取用户名MD5的奇数位
不知道为啥,我这jeb估计有问题,用的mumu模拟器和手机真机都连不上,直接看代码猜吧 就这个样子,adb是连接上了,jdk和sdk应该也没问题,有装as可以编译安卓程序
用户名取MD5的奇数位 1)如果不看视频介绍,首先无从下手,其次是不知道关键字,看不懂代码。
2)到了调试阶段,从WINDOWS的cmd窗口执行ADB命令,出现错误提示如下: huashengyue 发表于 2022-11-19 12:25
1)如果不看视频介绍,首先无从下手,其次是不知道关键字,看不懂代码。
2)到了调试阶段,从WINDOWS的cmd ...
你的这个安装包有问题,装一下第四课的,你可以替换了activity,adb找不到这个activity
有点疑惑为啥v6显示不出来,不知道问题在哪,无奈只能用显示出的值来搞,可以看到v3是显示出来的32位可能是md5。
smail转Java分析checksn方法
看代码的意思大概是用用户名生成md5,然后根据32位md5间隔的取数字(取index为0,2,4...的数)作为密钥与输入的sn比较输出结果。那如果图1中v3显示的为md5的话直接人工间隔取出16位数就好了(有点笨QAQ)。试试,这样不知道算不算成功