首页
社区
课程
招聘
[原创]对照Java源码学习smali语法,根据smali代码反推java代码
发表于: 2018-6-7 15:14 6728

[原创]对照Java源码学习smali语法,根据smali代码反推java代码

2018-6-7 15:14
6728

最近在分析一个加密应用的算法时,发现反编译出来的Java代码,有太多不完美的地方了,for循环尤其刺眼!我想要把相应的算法改成可编译的版本,这就需要对smali语法理解的比较透彻了。

 

反编译

 

由于手边有Android系统源码和编译好的各种模块,我可以比较容易的对照smali语句学习java代码,也可以很方便的看到对照java源码学习smali语法。

 

这次分析Android源码中/packages/apps/Snap/src/com/android/camera/PanoUtil.java的一个比较简单的函数decodeYUV420SPQuarterRes,分析几行Java代码对应的smali代码,这样有利于我们在没有源码的情况下更好的理解smali代码:

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.camera;

import java.text.SimpleDateFormat;
import java.util.Date;

public class PanoUtil {
    public static String createName(String format, long dateTaken) {
        Date date = new Date(dateTaken);
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(date);
    }

    // TODO: Add comments about the range of these two arguments.
    public static double calculateDifferenceBetweenAngles(double firstAngle,
            double secondAngle) {
        double difference1 = (secondAngle - firstAngle) % 360;
        if (difference1 < 0) {
            difference1 += 360;
        }

        double difference2 = (firstAngle - secondAngle) % 360;
        if (difference2 < 0) {
            difference2 += 360;
        }

        return Math.min(difference1, difference2);
    }

    public static void decodeYUV420SPQuarterRes(int[] rgb, byte[] yuv420sp, int width, int height) {
        final int frameSize = width * height;

        for (int j = 0, ypd = 0; j < height; j += 4) {
            int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
            for (int i = 0; i < width; i += 4, ypd++) {
                int y = (0xff & (yuv420sp[j * width + i])) - 16;
                if (y < 0) {
                    y = 0;
                }
                if ((i & 1) == 0) {
                    v = (0xff & yuv420sp[uvp++]) - 128;
                    u = (0xff & yuv420sp[uvp++]) - 128;
                    uvp += 2;  // Skip the UV values for the 4 pixels skipped in between
                }
                int y1192 = 1192 * y;
                int r = (y1192 + 1634 * v);
                int g = (y1192 - 833 * v - 400 * u);
                int b = (y1192 + 2066 * u);

                if (r < 0) {
                    r = 0;
                } else if (r > 262143) {
                    r = 262143;
                }
                if (g < 0) {
                    g = 0;
                } else if (g > 262143) {
                    g = 262143;
                }
                if (b < 0) {
                    b = 0;
                } else if (b > 262143) {
                    b = 262143;
                }

                rgb[ypd] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) |
                        ((b >> 10) & 0xff);
            }
        }
    }
}

 

第45行这个函数有四个参数,没有返回值:

public static void decodeYUV420SPQuarterRes(int[] rgb, byte[] yuv420sp, int width, int height){
......
}

在对应的smali代码中,四个参数分别用p0,p1,p2,p3表示:

