【Android逆向】破解黑宝宝apk,绕过签名校验
这是52pojie的一道题,实现输入任何密码都可以登录成功
他知道你最近在学习Android逆向 他想在游戏上线前让你测试一下他新加的签名验证是否能防住别人的破解。
下面是李华编写的黑宝宝apk
链接:https://pan.baidu.com/s/1h6pX2ARE3qtiKiYbcnJ-3g 密码:duv5
1. apk拖入到jadx中, 关键逻辑
//MainActivity.java
Button_regist.setOnClickListener(new View.OnClickListener() { // from class: demo2.jni.com.myapplication.MainActivity.1
@Override // android.view.View.OnClickListener
public void onClick(View view) {
Toast.makeText(MainActivity.this,
MainActivity.this.mj.check(
MainActivity.this.ct,
MainActivity.this.User_Name.getText().toString().trim(),
MainActivity.this.User_Pass.getText().toString().trim()), 0)
.show();
}
});
//myJNI.java
public class myJNI {
public native String check(Object obj, String str, String str2);
static {
System.loadLibrary("JniTest");
}
}
2. 看来答案在JniTest.so中,将so拖入到idapro中,稍微整理一下代码,反汇编可得
整理步骤:
1. 入参重命名, a1 改为 JNIEnv *env 等
2. 对于显示位乱码的数据,或者展示不出来的,多半可能是中文,可以按住alt+A键打开ASCII string style窗口
然后点击set default encodings 在弹出框中选择8-bit的change 选择utf-8后点击ok回到c语言界面按f5刷新一下界面 乱码问题解决
反汇编代码
int __fastcall Java_demo2_jni_com_myapplication_myJNI_check(
JNIEnv *env,
jobject object,
int context,
int username,
int password)
{
void *Signature; // r0
const char *v8; // r6
const char *v9; // r8
const char *v10; // r7
int v11; // r0
JNIEnv v12; // r5
Signature = (void *)getSignature(env, object, context);
v8 = (*env)->GetStringUTFChars(env, Signature, 0);
v9 = (*env)->GetStringUTFChars(env, username, 0);
v10 = (*env)->GetStringUTFChars(env, password, 0);
_android_log_print(4, "JNI_LOG", aJni, v8);
if ( !strcmp(
v8,
"308201dd30820146020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f6964204465627567311030"
"0e060355040a0c07416e64726f6964310b3009060355040613025553301e170d3138303332313033303431385a170d3438303331333033"
"303431385a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603"
"5504061302555330819f300d06092a864886f70d010101050003818d00308189028181008270f53e2cf8c7d7ed200863deb85a054defde"
"773be0b848ee792839d9a81da098dd9b74bbb9679c19ea30b63fe3bb74aabb270a5c9b3359ebe3fdf278b82fe576a6677f0d77f0eb5b08"
"8d0711b15d03cadae08b3b980f28055d0cde4bbc4a0b4b208b0f30f170b6ea77a8620269fa1d375442653663e1dd41293aa1c4910e3502"
"03010001300d06092a864886f70d010105050003818100044b9ab7e85346a147926c2d1c6c30e8ffcce174f88acb9763cb776fb1f4dd62"
"183c9524346738ff1aea16c5fa218c68da76d05a2422aee12fc23563b5e28925c3d96dff855a584fc1ec462aa768277bd25739085d52fe"
"3fedfd396e38180c13fbb289786e524535933dd8a99ed3154880544f3e41f044acc43ceefbbce3af59") )
{
_android_log_print(4, "JNI_LOG", byte_23BA);
exit(0);
}
_android_log_print(4, "JNI_LOG", byte_23A6);
v11 = strcmp(v9, "koudai");
v12 = *env;
if ( !v11 || !strcmp(v10, "black") )
return (int)v12->NewStringUTF(env, byte_23EA);
else
return (int)v12->NewStringUTF(env, byte_23DD);
}
3. 这里可以看到,首先做了一个签名校验,那么只要我们重打包,必然运行失败,然后做了账号密码的校验
这里留的题目是输入任何密码都可以登录成功,那么我们可以看看汇编代码的条件处
.text:00000EB8
.text:00000EB8 ; =============== S U B R O U T I N E =======================================
.text:00000EB8
.text:00000EB8
.text:00000EB8 ; int __fastcall Java_demo2_jni_com_myapplication_myJNI_check(int *, int, int, int, int)
.text:00000EB8 EXPORT Java_demo2_jni_com_myapplication_myJNI_check
.text:00000EB8 Java_demo2_jni_com_myapplication_myJNI_check
.text:00000EB8 ; DATA XREF: LOAD:000001FC↑o
.text:00000EB8
.text:00000EB8 arg_0= 0
.text:00000EB8
.text:00000EB8 ; __unwind {
.text:00000EB8 2D E9 F0 41 PUSH.W {R4-R8,LR}
.text:00000EBC 04 46 MOV R4, R0
.text:00000EBE 1F 46 MOV R7, R3
.text:00000EC0 FF F7 5C FF BL getSignature
.text:00000EC0
.text:00000EC4 22 68 LDR R2, [R4]
.text:00000EC6 D2 F8 A4 32 LDR.W R3, [R2,#0x2A4]
.text:00000ECA 00 22 MOVS R2, #0
.text:00000ECC 01 46 MOV R1, R0
.text:00000ECE 20 46 MOV R0, R4
.text:00000ED0 98 47 BLX R3
.text:00000ED0
.text:00000ED2 22 68 LDR R2, [R4]
.text:00000ED4 39 46 MOV R1, R7
.text:00000ED6 D2 F8 A4 52 LDR.W R5, [R2,#0x2A4]
.text:00000EDA 00 22 MOVS R2, #0
.text:00000EDC 06 46 MOV R6, R0
.text:00000EDE 20 46 MOV R0, R4
.text:00000EE0 A8 47 BLX R5
.text:00000EE0
.text:00000EE2 23 68 LDR R3, [R4]
.text:00000EE4 06 99 LDR R1, [SP,#0x18+arg_0]
.text:00000EE6 00 22 MOVS R2, #0
.text:00000EE8 1F 4D LDR R5, =(aJniLog - 0xEF2) ; "JNI_LOG"
.text:00000EEA D3 F8 A4 32 LDR.W R3, [R3,#0x2A4]
.text:00000EEE 7D 44 ADD R5, PC ; "JNI_LOG"
.text:00000EF0 80 46 MOV R8, R0
.text:00000EF2 20 46 MOV R0, R4
.text:00000EF4 98 47 BLX R3
.text:00000EF4
.text:00000EF6 1D 4A LDR R2, =(aJni - 0xF00) ; "JNI"
.text:00000EF8 29 46 MOV R1, R5 ; tag
.text:00000EFA 33 46 MOV R3, R6
.text:00000EFC 7A 44 ADD R2, PC ; "JNI" ; fmt
.text:00000EFE 07 46 MOV R7, R0
.text:00000F00 04 20 MOVS R0, #4 ; prio
.text:00000F02 FF F7 CC EE BLX __android_log_print
.text:00000F02
.text:00000F06 1A 49 LDR R1, =(a308201dd308201 - 0xF0E) ; "308201dd30820146020101300d06092a864886f"...
.text:00000F08 30 46 MOV R0, R6 ; char *
.text:00000F0A 79 44 ADD R1, PC ; "308201dd30820146020101300d06092a864886f"...
.text:00000F0C FF F7 CC EE BLX strcmp
.text:00000F0C
.text:00000F10 68 B9 CBNZ R0, loc_F2E
.text:00000F10
.text:00000F12 18 4A LDR R2, =(byte_23A6 - 0xF1C)
.text:00000F14 29 46 MOV R1, R5 ; tag
.text:00000F16 04 20 MOVS R0, #4 ; prio
.text:00000F18 7A 44 ADD R2, PC ; byte_23A6 ; fmt
.text:00000F1A FF F7 C0 EE BLX __android_log_print
.text:00000F1A
.text:00000F1E 16 49 LDR R1, =(aKoudai - 0xF26) ; "koudai"
.text:00000F20 40 46 MOV R0, R8 ; char *
.text:00000F22 79 44 ADD R1, PC ; "koudai"
.text:00000F24 FF F7 C0 EE BLX strcmp
.text:00000F24
.text:00000F28 25 68 LDR R5, [R4]
.text:00000F2A 48 B1 CBZ R0, loc_F40
.text:00000F2A
.text:00000F2C 14 E0 B loc_F58
.text:00000F2C
.text:00000F2E ; ---------------------------------------------------------------------------
.text:00000F2E
.text:00000F2E loc_F2E ; CODE XREF: Java_demo2_jni_com_myapplication_myJNI_check+58↑j
.text:00000F2E 13 4A LDR R2, =(byte_23BA - 0xF38)
.text:00000F30 04 20 MOVS R0, #4 ; prio
.text:00000F32 29 46 MOV R1, R5 ; tag
.text:00000F34 7A 44 ADD R2, PC ; byte_23BA ; fmt
.text:00000F36 FF F7 B2 EE BLX __android_log_print
.text:00000F36
.text:00000F3A 00 20 MOVS R0, #0 ; int
.text:00000F3C FF F7 BA EE BLX exit
.text:00000F3C
.text:00000F40 ; ---------------------------------------------------------------------------
.text:00000F40
.text:00000F40 loc_F40 ; CODE XREF: Java_demo2_jni_com_myapplication_myJNI_check+72↑j
.text:00000F40 0F 49 LDR R1, =(aBlack - 0xF48) ; "black"
.text:00000F42 38 46 MOV R0, R7 ; char *
.text:00000F44 79 44 ADD R1, PC ; "black"
.text:00000F46 FF F7 B0 EE BLX strcmp
.text:00000F46
.text:00000F4A 28 B9 CBNZ R0, loc_F58
.text:00000F4A
.text:00000F4C 0D 49 LDR R1, =(unk_23DD - 0xF58)
.text:00000F4E 20 46 MOV R0, R4
.text:00000F50 D5 F8 9C 32 LDR.W R3, [R5,#0x29C]
.text:00000F54 79 44 ADD R1, PC ; unk_23DD
.text:00000F56 04 E0 B loc_F62
.text:00000F56
.text:00000F58 ; ---------------------------------------------------------------------------
.text:00000F58
.text:00000F58 loc_F58 ; CODE XREF: Java_demo2_jni_com_myapplication_myJNI_check+74↑j
.text:00000F58 ; Java_demo2_jni_com_myapplication_myJNI_check+92↑j
.text:00000F58 0B 49 LDR R1, =(unk_23EA - 0xF64)
.text:00000F5A 20 46 MOV R0, R4
.text:00000F5C D5 F8 9C 32 LDR.W R3, [R5,#0x29C]
.text:00000F60 79 44 ADD R1, PC ; unk_23EA
.text:00000F60
.text:00000F62
.text:00000F62 loc_F62 ; CODE XREF: Java_demo2_jni_com_myapplication_myJNI_check+9E↑j
.text:00000F62 98 47 BLX R3
.text:00000F62
.text:00000F64 BD E8 F0 81 POP.W {R4-R8,PC}
.text:00000F64
.text:00000F64 ; End of function Java_demo2_jni_com_myapplication_myJNI_check
要修改的行
[1] 对应着签名条件的跳转
.text:00000F10 68 B9 CBNZ R0, loc_F2E
[2] 对应着username判断条件的跳转
.text:00000F2A 48 B1 CBZ R0, loc_F40
[3] 对应着password判断条件的跳转
.text:00000F4A 28 B9 CBNZ R0, loc_F58
查汇编与机器码对应关系可知
B9 对应 CBNZ
B1 对应 CBZ
那么只要把它们反过来就可以了
鼠标点住那行命令 View->Open subviews->Hex dump打开16进制编辑 ,
选中要改的机器码,按F2, 修改完毕后再按F2,表示修改完毕
4. 保存so的修改 : Edit -> Patch Program -> apply patch into file 进行保存
5. 对apk进行重打包,重签名,安装到手机,输入任何内容,显示登陆成功
【Android逆向】破解黑宝宝apk,绕过签名校验的更多相关文章
- 重打包APK绕过签名校验
这里先提一种针对性校强但简单好理解的办法,纯Java实现,代码大概也就50行不到吧. 还有更强的并且能过各种保护(反调试反HOOK反内存修改等等)的万能方法,不过较复杂,长篇大论的,等有空整理出来再提 ...
- Android5.1.1 - APK签名校验分析和修改源码绕过签名校验
Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...
- Android逆向破解表单注册程序
Android逆向破解表单注册程序 Android开发 ADT: android studio(as) 程序界面如下,注册码为6位随机数字,注册成功时弹出通知注册成功,注册失败时弹出通知注册失败. 布 ...
- Android逆向破解表单登录程序
Android逆向破解表单登录程序 Android开发 ADT: android studio(as) 程序界面如下,登录成功时弹出通知登录成功,登录失败时弹出通知登录失败. 布局代码 <?xm ...
- Android逆向 破解第一个Android程序
这节正式开始破解编写的第一个Android工程,打开Android Killer,把第一节自己编写的Android apk拖入Android Killer. PS: 如果Android Killer不 ...
- android: 使用android逆向助手反编译APK
第一步:下载逆向助手:(链接: https://pan.baidu.com/s/15jtoFDg9LWV80HREeyx5HA 提取码: k527 ) 第二步:将apk文件拷贝到逆向助手的apktoo ...
- Android逆向——破解水果大战
最近公司需要测试安卓app安全,但安卓基本上0基础,决定开始学习下安卓逆向根据吾爱破解上教程 <教我兄弟学Android逆向系列课程+附件导航帖> https://www.52pojie. ...
- Apk去签名校验详解
某些apk为了防止重打包,使用了签名校验.所以在破解的时候我们需要破解签名校验.在定位签名校验位置时常用的关键词有sign,signature,checkSign,signCheck,getPacka ...
- Android逆向破解:Android Killer使用
目录 目录 软件介绍 Android Killer是一款可以对APK进行反编译的工具,它能够对反编译后的Smali文件进行修改,并将修改后的文件进行打包. 软件下载 这里用的是@昨夜星辰2012 ...
- apk文件签名绕过
声明: 1.本文转载自:http://www.2cto.com/Article/201311/256406.html,为了留作日后参考上传博客 2.如有转载请复试上面连接,尊重原创 apk文件签名绕过 ...
随机推荐
- [转帖]mysql - 使用文件中的 mysql 加载数据格式化 csv 日期列
https://www.coder.work/article/2481907#:~:text=LOAD%20DATA%20INFILE%20%27%2Finvoices%2Finvoice138130 ...
- [转帖]LSM树详解
https://zhuanlan.zhihu.com/p/181498475 LSM树(Log-Structured-Merge-Tree)的名字往往会给初识者一个错误的印象,事实上,LSM树并不像B ...
- jcmd的简要分析命令
jcmd的简要分析命令 背景 端午加班一整天. 回到家同事让他们抓取一下堆栈信息好进行分析 连上VPN后就进行了一下处理. 自己简单看了下堆栈的总数等信息. 同事使用工具进行了分析. 我这边其实下过很 ...
- Python学习之九_winrm执行远程机器的cmd命令
Python学习之九_winrm执行远程机器的cmd命令 winrm # 注意如下命令需要按照顺序执行. # 打开powershell的管理员模式进行如下的操作. set-executionpolic ...
- [转帖]springcloud nacos配置
配置文件中的nacos配置,discovery和config配置项 版本: <spring.boot.version>2.3.2.RELEASE</spring.boot.versi ...
- [转帖]公钥基础设施(PKI,Public Key Infrastructure)闲谈
https://zhuanlan.zhihu.com/p/384436119 背景 在现实空间中,人类的活动范围和接触人的范围有限,人和人最初的信任是建立在小团体或部落内部.随着全球化进展,人类的活动 ...
- Java单元测试浅析(JUnit+Mockito)
作者:京东物流 秦彪 1. 什么是单元测试 (1)单元测试环节: 测试过程按照阶段划分分为:单元测试.集成测试.系统测试.验收测试等.相关含义如下: 1) 单元测试: 针对计算机程序模块进 ...
- SpringBoot中Bean的条件装配
目录 概述 Profile Conditional ConditionalOn ConditionalOnProperty 概述 众所周知,SpringBoot最腻害的地方就是容器,开发人员的日常工作 ...
- 往返回来的数据数组Array中添加一个字段的最优写法
在工作中我们经常会对后端返回来的数据进行添加一个字段: 最优的写法是 直接在 res.data[i].xx=aa 这样的方式去添加: 添加好了之后美酒 可以去赋值了: 让表格去渲染数据 this.$a ...
- 【JS 逆向百例】网洛者反爬练习平台第二题:JJEncode 加密
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...