反编译之apk0


smali规则

J-long  Z-boolean  B-byte  C-charD-double  F-float  I-int  S-short  V-void  [Lxxx/nnn-array

如 int和float 1维数组表示为:[I、[F;对象的表示格式是LpackageName/objectName;(注意分号),如String:Ljava/lang/String;,数组每一个维度最多255个,内部类的引用是:LpackageName/objectName$subObjectName;

方法:参数间无分隔符: f()V - void f()          f (III)Z -boolean f(int, int, int)           f(Z[ILjava/lang/String;J)Ljava/lang/String; - String f(boolean, int[], String, long)


"if-eq vA, vB, :cond_**"   vA等于vB则goto_**
"if-ne vA, vB, :cond_**"   不等于
"if-lt vA, vB, :cond_**"   小于
"if-ge vA, vB, :cond_**"   大于等于
"if-gt vA, vB, :cond_**"   大于
"if-le vA, vB, :cond_**"   小于等于
"if-eqz vA, :cond_**"   等于0
"if-nez vA, :cond_**"   不等于0
"if-ltz vA, :cond_**"   小于0
"if-gez vA, :cond_**"   大于等于0
"if-gtz vA, :cond_**"   大于0
"if-lez vA, :cond_**"   小于等于0 

if:
private boolean e(){
        boolean temp = ()? true : false;
        if (temp ) {
            return true;
        }else{
            return false;
        }
    }
.method private e()Z
    .locals 2
    .prologue
    .line 22
    const/4 v0, 0x1     // v0赋值为1
    .line 24
    .local v0, tempFlag:Z
    if-eqz v0, :cond_0     // 判断v0是否等于0
    .line 25
    const/4 v1, 0x1  


    .line 27
    :goto_0
    return v1


    :cond_0
    const/4 v1, 0x0    


    goto :goto_0
.end method

for:
private void for(){
    listStr = new ArrayList<String>(COUNT);
    for (int i = 0; i < COUNT; i++) {
        listStr.add("l");
    }
}
 .line 40
 const/4 v0, 0x0
 .local v0, i:I


 :
goto_0
 if-lt v0, v3, :
cond_0  //  if-lt判断数值v0小于v3

 .line 43
 
return-void

 .line 41
:cond_0  
 iget-object v1, p0, Lcom/example/smalidemo/MainActivity;->listStr:Ljava/util/List;    
 const-string v2, "\u73b0\u5728\u8f6e\u5230\u6211\u4e0a\u573a\u4e50"
 invoke-interface {v1, v2}, Ljava/util/List;->add(Ljava/lang/Object;)Z

 .line 40
 add-int/lit8 v0, v0, 0x1 //将第二个v0寄存器中的值,加上0x1的值放入第一个寄存器中

 
goto :goto_0

本地寄存器(无限制):如v0、v1、v2,参数寄存器:如p0、p1、p2 注p0不一定是第一个参数,在非static方法中,p0指“this”,p1表示方法的第一个参数,p2代表方法中的第二个…在static方法中p0才对应第一个参数(因为Java的static方法中没this方法)

const/4 v0, 0x0  //把值0x0(false)存到v0中

iput-boolean v0, p0, Lcom/d/W/WA;->is:Z //iput-boolean指令把v0中的值存到com.d.W.WA.is成员变量中,p0为this

调用变量的指令:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等,赋值:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等


1)static fields:sget-object v0, Lcom/d/W/WA;->ID:Ljava/lang/String;  //获取变量值并保存到紧接着的参数的寄存器中

2)获取instance fields:由于不是static变量,不仅指出该变量所在类的类型,还需该变量所在类的实例:

iget-object v0, p0, Lcom/d/W/WA;->veiw:Lcom/d/co/WV;  //比sget-object多了该变量所在类的实例参数p0即“this”

put和get指令相对:
const/4 v3, 0x0  
sput-object v3, Lcom/d/W/WA;->handler:Lcom/d/con/Handler;  
    this.handler = null;(
null = 0x0

.local v0, wait:Landroid/os/Message;  //wait是Message的实例
const/4 v1, 0x2  
iput v1, v0, Landroid/os/Message;->what:I  
     wait.what = 0x2;



direct method是private方法,其余为virtual。

const-string v0, "fx"  

invoke-static

{v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V //v0就是"fx",“{}”,调用该方法的实例+参数们,这方法既不需参数也是static的,static方法比起其他调用少调用者参数

const/4 v2, 0x0

invoke-virtual {p0, v2}, Lcom/disney/WMW/WMWActivity;->getPreferences(I)Landroid/content/SharedPreferences;

invoke-static/range{v0 .. v5}, Lcn/game189/sms/SMS;->checkFee(Ljava/lang/String;Landroid/app/Activity;Lcn/game189/sms/SMSListener;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z  //6个参数多于4个时invoke-XXX/range

move-result-object v1  // v1保存的就是调用getPreferences(int)方法返回的SharedPreferences实例。move-result(返回基本数据类型)和move-result-object(返回对象), smali调用与获取返回值分开 有别于java

invoke-virtual {v2}, Ljava/lang/String;->length()I  
move-result v2  //v2保存的则是调用String.length()返回的整型。



#annotations
 .annotation system Ldalvik/annotation/MemberClasses;
     value = {
      Lcom/d/W/WA$MessageHandler;,
    Lcom/d/W/WA$FinishActivityArgs;
  }
.
end annotation//表示有俩成员内部类


# static fields # instance fields //成员变量


direct methods  

.method static synthetic ac$200(Lcom/d/W/WA;)Lcom/d/co/WV; //

.locals 3   //  在这个方法中最少要用到的本地寄存器的个数,在方法的第一行。.registers指定方法中寄存器总个数

.parameter "x0" // move p0, v3 把v3寄存器的值移动到寄存器p0上. const v0, 把值0x1赋值到寄存器v0上  .parameter .parameter   //表示有两个参数

.prologue   //方法开始

.line 30   //非必需

.invoke-direct {p0}, Lcom/d/W/WA;->initIap()V  //

iget-object v0, p0, Lcom/d/W/WA;->_view:Lcom/d/co/WV;  


return-object v0  

.end method



常见错误:.local 的值不对,invoke-virtual或invoke-static将在回编译后程序运行时引发一个常见的VerifyError


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
反编译安卓apk并且兼容低版本,可以使用以下步骤: 1. 安装apktool工具:apktool是一个开源的反编译工具,可以将apk文件反编译为可以编辑的smali代码。可以从官网https://ibotpeaches.github.io/Apktool/ 下载最新版本的apktool,并按照官方文档进行安装配置。 2. 反编译apk文件:执行命令`apktool d xxx.apk`,将apk文件反编译为smali代码。此时会在当前目录下生成一个与apk同名的文件夹,里面包含了所有的反编译后的文件。 3. 修改smali代码:使用文本编辑器打开smali代码,进行相应的修改。注意:修改smali代码需要有一定的Android开发经验。 4. 重新打包:执行命令`apktool b xxx -o new.apk`,将修改后的smali代码重新打包为apk文件。此时会在当前目录下生成一个名为new.apkapk文件。 5. 签名:使用Android SDK提供的工具进行签名。在命令行中进入到SDK的bin目录,执行命令`apksigner sign --ks my-release-key.jks --out new_signed.apk new.apk`,将new.apk签名为new_signed.apk。其中,--ks参数指定签名文件的路径,--out参数指定签名后的apk文件名。 6. 兼容低版本:使用Android SDK提供的工具将新生成的apk文件进行兼容处理。在命令行中进入到SDK的build-tools目录,执行命令`zipalign -v 4 new_signed.apk final.apk`,将new_signed.apk进行兼容处理,生成名为final.apkapk文件。 完成以上步骤后,就能得到一个已经反编译、修改、打包、签名并且兼容低版本的apk文件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值