.method public static decodeYUV420SPQuarterRes([I[BII)V
    .locals 17
    .param p0, "rgb"    # [I
    .param p1, "yuv420sp"    # [B
    .param p2, "width"    # I
    .param p3, "height"    # I
......
.end method

 

第46行代码,两个参数相乘,赋值给另一个变量:

    final int frameSize = width * height;

这个.line 46表示下面的代码对应的Java代码在第46行,v2代表变量frameSize

    .prologue
    .line 46
    mul-int v2, p2, p3

 

48行,java中的一个for循环:

    for (int j = 0, ypd = 0; j < height; j += 4) {
    ......
    }

if-ge v5, v0, :cond_8相当于java代码中的j < height,意思是如果v5(j)大于等于v0(height)则跳转到cond_8跳出循环。

 

如果不满足条件则执行下面的语句,一轮循环结束刚好到cond_7,执行add-int/lit8 v5, v5, 0x4相当于java代码中的j += 4,然后返回goto_0,继续判断j < height是否成立。

    .line 48
    .local v2, "frameSize":I
    const/4 v5, 0x0

    .local v5, "j":I
    const/4 v13, 0x0

    .local v13, "ypd":I
    :goto_0
    move/from16 v0, p3

    if-ge v5, v0, :cond_8
......
    :cond_7
    add-int/lit8 v5, v5, 0x4

    goto/16 :goto_0

    .line 85
    .end local v4    # "i":I
    .end local v7    # "u":I
    .end local v9    # "uvp":I
    .end local v10    # "v":I
    :cond_8
    return-void

 

第49行java代码,三个赋值语句

        int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;

比较容易理解,其中uvp = frameSize + (j >> 1) * width对应smali代码前三行:

    .line 49
    shr-int/lit8 v14, v5, 0x1

    mul-int v14, v14, p2

    add-int v8, v2, v14

    .local v8, "uvp":I
    const/4 v7, 0x0

    .local v7, "u":I
    const/4 v10, 0x0

在把那个加密算法逆向出来之前,应该会持续更新!

Reference


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-6-7 17:34 被Explorerl编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 6682
活跃值: (1156)
能力值: ( LV5,RANK:158 )
在线值:
发帖
回帖
粉丝
2

根据smali代码和反编译出的java代码反推出更容易理解的java代码

已知一段smali代码如下:

.method public static c(Ljava/lang/String;)Ljava/lang/String;
    .locals 10

    const/4 v7, 0x0

    if-nez p0, :cond_0

    move-object v6, v7

    :goto_0
    return-object v6

    :cond_0
    :try_start_0
    new-instance v8, La/auu/a;

    invoke-direct {v8}, La/auu/a;-><init>()V

    const/4 v9, 0x0

    invoke-virtual {v8, p0, v9}, La/auu/a;->ooo0ooo0o0o000o(Ljava/lang/String;I)[B

    move-result-object v0

    array-length v5, v0

    const/4 v4, 0x7

    new-array v1, v4, [B

    fill-array-data v1, :array_0

    const/4 v2, 0x0

    const/4 v3, 0x0

    :goto_1
    if-lt v2, v5, :cond_1

    new-instance v6, Ljava/lang/String;

    invoke-direct {v6, v0}, Ljava/lang/String;-><init>([B)V

    goto :goto_0

    :cond_1
    if-lt v3, v4, :cond_2

    const/4 v3, 0x0

    :cond_2
    aget-byte v8, v0, v2

    aget-byte v9, v1, v3

    xor-int/2addr v8, v9

    int-to-byte v8, v8

    aput-byte v8, v0, v2
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

    add-int/lit8 v2, v2, 0x1

    add-int/lit8 v3, v3, 0x1

    goto :goto_1

    :catch_0
    move-exception v1

    move-object v6, v7

    goto :goto_0

    nop

    :array_0
    .array-data 1
        0x4et
        0x65t
        0x74t
        0x65t
        0x61t
        0x73t
        0x65t
    .end array-data
.end method

使用dex2jar得到的java代码是这样的:

 public static String c(String paramString)
  {
    if (paramString == null) {
      return null;
    }
    for (;;)
    {
      try
      {
        paramString = new a().ooo0ooo0o0o000o(paramString, 0);
        int m = paramString.length;
        j = 0;
        i = 0;
        if (j < m) {
          break label106;
        }
        return new String(paramString);
      }
      catch (Exception paramString)
      {
        int j;
        return null;
      }
      paramString[j] = ((byte)(paramString[j] ^ new byte[] { 78, 101, 116, 101, 97, 115, 101 }[k]));
      j += 1;
      int i = k + 1;
      continue;
      label106:
      int k = i;
      if (i >= 7) {
        k = 0;
      }
    }
  }

 

根据smali代码修正后的java代码

  public static String c(String paramString)
  {
    if (paramString == null) {
      return null;
    }
      try
      {
        paramString = new a().ooo0ooo0o0o000o(paramString, 0);
        int m = paramString.length;
          for(j = 0, k = 0; j < m; j++, k++){
              if(k < 7){
                  paramString[j] = ((byte)(paramString[j] ^ new byte[] { 78, 101, 116, 101, 97, 115, 101 }[k]));
                }
                k = 0;
          }
          return new String(paramString);
      }

      catch (Exception paramString)
      {
        return null;
      }
  }
最后于 2018-6-7 17:19 被Explorerl编辑 ,原因:
2018-6-7 17:14
0
游客
登录 | 注册 方可回帖
返回
//