在這裏講述的實際上是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
相信學過彙編的對這些都不陌生,若是你看得頭暈,那就沒轍了,由於這只是窗口大小的代碼,一箇中等方法大概有這樣的代碼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
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,邏輯基本理清完整,放入工程,一切正常,目前還須要作測試,看看運算結果是否和原包結果一致。 這階段就到這裏,眼睛痛。