反編譯Android App問題攻克

在這裏講述的實際上是java反編譯,主要是由於我是反編譯人家的app源碼入手的,就天然的掛起了羊頭。 java

衆所周知,經過dex2jar能將android app的dex解析爲class文件jar包,而後經過jd等反編譯工具查看源代碼,貌似很容易就能對別人的勞動成果拿來主義,可果然如此理想麼? 本着實事求是的原則,本身親手試了下,結果天然是杯具的。 android

如下是反編譯出的結果,咱們簡單的以一個方法爲例: 編程

public double getCORRLN(double[] paramArrayOfDouble)
  {
    double d1 = 0.0D;
    double d2 = 0.0D;
    double d3 = 0.0D;
    double d4 = 0.0D;
    double[] arrayOfDouble1 = new double[this.grayLevel];
    double[] arrayOfDouble2 = new double[this.grayLevel];
    int i = 0;
    int k;
    label42: int m;
    if (i >= this.grayLevel)
    {
      k = 0;
      if (k < 32)
        break label171;
      m = 0;
      if (m < 32)
        break label201;
    }
    for (int i1 = 0; ; i1++)
    {
      if (i1 >= 32)
      {
        if ((d3 != 0.0D) && (d4 != 0.0D))
          this.CORRLN = ((this.CORRLN - d1 * d2) / Math.sqrt(d3 * d4));
        return this.CORRLN;
        for (int j = 0; ; j++)
        {
          if (j >= this.grayLevel)
          {
            d1 += (i + 1) * arrayOfDouble1[i];
            i++;
            break;
          }
          arrayOfDouble1[i] += paramArrayOfDouble[(j + i * this.grayLevel)];
        }
        label171: d3 += Math.pow(k + 1 - d1, 2.0D) * arrayOfDouble1[k];
        k++;
        break label42;
        label201: for (int n = 0; ; n++)
        {
          if (n >= 32)
          {
            d2 += (m + 1) * arrayOfDouble2[m];
            m++;
            break;
          }
          arrayOfDouble2[m] += paramArrayOfDouble[(m + n * this.grayLevel)];
        }
      }
      d4 += Math.pow(i1 + 1 - d2, 2.0D) * arrayOfDouble2[i1];
    }
  }



是否是感受狗屁不通?這仍是例舉的一個相對簡單的方法,看看這個

基本每一個方法都有錯誤,基本每一個錯誤都是邏輯混亂,基本沒一個方法能用,簡單來講,這個文件就是廢的。 數組

第一次看到這狀況,內心很納悶,不知道是dex2jar這個過程除了問題仍是jd的問題,後來百度了一下(谷歌打不開,懶得折騰,別鄙視,人家度娘同樣很敬業),發現這種問題不少,經過jad爲核心的反編譯工具(jd就是如此)都這副尿性,恰恰jad在java反編譯工具中又算最好的,不知道是否是由於過久沒更新的緣故,反正就是不給力。 app

那如何是好呢,嘿 用java開發,就沒有不能破解的,工具不給力,那就人工來唄,果斷搞起。 工具

首先,找出該類的.class文件,javap隆重登場,在這裏 好比該類爲xohome.class, 在終端中,切入該文件所在目錄,執行命令: oop

javap -c -private xohome.class



簡單掃盲:javap是jdk自帶的反編譯工具,能簡單解析class字節碼文件的內容,參數 -c爲顯示字節碼 -private爲反編譯級別,可開發過程當中可見級別同樣,一下是上頭例舉方法的字節碼:


相信學過彙編的對這些都不陌生,若是你看得頭暈,那就沒轍了,由於這只是窗口大小的代碼,一箇中等方法大概有這樣的代碼500行。。。 測試

咱們開好工做窗口,將jd反編譯的代碼、字節碼、空白文檔(用做寫反編譯的代碼用)依次列開: this

這就是簡單的工做臺了,我原本想截大點的,可oc上傳圖片200K讓人憂傷。。。 spa

OK,開始正式工做,首先 咱們得了解下java字節碼中方法的構成,在這裏,須要明白的是方法內的局部變量表,一個java方法,包含一個局部變量表,裏頭存儲着包含參數在內的變量信息,一個java方法默認有一個參數,則是隱性參數this,也就說該表下標爲0的變量爲this,其次,根據你參數的數量和順序,一次對於參數一、參數二、參數3....等等; 其次,是Exception的異常表,該表在反編譯過程當中不過重要:

