吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8423|回复: 10
收起左侧

[Android 分享] 用Smali写一个加法程序

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

[Asm] 纯文本查看 复制代码
.class public Ltest;
.super Ljava/lang/Object;
.method public constructor <init>()V
#寄存器数量待定
    .registers 1 
.parameter
.prologue
    return-void
.end method

思路:由于要传2个参数进去计算,并不是像书上的例子一样,只是打印出一行字,所以要弄清楚参数是如何传进去的。写一个简单的程序反编译看看。程序代码:
代码:

[Asm] 纯文本查看 复制代码
public class test2 {
  public static void main(String[] args) {
    String a = args[0];       
  }
}

编译成smali代码先看看参数是怎么样传进去的,smali代码如下:
[Asm] 纯文本查看 复制代码
.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:
[Asm] 纯文本查看 复制代码
.method public constructor <init>()V


表示该类的不带参数缺省的构造方法
看来这就是传参的关键。

[Asm] 纯文本查看 复制代码
const/4 v0, 0x0
 aget-object v0, p0, v0


Main函数中用这2句的接受传进来的值。
所以应该先添加这个构造方法:


[Asm] 纯文本查看 复制代码
# direct methods
.method public constructor <init>()V
    .registers 1
    .prologue
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method

接着写代码如下:
[Asm] 纯文本查看 复制代码
#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文件:

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

重新编译dex-->PUSH-->执行再试试:
图片5.png
好了,当然编写的过程中可能会出现各种各样的错误,需要耐心+毅力。
最后要说一下,.parameter这行我是删了,用了2个版本的

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


免费评分

参与人数 4吾爱币 +1 热心值 +4 收起 理由
fu90 + 1 + 1 用心讨论,共获提升!
WildWolf + 1 invoke后面的不是很理解,书上也没解释
Free-Man + 1 膜拜程序员
低调(d-iao) + 1 膜拜程序员

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

独步逍遥 发表于 2014-11-27 16:03
很认真地看了一下···还是不懂···
ymwcwee 发表于 2014-11-27 16:08
 楼主| Ericky 发表于 2014-11-27 19:07
独步逍遥 发表于 2014-12-4 12:27

嘿嘿··我新手··
leidian0808 发表于 2015-7-19 10:56
能否发一下源码,搞了好久了还是出现unable to find static main() 错误,快崩溃了
qtfreet00 发表于 2015-7-19 12:45 来自手机
小雨推荐基本书吧
 楼主| Ericky 发表于 2015-7-21 15:32

非虫那本不错。基础打牢点
xiaohe009 发表于 2016-11-12 14:22
修改反编译代码有用
Lapprentice 发表于 2017-5-17 09:36
仔细看了一下代码并且实际操作了一下,发现.method public static main([Ljava/lang/String;)V方法中缺了以下代码:
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
#输出结果
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
此外v1值应该为1:
const/4 v1, 0x1
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 16:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表