Android逆向:smali编码实践(三)—— 实体类创建以及if判断

目录

1.准备工作

2.编写smali文件

3.编译smali文件

4.检查并运行

5.遇到问题


1.准备工作

1.1下载好smali的jar这里使用smali-2.4.0.jar  (PS: 执行命令为 java -jar assemble xxx.smali -o xxx.dex)

1.2 root的真机或者模拟器

1.3 安装好JaDex方便自己看看大概写出来的东西是个什么样子,用其它工具也行,不过这个很方便。

2.编写smali文件

.class public Lcom/test/smali/Programmer;
.super Ljava/lang/Object;
.source "Programmer.java"

#变量
.field private name:Ljava/lang/String;#名称
.field private age:I#年龄
.field private sex:I#性别 1男 0女
.field private partnerName:Ljava/lang/String;


#构造函数 PS:如果只有一个无参构造函数不用自己写g构造函数,否则new的时候会死循环
.method public constructor <init>(Ljava/lang/String;)V
.locals 1

invoke-direct {p0}, Lcom/test/smali/Programmer;-><init>()V

.param p1,"name"	
if-eqz p1,:cound_0
iput-object p1,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;
:cound_0

return-void
.end method

#get\set函数

#getName函数
.method public getName()Ljava/lang/String;
.locals 1
.prologue
iget-object v0,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;
return-object v0
.end method

#setName函数
.method public setName(Ljava/lang/String;)V
.locals 1
.prologue
.local p1, "name":Ljava/lang/String;
if-eqz p1,:cound_0
#move-object name,p1 #这么写是错的,操作field要用iput
iput-object p1,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;
:cound_0
return-void
.end method

#getAge函数
.method public getAge()I
.locals 1
.prologue
iget v0,p0,Lcom/test/smali/Programmer;->age:I
return v0
.end method

#setAge函数
.method public setAge(I)V
.locals 1
.prologue
.local p1, "age":I
if-lez p1,:cound_0 
iput p1,p0,Lcom/test/smali/Programmer;->age:I
:cound_0
return-void
.end method

#getSex函数
.method public getSex()I
.locals 1
.prologue
iget v0,p0,Lcom/test/smali/Programmer;->sex:I
return v0
.end method

#setSex函数
.method public setSex(I)V
.locals 1
.local p1,"sex":I
iput p1,p0,Lcom/test/smali/Programmer;->sex:I
return-void
.end method

#getPartnerName函数
.method public getPartnerName()Ljava/lang/String;
.locals 1
.prologue
iget-object v0,p0,Lcom/test/smali/Programmer;->partnerName:Ljava/lang/String;
return-object v0
.end method

#setPartnerName函数
.method public setPartnerName(Ljava/lang/String;)V
.locals 1
.local p1,"name":Ljava/lang/String;
if-eqz p1,:cound_0
iput-object p1,p0,Lcom/test/smali/Programmer;->partnerName:Ljava/lang/String;
:cound_0
return-void
.end method

#toString函数
.method public toString()Ljava/lang/String;
.locals 14
.prologue

#创建一个StringBuilder用来拼接字符串
new-instance v0,Ljava/lang/StringBuilder;
invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
#给v0寄存器所持有的StringBuilder的实例一个为"sb"名称 
.local v0,"sb":Ljava/lang/StringBuilder;

iget-object v1,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;
.local v1,"name":Ljava/lang/String;
iget v2,p0,Lcom/test/smali/Programmer;->age:I
.local v2,"age":I
iget v3,p0,Lcom/test/smali/Programmer;->sex:I
.local v3,"sex":I
iget-object v4,p0,Lcom/test/smali/Programmer;->partnerName:Ljava/lang/String;
.local v4,"partnerName":Ljava/lang/String;

const-string v5,"这是一个默默无闻的程序员"
const-string v6,"年龄:"
const-string v7,"对象是"
const-string v8,"是条单身狗!"
const-string v9,"性别"
const-string v10,"男"
const-string v11,"女"

#对属性的值进行判断

if-eqz v1,:cound_0
#if(name!=null)
invoke-virtual {v0,v1},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:cound_0

if-nez v1,:cound_1
#if(name==null)
invoke-virtual{v0,v5},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:cound_1

invoke-virtual{v0,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invoke-virtual{v0,v2},Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
invoke-virtual{v0,v9},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

if-eqz v3,:cound_2
#if(sex!=0)
invoke-virtual{v0,v10},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:cound_2

if-nez v3,:cound_3
#if(sex == 0)
invoke-virtual{v0,v11},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:cound_3

if-eqz v4,:cound_4
invoke-virtual{v0,v7},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invoke-virtual{v0,v4},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:cound_4

if-nez v4,:cound_5
invoke-virtual{v0,v8},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:cound_5

invoke-virtual {v0},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v12

sget-object v13,Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v13,v12},Ljava/io/PrintStream;->println(Ljava/lang/String;)V