編程,無非就是對各類參數的各類加減乘除運算,在瞭解了變量表以後,在基於堆棧的Java虛擬機,就剩下很簡單的重複勞動了,以java字節碼指令表爲參考,用上述例舉的方法爲例:

0  > this					// 參數0爲this
1  > paramArrayOfDouble		// 參數1爲方法參數,標記爲paramArrayOfDouble 
2  > d1						// double d1  該變量是經過字節碼信息來肯定的,下述變量都是如此, 由於double變量佔2字節,下一個變量下標就爲4
4  > d2
6  > d3
8  > d4
10 > arrayOfDouble1  double[]
11 > arrayOfDouble2  double[]
12 > i
13 > j
public double getDouble(double[]);
    Code:
       0: dconst_0			// 取常數0入棧
       1: dstore_2			// d1 = 0 dstore_2指令爲爲double類型變量賦值,可得出參數1爲double類型,這裏命名爲d1
       2: dconst_0      
       3: dstore        4		// d2 = 0 同d1
       5: dconst_0      
       6: dstore        6		// d3 = 0 同d2
       8: dconst_0      
       9: dstore        8		// d4 = 0 同d3
      11: aload_0			// aload_0指令爲加載局部變量0的引用,0爲this
      12: getfield      #48                 // Field grayLevel:I   // 獲取當前類成員變量grayLevel	
      15: newarray       double
      17: astore        10	// 上面指令爲建立數組 附帶信息未double  當前指令爲賦值 》array1 = new double[this.grayLevel]
      19: aload_0       
      20: getfield      #48                 // Field grayLevel:I
      23: newarray       double
      25: astore        11	// 同array1 array2 = new double[this.grayLevel]

      27: iconst_0      
      28: istore        12	// int i = 0 istore指令爲int類型賦值

// if i < this.grayLevel goto 110
      30: iload         12
      32: aload_0       
      33: getfield      #48                 // Field grayLevel:I
      36: if_icmplt     110		// if_icmplt指令爲分支指令,對比當前棧的值value1是否小於value2  
// else
      39: iconst_0      
      40: istore        14		// int k = 0
	// loop
      42: iload         14
      44: bipush        32		// byte 32入棧
// if k < 32 goto 171
      46: if_icmplt     171		
// else
      49: iconst_0      
      50: istore        15		// int m = 0

      52: iload         15
      54: bipush        32
// if m < 32 goto 201
      56: if_icmplt     201
// else 
      59: iconst_0      
      60: istore        17		// int i1
      62: iload         17
      64: bipush        32
// if i1 < 32 goto 262
      66: if_icmplt     262
// else
      69: dload         6			// 載入d3
      71: dconst_0				// 載入0
      72: dcmpl         
      73: ifeq          105		// d3!=0
      76: dload         8	
      78: dconst_0      
      79: dcmpl         
      80: ifeq          105		// d4!=0
      83: aload_0       
      84: aload_0       
      85: getfield      #84                 // Field CORRLN:D
      88: dload_2       
      89: dload         4
      91: dmul          
      92: dsub          
      93: dload         6
      95: dload         8
      97: dmul          
      98: invokestatic  #147                // Method java/lang/Math.sqrt:(D)D
     101: ddiv          
     102: putfield      #84                 // Field CORRLN:D

     105: aload_0       
     106: getfield      #84                 // Field CORRLN:D
     109: dreturn    

// if i < this.grayLevel
     110: iconst_0      
     111: istore        13		// int j=0

     113: iload         13
     115: aload_0       
     116: getfield      #48                 // Field grayLevel:I
// if j < this.grayLevel goto 142
     119: if_icmplt     142
// else
     122: dload_2			// 載入d2  
     123: iload         12	// 載入i
     125: iconst_1			// 載入1
     126: iadd				// d2 + 1      
     127: i2d				// int to double
     128: aload         10	// arrayOfDouble1
     130: iload         12	// 載入i
     132: daload				// arrayOfDouble1[i]  
     133: dmul
     134: dadd          
     135: dstore_2			// d1 += (i + 1) * arrayOfDouble1[i];
     136: iinc          12, 1	// i++
     139: goto          30

// j < this.grayLevel
     142: aload         10	// 載入arrayOfDouble1
     144: iload         12	// 載入i
     146: aload         10
     148: iload         12
     150: daload				// arrayOfDouble1[i]
     151: aload_1			// paramArrayOfDouble       
     152: iload         13	// j
     154: iload         12	// i
     156: aload_0       
     157: getfield      #48                 // Field grayLevel:I
     160: imul          
     161: iadd          
     162: daload				// paramArrayOfDouble[j + i*this.grayLevel]
     163: dadd          
     164: dastore			
		// arrayOfDouble1[i] += paramArrayOfDouble[(j + i * this.grayLevel)];       
     165: iinc          13, 1
     168: goto          113

