首页
社区
课程
招聘
[原创]用Smali写一个加法程序
发表于: 2014-11-27 15:38 24016

[原创]用Smali写一个加法程序

2014-11-27 15:38
24016
最近对移动端产生了很浓厚的兴趣,那就开始学习吧!因为还有工作任务,忙里偷闲把丰生强的前3章认真读了一遍。小结内容是说必须熟练掌握这一部分的内容,可通过手动编写Dalvik汇编代码来熟悉一下指令,为后面的分析夯实好基础。
书上的是一个显示HelloWorld的例子,为了练习好基础。准备要用Dalvik汇编写一个简单的程序,功能如下:

按照书上的,把框架搭好如下:
.class public Ltest;
.super Ljava/lang/Object;
.method public constructor <init>()V
#寄存器数量待定
    .registers 1 
.parameter
.prologue
    return-void
.end method

思路:由于要传2个参数进去计算,并不是像书上的例子一样,只是打印出一行字,所以要弄清楚参数是如何传进去的。写一个简单的程序反编译看看。程序代码:
public class test2 {
	public static void main(String[] args) {
		String a = args[0];       
	}
}

编译成smali代码先看看参数是怎么样传进去的,smali代码如下:
.class public Ltest2;
.super Ljava/lang/Object;
.source "test2.java"
# direct methods
.method public constructor <init>()V
    .registers 1
    .prologue
    .line 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method
.method public static main([Ljava/lang/String;)V
    .registers 2
    .prologue
    .line 4
    const/4 v0, 0x0
    aget-object v0, p0, v0

    .line 6
    return-void
.end method

发现除了main函数外还有一个direct method:
.method public constructor <init>()V

表示该类的不带参数缺省的构造方法
看来这就是传参的关键。
const/4 v0, 0x0
 aget-object v0, p0, v0

Main函数中用这2句的接受传进来的值。
所以应该先添加这个构造方法:
# direct methods
.method public constructor <init>()V
    .registers 1
    .prologue
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method

接着写代码如下:
#V0 V1 清零
 const/4 v0, 0x0
 const/4 v1, 0x0
#接收传进来的2个参数
 aget-object v0, p0, v0
     aget-object v1, p0, v1
#把第一个参数转化成int类型 给vo
    invoke-static {v0}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
    move-result v0
#把第二个参数转化成int类型 给v1
    invoke-static {v1}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
    move-result v1
#两个参数相加  值存 给vo
    add-int/2addr v0, v1
#把vo中的结果转化成String类型  再给v0
    invoke-static {v0}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
    move-result-object v0
#构造一个String类型对象的新实例 把值赋给v2
    new-instance v2, Ljava/lang/StringBuilder;
#调用实例的直接方法
    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
#定义一个字符串常量
    const-string v3, "The Sum is :"
#调用实例方法,把v3与v2里的字符串相加再给v2 invoke-virtual{v2,v3},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v2
#调用实例方法,把v0与v2里的字符串相加再给v2 
invoke-virtual{v2,v0},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v2
#输出结果
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

终于写完了,我们编译好来看看结果。
编译出dex文件:

Push到android里:

执行:

发现报错了。百思不得其解,纠结了好久。代码也检查了好几遍,最后都要崩溃了,还是出错。后来实在忍无可忍,写了个程序反编译出dex文件看看吧。结果发现了原来少了这么一句:
#此句加在输入结果之前,将v2里的东西转化成String类型。
 invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v2

重新编译dex-->PUSH-->执行再试试:

好了,当然编写的过程中可能会出现各种各样的错误,需要耐心+毅力。
最后要说一下,.parameter这行我是删了,用了2个版本的

都试了一下,发现没有.parameter,有的话会报错。可能是丰写此书的时候版本还很低吧,这个大家要注意哦。
总的来说,虽然就这么一点代码,也不难。但确实是花了我不少时间,不过同时也学到了不少东西,对smali语句和adb命令,dex、class、smali等几种格式的互相转化也很熟练了。
最后感谢丰大牛,书写得很好,有的细节不够完美,但瑕不掩瑜。路漫漫其修远兮,打牢基础才能走得更远。

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 4687
活跃值: (388)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持!够详细,够基础。迈出这一步很艰难,相信走来了就会顺利许多!赞
2014-11-27 15:44
0
雪    币: 1185
活跃值: (458)
能力值: ( LV13,RANK:360 )
在线值:
发帖
回帖
粉丝
3
谢谢 再接再厉
2014-11-27 19:06
0
雪    币: 184
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享精彩教程,支持
2014-12-11 17:40
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
支持,同为新手。
2014-12-11 18:02
0
雪    币: 1185
活跃值: (458)
能力值: ( LV13,RANK:360 )
在线值:
发帖
回帖
粉丝
6
不客气~共勉
2014-12-11 19:42
0
雪    币: 590
活跃值: (678)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢精彩教程,加油
2015-1-26 12:11
0
雪    币: 188
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
支持一个,很不错
2015-1-27 00:04
0
雪    币: 8
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
非虫书里,adb push那里写的是push .zip文件,但好像不对,push上去用不了,应该直接push .dex。
2015-3-25 14:12
0
雪    币: 1185
活跃值: (458)
能力值: ( LV13,RANK:360 )
在线值:
发帖
回帖
粉丝
10
是的
2015-3-25 14:15
0
游客
登录 | 注册 方可回帖
返回