.end local v0
#调用父类的toString方法
invoke-super {p0}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v0
return-object v0
.end method

#main函数
.method public static main([Ljava/lang/String;)V
.locals 6
.local p0,"strs":[Ljava/lang/String;
.prologue

const-string v0,"张三"
.local v0,"name":Ljava/lang/String;
const/16 v1,0x12
.local v1,"age":I
const/16 v2,0x1
.local v2,"sex":I
const-string v3,"李四"
.local v3,"partnerName":Ljava/lang/String;

new-instance v4,Lcom/test/smali/Programmer;

invoke-direct {v4},Lcom/test/smali/Programmer;-><init>()V

invoke-virtual {v4,v0},Lcom/test/smali/Programmer;->setName(Ljava/lang/String;)V
invoke-virtual {v4,v1},Lcom/test/smali/Programmer;->setAge(I)V
invoke-virtual {v4,v2},Lcom/test/smali/Programmer;->setSex(I)V
#注释之后打印出该程序猿/媛是个单生狗
#invoke-virtual {v4,v3},Lcom/test/smali/Programmer;->setPartnerName(Ljava/lang/String;)V

invoke-virtual {v4},Lcom/test/smali/Programmer;->toString()Ljava/lang/String;

return-void
.end method

3.编译smali文件

自己写的一个smali.bat,为了少打几个字!

开始编译

4.检查并运行

JaDex查看:

package com.test.smali;

public class Programmer {
    private int age;
    private String name;
    private String partnerName;
    private int sex;

    public Programmer(String name) {
        if (name != null) {
            this.name = name;
        }
    }

    public static void main(String[] strArr) {
        String partnerName = "李四";
        Programmer programmer = new Programmer();
        programmer.setName("张三");
        programmer.setAge(18);
        programmer.setSex(1);
        programmer.toString();
    }

    public int getAge() {
        return this.age;
    }

    public String getName() {
        return this.name;
    }

    public String getPartnerName() {
        return this.partnerName;
    }

    public int getSex() {
        return this.sex;
    }

    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }

    public void setName(String name) {
        if (name != null) {
            this.name = name;
        }
    }

    public void setPartnerName(String name) {
        if (name != null) {
            this.partnerName = name;
        }
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        String name = this.name;
        int age = this.age;
        int sex = this.sex;
        String partnerName = this.partnerName;
        String str = "这是一个默默无闻的程序员";
        String str2 = "年龄:";
        String str3 = "对象是";
        String str4 = "是条单身狗!";
        String str5 = "性别";
        String str6 = "男";
        String str7 = "女";
        if (name != null) {
            sb.append(name);
        }
        if (name == null) {
            sb.append(str);
        }
        sb.append(str2);
        sb.append(age);
        sb.append(str5);
        if (sex != 0) {
            sb.append(str6);
        }
        if (sex == 0) {
            sb.append(str7);
        }
        if (partnerName != null) {
            sb.append(str3);
            sb.append(partnerName);
        }
        if (partnerName == null) {
            sb.append(str4);
        }
        System.out.println(sb.toString());
        return super.toString();
    }
}

模拟器运行:

5.遇到问题

1.定义全局变量出现错误

错误写法:.field private name:Ljava/lang/String; = "",根据错误提示的字面意思理解,应该是"只有静态的域才能够指定初始值。"

正确写法:.field private name:Ljava/lang/String;

编译后Jadex查看如下:

2.创建setName方法时move指令与iput混淆

错误写法:move-object p1,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;

正确写法:iput-object p1,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;

编译后JaDex查看如下:

3.创建方法提示寄存器数量定义问题

创建方法时没有指明寄存器数量,加上.locals "函数用到的寄存器数量" 即可。如: .locals 5 

4.new-instance 死循环

由于模仿反编译出来的smali文件写了无参构造函数,结果在编译时出现构造函数死循环。

正确方法:不写构造函数,或者写一个有参的的构造函数。如下:

.method public constructor<init>(Ljava/lang/String;)V
.locals 1
.prologue
.param p1,"name"

invoke-direct {p0},Lcom/test/smali/Programmer;-><init>()V

if-eqz p1,:cound_0
iput-object p1,p0,Lcom/test/smali/Programmer;->name:Ljava/lang/String;
:cound_0

return-void
.end method

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值