移动安全:Smali语法学习示例与实践
文章目录
- 前言
- 一、Smali简介
- 二、Smali语法简介
- 1.基本类型
- 2.引用类型
- 3.方法体定义
- 4.关键字
- 5.寄存器类别区分
- 6.条件跳转
- 7.Smali针对函数返回结果的操作
- 8.Smali变量操作权限
- 三、阅读部分
- APK效果
- 打包和反编译
- 阅读
- 四、实际操作部分
- 总结
前言
本节介绍移动安全相关知识中的Smali语法,并自主动手完成一个小练习
一、Smali简介
Smali是Android虚拟机Davlik的寄存器语言,语法上和汇编语言类似. Davlik是基于寄存器的,就是说smali里的所有操作都必须经过寄存器来进行.
简单来说就是高级语言Java和机器语言的一个中间层代码语言,执行效率相比高级语言更加高效,更加贴近底层,通过我们用Apktool反编译APK出来的结果中便会含有Smali文件夹,文件夹下的内容就是Smali语言
本节主要针对基于Java编写的Android应用反编译出的Smali文件进行分析。
二、Smali语法简介
1.基本类型
B—byte
C—char
D—double
F—float
I—int
S—short
V—void
J—long
Z—boolean
2.引用类型
- [XXX->X代表类型的数组
例:
[B -->Byte[]
[I -->Int[] - Lxx/yyy -->Object对象
例如:
String str–>str Ljava/lang/String;
subobjectName objectName->objectName LpackageaName/objectNamesubobjectName注:这里的subobjectName 注:这里的subobjectName注:这里的符号代表内部类,内部类的含义我就不用解释了吧
3.方法体定义
方法体格式:
Func-Name (Para-Type1Para-Type2Para-Type3…)Return-Type 注意: 参数之间没有任何分隔符,返回值在最后
例:
void hello() —> hello()V
boolean hello(int,int,int) —>hello(III)Z
String fun(boolean, int[], int[], String, long)
—>fun(Z[I[ILjava/lang/String,J)Ljava/lang/String
4.关键字
- .field private isFlag:z 定义变量
- .method 方法
- .parameter 方法参数
- .prologue 方法开始
- .line123 此方法开始于123行
- invoke-super 调用父函数
- const/high16 v0,0x7fox 把0x7fox的值赋值给v0
- invoke-direct 调用函数
- return-void 函数返回void
- .end method 函数结束
- new-instance 创建实例
- iput-object 对象赋值
- iget-object 调用对象
- invoke-static 调用静态函数
- .class public Lcom/disney/WMW/WMWActivty; 类名
- .super Lcom/XXX/XXX/XXX; 父类名
- .source “XXX.java” 源文件名
- .implements Lcom/XXX/XXX/XXX; 实现了接口
- .annotation 内部类
5.寄存器类别区分
寄存器v,本地寄存器 (local register, 非参寄存器)
常用v开头数字结尾的符号表示 v0,v1,v2…
可以看到这里的locals后面的参数为2,表明使用两个v开头的本地寄存器,若修改数量为1,可以编译通过,但是运行时,会发生错误寄存器p,参数寄存器 (parameter regisgter)
常用p开头数字结尾的符号来表示 p0,p1,p2,p3…
# direct methods
.method public constructor <init>()V.locals 0.line 18invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;-><init>()Vreturn-void
.end method
p0为非静态方法自动创建的寄存器,存储着this,也就是该方法所属类的实例本身,例如这段函数中,一个Activity invoke-direct调用其父类AppCompatActivity的init()方法,传入的参数是这个实例本身的this
6.条件跳转
- if-eq vA,vB, :cond_** 如果vA等于vB,则跳转到:cond_**
- if-ne vA,vB, :cond_** 如果vA不等于vB,则跳转到:cond_**
- if-lt vA,vB, :cond_** 如果vA小于vB,则跳转到:cond_**
- if-ge vA,vB, :cond_** 如果vA大于等于vB,则跳转到:cond_**
- if-gt vA,vB, :cond_** 如果vA大于vB,则跳转到:cond_**
- if-le vA,vB, :cond_** 如果vA小于等于vB,则跳转到:cond_**
- if-eqz vA, :cond_** 如果vA等于0,则跳转到:cond_**
- if-nez vA, :cond_** 如果vA不等于0,则跳转到:cond_**
- if-ltz vA, :cond_** 如果vA小于0,则跳转到:cond_**
- if-gez vA, :cond_** 如果vA大于等于0,则跳转到:cond_**
- if-gtz vA, :cond_** 如果vA大于0,则跳转到:cond_**
- if-lez vA, :cond_** 如果vA小于等于0,则跳转到:cond_**
7.Smali针对函数返回结果的操作
在Java代码中调用函数和返回函数结果可以只用一条语句来表示,如:
A=getPoint();
但在Smali里则需要分开完成,在使用上述指令后,如果调用的函数返回非void, 那么还需要用到move-result(返回基本函数类型)和move-result-object(返回对象指令);
例:
const-string v0,"Eric"invoke-static {v0},Lcmb/pbi;->t(Ljava/lang/String)LJava/lang/String;move-result-object v2
此时v2保存的就是调用t方法得到的String字符串
8.Smali变量操作权限
字段操作指令表示对对象字段进行设值和取值操作,就像是你在代码中长些的set和get方法.基本指令是iput-type,iget-type,sput-type,sget-type.type表示数据类型.
普通字段读写操作
前缀是i的iput-type和iget-type指令用于字段的读写操作.
指令 描述
- iget-object vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id对象的引用值给vBB寄存器
- iget-boolean vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id的值给vBB寄存器
- iget-wide vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id的值给vBB寄存器
- iget vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id的值给vBB寄存器
- iput-object vAA,vBB,filed_id 把vAA寄存器指向的对象的引用赋值给vBB寄存器中的filed_id对象
- iput-boolean vAA,vBB,filed_id 把vAA寄存器的值给vBB寄存器中的boolean类型
- iput-wide vAA,vBB,filed_id 把vAA寄存器的值给vBB寄存器中的wide类型
- iput vAA,vBB,filed_id 把vAA寄存器的值给vBB寄存器中的int类型
静态字段读写操作
前缀是s的sput-type和sget-type指令用于静态字段的读写操作
指令 描述
- sget-object vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id对象的引用值给vBB寄存器
- sget-boolean vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id的值给vBB寄存器
- sget-wide vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id的值给vBB寄存器
- sget vAA,vBB,filed_id 读取vAA寄存器中的对象中的filed_id的值给vBB寄存器
- sput-object vAA,vBB,filed_id 把vAA寄存器指向的对象的引用赋值给vBB寄存器中的filed_id对象
- sput-boolean vAA,vBB,filed_id 把vAA寄存器的值给vBB寄存器中的boolean类型
- sput-wide vAA,vBB,filed_id 把vAA寄存器的值给vBB寄存器中的wide类型
- sput vAA,vBB,filed_id 把vAA寄存器的值给vBB寄存器中的int类型
三、阅读部分
我们这里采取自己动手打包一个登录验证的APK进行阅读和练习
APK效果
登录界面
登陆后的界面
打包和反编译
打包用AS一键打包
反编译用APKTool对APK进行反编译出相关Smali代码
点击Smali用VS Code工具进行阅读
阅读
MainActivity.smali
.class public Lcom/example/androidsafetest01/MainActivity;//包名+类名
.super Landroidx/appcompat/app/AppCompatActivity;//父类名称
.source "MainActivity.java"//.source 源文件名称# instance fields
.field private btn:Landroid/widget/Button;.field private editText:Landroid/widget/EditText;//实例变量 变量名称:包名# direct methods
.method public constructor <init>()V//方法开始.locals 0.line 12//这个方法对应Java代码中的12行invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;-><init>()V//调用父类中的构造函数,返回值为空return-void
.end method//方法结束.method static synthetic access$000(Lcom/example/androidsafetest01/MainActivity;)Landroid/widget/EditText;.locals 0.line 12iget-object p0, p0, Lcom/example/androidsafetest01/MainActivity;->editText:Landroid/widget/EditText;//将MainActivity的id值送给EditText,初步猜测是在给权限return-object p0
.end method.method private initEvent()V.locals 2//使用了两个寄存器.line 26iget-object v0, p0, Lcom/example/androidsafetest01/MainActivity;->btn:Landroid/widget/Button;new-instance v1, Lcom/example/androidsafetest01/MainActivity$1;invoke-direct {v1, p0}, Lcom/example/androidsafetest01/MainActivity$1;-><init>(Lcom/example/androidsafetest01/MainActivity;)Vinvoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V//调用实例的虚方法return-void
.end method.method private initView()V.locals 1const v0, 0x7f08008f.line 44invoke-virtual {p0, v0}, Lcom/example/androidsafetest01/MainActivity;->findViewById(I)Landroid/view/View;move-result-object v0check-cast v0, Landroid/widget/EditText;iput-object v0, p0, Lcom/example/androidsafetest01/MainActivity;->editText:Landroid/widget/EditText;const v0, 0x7f080057.line 45invoke-virtual {p0, v0}, Lcom/example/androidsafetest01/MainActivity;->findViewById(I)Landroid/view/View;move-result-object v0check-cast v0, Landroid/widget/Button;iput-object v0, p0, Lcom/example/androidsafetest01/MainActivity;->btn:Landroid/widget/Button;return-void
.end method# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V.locals 0.annotation system Ldalvik/annotation/MethodParameters;accessFlags = {0x0}names = {"savedInstanceState"}.end annotation.line 19invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)Vconst p1, 0x7f0b001d.line 20invoke-virtual {p0, p1}, Lcom/example/androidsafetest01/MainActivity;->setContentView(I)V.line 21invoke-direct {p0}, Lcom/example/androidsafetest01/MainActivity;->initView()V.line 22invoke-direct {p0}, Lcom/example/androidsafetest01/MainActivity;->initEvent()Vreturn-void
.end method
MainActivity$1.smali
.class Lcom/example/androidsafetest01/MainActivity$1;
.super Ljava/lang/Object;
.source "MainActivity.java"# interfaces
.implements Landroid/view/View$OnClickListener;# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;value = Lcom/example/androidsafetest01/MainActivity;->initEvent()V
.end annotation.annotation system Ldalvik/annotation/InnerClass;accessFlags = 0x0name = null
.end annotation# instance fields
.field final synthetic this$0:Lcom/example/androidsafetest01/MainActivity;# direct methods
.method constructor <init>(Lcom/example/androidsafetest01/MainActivity;)V.locals 0.annotation system Ldalvik/annotation/MethodParameters;accessFlags = {0x8010}names = {"this$0"}.end annotation.line 26iput-object p1, p0, Lcom/example/androidsafetest01/MainActivity$1;->this$0:Lcom/example/androidsafetest01/MainActivity;invoke-direct {p0}, Ljava/lang/Object;-><init>()Vreturn-void
.end method# virtual methods
.method public onClick(Landroid/view/View;)V.locals 2.annotation system Ldalvik/annotation/MethodParameters;accessFlags = {0x0}names = {"view"}.end annotation.line 29iget-object p1, p0, Lcom/example/androidsafetest01/MainActivity$1;->this$0:Lcom/example/androidsafetest01/MainActivity;invoke-static {p1}, Lcom/example/androidsafetest01/MainActivity;->access$000(Lcom/example/androidsafetest01/MainActivity;)Landroid/widget/EditText;move-result-object p1invoke-virtual {p1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;move-result-object p1invoke-virtual {p1}, Ljava/lang/Object;->toString()Ljava/lang/String;move-result-object p1if-eqz p1, :cond_0.line 30invoke-virtual {p1}, Ljava/lang/String;->length()Imove-result v0if-eqz v0, :cond_0const-string v0, "123456".line 31invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Zmove-result p1if-eqz p1, :cond_1.line 32new-instance p1, Landroid/content/Intent;iget-object v0, p0, Lcom/example/androidsafetest01/MainActivity$1;->this$0:Lcom/example/androidsafetest01/MainActivity;invoke-virtual {v0}, Lcom/example/androidsafetest01/MainActivity;->getApplicationContext()Landroid/content/Context;move-result-object v0const-class v1, Lcom/example/androidsafetest01/EndActivity;invoke-direct {p1, v0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V.line 33iget-object v0, p0, Lcom/example/androidsafetest01/MainActivity$1;->this$0:Lcom/example/androidsafetest01/MainActivity;invoke-virtual {v0, p1}, Lcom/example/androidsafetest01/MainActivity;->startActivity(Landroid/content/Intent;)Vgoto :goto_0.line 36:cond_0iget-object p1, p0, Lcom/example/androidsafetest01/MainActivity$1;->this$0:Lcom/example/androidsafetest01/MainActivity;invoke-virtual {p1}, Lcom/example/androidsafetest01/MainActivity;->getApplicationContext()Landroid/content/Context;move-result-object p1const/4 v0, 0x0const-string v1, "\u8f93\u5165\u5bc6\u7801\u6709\u8bef"//这里Smali采用的是Unicode编码invoke-static {p1, v1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;move-result-object p1invoke-virtual {p1}, Landroid/widget/Toast;->show()V:cond_1:goto_0return-void
.end method
四、实际操作部分
这里通过修改其中的明文密码判定部分,改变其登录逻辑为,密码等于123456789时,进行登录行为
改变后
再次打包APK,进行重签名发送到手机上进行安装
重签名,这里的签名方式采用的是Java中的jarsigner命令,jarsigner命令只可以针对V1的签名方式进行签名,后期应该会进行更改签名方式
jarsigner -verbose -keystore D:\2022\Names\AndroidSafeSign.jks D:\2022\移动安全\apks\release\AndroidSafeTest02.apk -signedjar D:\2022\移动安全\apks\AfterRenamed\AndroidSafeTest01.apk key0
执行效果:
修改过后的视频播放地址
但是这种修改Smali的方法基于静态调试,实际反编译APK过程中基本不会有打静态补丁的机会,这里也是仅供练习使用。
总结
以上是Smali语法学习部分,欢迎大家指正
移动安全:Smali语法学习示例与实践相关推荐
- Android逆向入门7——Smali语法学习(1)
这一节我们一起探讨smali语法和smali在Android逆向中的应用,它是Android逆向世界中不可或缺的一部分. 简单的来说,Dex反编译的结果就是Smali,Smali和dex之间的关系,我 ...
- Smali语法学习三
寄存器与变量 Java中的变量都是放在内存中的,安卓为了提高性能,变量都是放在寄存器中的.寄存器为32位,可以支持任何类型.其中long和double这种64为的类型需要两个寄存器保存.寄存器采用v和 ...
- Smali语法学习五
#算数运算 Java代码: public void num(int b){int a = b;boolean b1 = true;Log.d("MainActivity",&quo ...
- notepad++ smali语法高亮模板分享
某论坛也有,但是太难看了, 前面介绍了一些工具可以反编译dex文件为smali文件,在Android程序逆向分析中,阅读smali代码已然是十分重要的,但各种代码编辑器都无法较好的支持smali文件的 ...
- smali语法中文版
这是学习Smali重中之中,不过现在有些反编译的软件已经存在相应的插件,可以直接看到这些操作码名称的中文解释(如:Android killer),但是对其进行学习还是非常有必要的.以下是 ...
- 《0基础学安卓逆向》第2集:初始apk文件和smali语法
1.APK文件 apk=android Application PacKage=APKapk文件是什么:是安卓app的安装文件本质:(apk文件其实就是个)zip压缩包 意味着可以用解压缩工具把apk ...
- jsx 调用php,JavaScript_JavaScript的React框架中的JSX语法学习入门教程,什么是JSX?
在用React写组件的 - phpStudy...
JavaScript的React框架中的JSX语法学习入门教程 什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上 ...
- MySQL语法学习笔记
MySQL语法学习笔记 学习之道,非尽心竭力者不能进也!我是小七黛,欢迎查看我的笔记,有问题欢迎交流探讨. SQL是一种结构查询语言,用于查询关系数据库的标准语言,包括若干关键字和一致的语法,便于数据 ...
- Markdown语法学习|精简版
markdown语法学习|精简版 文章开头 点击这里回到下方介绍 页面跳转 的阅读位置 点击这里回到下方介绍 toc 的阅读位置 此笔记学习摘抄自Markdown语法大全(超级版),并根据笔者的使用不 ...
- 搜索引擎系统学习与开发实践总结
导读: 搜索引擎系统学习与开发实践总结 2006-07-23 20:14 一.搜索引擎概述 搜索引擎的发展历史 在互联网发展初期,网站相对较少,信息查找比较容易.然而伴随互联网爆炸性的发展,普通网络用 ...
最新文章
- Leangoo敏捷工具,scrum看板工具截止时间变化~
- P3225 [HNOI2012]矿场搭建
- 127. Word Ladder 单词接龙
- java 验证码 添加背景图_java登陆界面怎么加背景图 会的我加你
- 【Web前端开发最佳实践系列】前端代码推荐和建议
- 阿里云、腾讯云和华为云618活动细节对比
- webpack 安装vue(两种代码模式compiler 和runtime)
- Linux复习-shell程序设计
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟 1
- Matlab实现Compow协议,optisystem和matlab协同仿真
- 计算机数据结构模拟试题,十套计算机数据结构试题及答案.doc
- rfid破解 BLE Hacking
- 理解Mybatis一级缓存,以及如何真正使用到一级缓存
- win定时关机_windows如何设置定时关机?
- 前端1——html笔记
- onclick和onfocus的区别
- js实现页面指定区域局部刷新
- 【数据库系统】第一部分 数据库基础(4) 数据库安全性
- 遍历HashMap中元素的三种方法
- freopen函数使用
热门文章
- 在office2003中打开office2007文件的补丁(.docx文件,pptx文件打开方法)
- 解决U盘快捷方式木马
- SQL Server 2008 R2安装步骤示例
- Android静默安装实现方案,仿360手机助手秒装和智能安装功能
- 在ubuntu9.10下 安装nvidia GT130M最新驱动190.42版本
- win10打开蓝牙_联想笔记本win10无法连接蓝牙音箱的解决方法
- android 关闭进程 后台进程还在,为何有些安卓后台程序就是关不掉呢?
- 基于QT的IM(jabber)库和客户端
- 玩qq游戏提示计算机内存不足,win10系统玩游戏提示“计算机内存不足”怎么办...
- 镜像翻转_《蒙娜丽莎》镜像翻转后,暗藏神秘的第二张脸?网友:笑容消失了...