// if k < 32 goto
     171: dload         6
     173: iload         14
     175: iconst_1      
     176: iadd          
     177: i2d           
     178: dload_2       
     179: dsub          
     180: ldc2_w        #148                // double 2.0d
     183: invokestatic  #153                // Method java/lang/Math.pow:(DD)D
     186: aload         10
     188: iload         14
     190: daload        
     191: dmul          
     192: dadd          
     193: dstore        6
	// d3 += Math.pow(k + 1 - d1, 2.0D) * arrayOfDouble1[k];
     195: iinc          14, 1
     198: goto          42

// if m < 32
     201: iconst_0      
     202: istore        16	// n = 0
     204: iload         16
     206: bipush        32	// 32
// if n < 32  goto 233
     208: if_icmplt     233
// else
     211: dload         4		// d2
     213: iload         15	// m
     215: iconst_1			// 1
     216: iadd				// m + 1
     217: i2d           
     218: aload         11
     220: iload         15
     222: daload        
     223: dmul          
     224: dadd          
     225: dstore        4		// d2 += (m + 1) * arrayOfDouble2[m];
     227: iinc          15, 1
     230: goto          52

if n<32
     233: aload         11
     235: iload         15
     237: aload         11
     239: iload         15
     241: daload        
     242: aload_1					// paramArrayOfDouble
     243: iload         15
     245: iload         16
     247: aload_0       
     248: getfield      #48                 // Field grayLevel:I
     251: imul          
     252: iadd          
     253: daload        
     254: dadd          
     255: dastore       
     256: iinc          16, 1
     259: goto          204

// i1 < 32
     262: dload         8
     264: iload         17
     266: iconst_1      
     267: iadd          
     268: i2d           
     269: dload         4
     271: dsub          
     272: ldc2_w        #148                // double 2.0d
     275: invokestatic  #153                // Method java/lang/Math.pow:(DD)D
     278: aload         11
     280: iload         17
     282: daload        
     283: dmul          
     284: dadd          
     285: dstore        8
     287: iinc          17, 1
     290: goto          62



花了大概接近一個小時,將該方法邏輯理清楚,順便去洗了下眼睛。還好jd對運算的解析還算到位,只是邏輯不清楚,不然難度還會上升N大截。  根據上面標註的信息,源碼撰寫以下:

0  > this
1  > paramArrayOfDouble
2  > d1
4  > d2
6  > d3
8  > d4
10 > arrayOfDouble1  double[]
11 > arrayOfDouble2  double[]
12 > i
13 > j
14 > k
15 > m
16 > n
17 > i1
code:
double d1 = 0.0D;
double d2 = 0.0D;
double d3 = 0.0D;
double d4 = 0.0D;
double[] arrayOfDouble1 = new double[this.grayLevel];
double[] arrayOfDouble2 = new double[this.grayLevel];

	
	for(int i=0;
30			i < this.grayLevel; i++) {
110		for(int j=0;
113				j < this.grayLevel; j++) {
142			arrayOfDouble1[i] += paramArrayOfDouble[(j + i * this.grayLevel)];
		}
122		d1 += (i + 1) * arrayOfDouble1[i];
	}
39	for(int k=0;
42			k < 32;k++) {
171		d3 += Math.pow(k + 1 - d1, 2.0D) * arrayOfDouble1[k];
	}
49	for(int m=0;
52			m < 32;m++) {
201		for(int n=0; n<32; n++) {
233			arrayOfDouble2[m] += paramArrayOfDouble[(m + n * this.grayLevel)];
		}
		d2 += (m + 1) * arrayOfDouble2[m];
	}
59	for(int i1=0; 
62			i1 < 32; i1++) {
262		d4 += Math.pow(i1 + 1 - d2, 2.0D) * arrayOfDouble2[i1];
	}
69	if(d3 != 0 && d4 != 0) {
		this.CORRLN = ((this.CORRLN - d1 * d2) / Math.sqrt(d3 * d4));
	}
	return this.CORRLN;
OK,邏輯基本理清完整,放入工程,一切正常,目前還須要作測試,看看運算結果是否和原包結果一致。 這階段就到這裏,眼睛痛。
相關文章
相關標籤/搜索