学破解第213天,《初识smali,vip终结者》学习
前言:  坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:(https://www.52pojie.cn/thread-2006536-1-1.html)
**立帖为证!--------记录学习的点点滴滴**
## 0x1 初识smali,vip终结者
  1.开始第二关,先获取硬币,然后点击一键三连提示需要会员。
  2.点导航,搜索文本,可以看到搜索到了
  3.双击进去,可以看到反编译后的java代码
```
public static final boolean m27onCreate$lambda2(Ref.IntRef intRef, ChallengeSecond challengeSecond, ImageView imageView, ImageView imageView2, ImageView imageView3, View view) {
if (intRef.element < 10) {
Toast.makeText(challengeSecond, "请先获取10个硬币哦", 1).show();
}
if (challengeSecond.isvip()) {
ChallengeSecond challengeSecond2 = challengeSecond;
Toast.makeText(challengeSecond2, "当前已经是大会员了哦!", 1).show();
imageView.setImageResource(R.mipmap.zan_active);
imageView2.setImageResource(R.mipmap.coin_active);
imageView3.setImageResource(R.mipmap.collect_active);
SPUtils.INSTANCE.saveInt(challengeSecond2, "level", 2);
} else {
Toast.makeText(challengeSecond, "请先充值大会员哦!", 1).show();
}
return true;
}
```
  4.点底部的Smali按钮查看代码,发现看不到汉字,这是因为汉字存储采用了Unicode编码,找个在线转换工具,转换一下再搜索,在Smali代码里面成功定位。
```
请先充值大会员哦!
\u8bf7\u5148\u5145\u503c\u5927\u4f1a\u5458\u54e6\uff01
```
  5.查看各指令含义(详细的见原教程)。
|关键字 |注释 |
|--|--|
|const |重写整数属性,真假属性内容,只能是数字类型|
|const-string |重写字符串内容|
|const-wide |重写长整数类型,多用于修改到期时间。|
|return |返回指令|
|if-eq |全称equal(a=b),比较寄存器ab内容,相同则跳|
|if-ne |全称not equal(a!=b),ab内容不相同则跳|
|if-eqz |全称equal zero(a=0),z即是0的标记,a等于0则跳|
|if-nez |全称not equal zero(a!=0),a不等于0则跳|
|if-ge |全称greater equal(a>=b),a大于或等于则跳|
|if-le |全称little equal(a<=b),a小于或等于则跳|
|goto |强制跳到指定位置|
|switch |分支跳转,一般会有多个分支线,并根据指令跳转到适当位置|
|iget |获取寄存器数据|
  6.提取安装包,点查看,使用dex编辑plus打开dex文件,再点搜索“大会员”,先看第一个跳转if-ge,改成if-le,让他不执行比较,再在第二个if-eqz这里注释掉,直接进入大会员的流程就可以破解了,保存修改后的文件,安装在运行,直接点击一键三连,提示已经是大会员,并且点亮了图标。
```
if-ge p0, v0, :cond_15//判断硬币数量是否小于10
.line 34
move-object p0, p1
check-cast p0, Landroid/content/Context;
const-string v0, "\u8bf7\u5148\u83b7\u53d610\u4e2a\u786c\u5e01\u54e6"//请先获取10个硬币哦
check-cast v0, Ljava/lang/CharSequence;
invoke-static {p0, v0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object p0
invoke-virtual {p0}, Landroid/widget/Toast;->show()V
.line 36
:cond_15
invoke-virtual {p1}, Lcom/zj/wuaipojie/ui/ChallengeSecond;->isvip()Z
move-result p0
if-eqz p0, :cond_43//判断结果是否为真,返回1,否则返回0,跳转
.line 37
check-cast p1, Landroid/content/Context;
const-string p0, "\u5f53\u524d\u5df2\u7ecf\u662f\u5927\u4f1a\u5458\u4e86\u54e6\uff01"//当前已经是大会员了哦!
check-cast p0, Ljava/lang/CharSequence;
invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object p0
invoke-virtual {p0}, Landroid/widget/Toast;->show()V
const p0, 0x7f0d0018
.line 38
invoke-virtual {p2, p0}, Landroid/widget/ImageView;->setImageResource(I)V
const p0, 0x7f0d0008
.line 39
invoke-virtual {p3, p0}, Landroid/widget/ImageView;->setImageResource(I)V
const p0, 0x7f0d000a
.line 40
invoke-virtual {p4, p0}, Landroid/widget/ImageView;->setImageResource(I)V
.line 41
sget-object p0, Lcom/zj/wuaipojie/util/SPUtils;->INSTANCE:Lcom/zj/wuaipojie/util/SPUtils;
const/4 p2, 0x2
const-string p3, "level"
invoke-virtual {p0, p1, p3, p2}, Lcom/zj/wuaipojie/util/SPUtils;->saveInt(Landroid/content/Context;Ljava/lang/String;I)V
goto :goto_50
.line 44
:cond_43
check-cast p1, Landroid/content/Context;
const-string p0, "\u8bf7\u5148\u5145\u503c\u5927\u4f1a\u5458\u54e6\uff01"//请先充值大会员哦!
check-cast p0, Ljava/lang/CharSequence;
invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object p0
invoke-virtual {p0}, Landroid/widget/Toast;->show()V
:goto_50
return p5
```
  7.这段代码似乎哪怕我硬币不足10个也不会出现要先准备10个硬币的提示,看了半天才发现第一个if执行与否不影响第二个,因为不是嵌套关系。
  8.再来试试修改寄存器的值,将const/16 v0, 0xa,改成const/16 v0, 0x0。这样硬币数量肯定大于等于0
```
在smali里的所有操作都必须经过寄存器来进行:
本地寄存器用v开头数字结尾的符号来表示,如v0、 v1、v2。
参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2。
特别注意的是,p0不一定是函数中的第一个参数,在非static函数中,p0代指“this",p1表示函数的第一个 参数,p2代表函数中的第二个参数。
而在static函数中p0才对应第一个参数(因为Java的static方法中没有this方法)
```
  9.在找到isvip函数,长按再点三个点,然后点跳转就可以进入函数内部,可以看到直接return 0不是会员,这里将const/4 v0, 0x0改成const/4 v0, 0x1让他返回结果为真,保存。
```
# virtual methods
.method public final isvip()Z
.registers 2
const/4 v0, 0x0
return v0
.end method
```
## 0x2 作业
  1.安装作业apk观察一下,需要输入用户名和密码,直接点登录会提示登录失败。
  2.同样用jadx搜索字符串,定位到关键代码:(直接就看到了用户名和密码,当然了我们的目的是为了用刚刚学习的技术)
```
public void check(String name, String pass) {
if (!name.equals("hfdcxy") || !pass.equals("1234")) {
Toast.makeText(this, "登录失败", 0).show();
} else {
Toast.makeText(this, "登录成功", 0).show();
}
}
```
  3.查看Smali代码,两个if-eqz,如果跳转到cond_1b代码块就登录失败,所以我们加个#号注释掉这两行代码就可以了。
```
.prologue
const/4 v1, 0x0
.line 28
const-string v0, "hfdcxy"
invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :cond_1b
const-string v0, "1234"
invoke-virtual {p2, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :cond_1b
.line 30
const-string v0, "\u767b\u5f55\u6210\u529f"//登录成功
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
.line 34
:goto_1a
return-void
.line 33
:cond_1b
const-string v0, "\u767b\u5f55\u5931\u8d25"//登录失败
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
```
  4.改完之后保存,重新安装,直接点登录,登陆成功。
## 0x3 参考文档
  1.[初识smali,vip终结者](https://www.52pojie.cn/thread-1701353-1-1.html) 精神可嘉,学习了 精神可嘉, 向楼主学习 坚持不懈的精神{:1_921:} 楼主强{:1_921:}学习之~ 坚持不懈强悍楼主 , 能坚持学习很不错 楼主太强了,从刚开始到现在学了多久了啊 记录学习的点点滴滴 楼主真强