Java逆向基础之ZKM字符串混淆与还原

为了防止静态分析,ZMK在混淆时对输出的字符串使用对称加密方法进行加密

早期的ZKM只在静态代码块的时候进行简单的异或加密,后续版本使用了流加密技术进行二次加密

看一个简单的字符串输出例子

package com.vvvtimes.main;

public class Main {
	public static void main(String[] args) {
		System.out.println("Hello");
		System.out.println("World");
	}
}

混淆反编译之后的代码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.vvvtimes.main;

public class a {
    public static int a;
    public static int b;
    private static String[] c;
    private static String[] d;

    public a() {
    }

    public static void main(String[] var0) {
        int var10000 = b;
        System.out.println(a(-7991, 8444));
        int var1 = var10000;
        System.out.println(a(-7992, -25829));
        if (var1 != 0) {
            int var2 = a;
            ++var2;
            a = var2;
        }

    }

    static {
        String[] var5 = new String[2];
        int var3 = 0;
        String var2 = "\u0093íè[Í\u0005ükçÀú"; 
        int var4 = var2.length();
        char var1 = 5;
        int var0 = -1;

        boolean flag =true;

        while(flag) {
            char[] var10002;
            label41: {
                ++var0;
                char[] var10001 = var2.substring(var0, var0 + var1).toCharArray();
                int var10003 = var10001.length;
                int var6 = 0;
                var10002 = var10001;
                int var7 = var10003;
                char[] var9;
                int var10004;
                if (var10003 <= 1) {
                    var9 = var10001;
                    var10004 = var6;
                } else {
                    var10002 = var10001;
                    var7 = var10003;
                    if (var10003 <= var6) {
                        break label41;
                    }

                    var9 = var10001;
                    var10004 = var6;
                }
                

                while(true) {
                    char var10005 = var9[var10004];
                    byte var10006;
                    switch(var6 % 7) {
                        case 0:
                            var10006 = 116;
                            break;
                        case 1:
                            var10006 = 91;
                            break;
                        case 2:
                            var10006 = 57;
                            break;
                        case 3:
                            var10006 = 40;
                            break;
                        case 4:
                            var10006 = 121;
                            break;
                        case 5:
                            var10006 = 92;
                            break;
                        default:
                            var10006 = 118;
                    }

                    var9[var10004] = (char)(var10005 ^ var10006);
                    ++var6;
                    if (var7 == 0) {
                        var10004 = var7;
                        var9 = var10002;
                    } else {
                        if (var7 <= var6) {
                            break;
                        }

                        var9 = var10002;
                        var10004 = var6;
                    }
                }
            }
            

            String var11 = (new String(var10002)).intern();
            var5[var3++] = var11;
            if ((var0 += var1) >= var4) {
                c = var5;
                d = new String[2];
                flag=false;
            }else{
                var1 = var2.charAt(var0);
            }


        }
    }

    private static String a(int var0, int var1) {
        int var2 = (var0 ^ -7991) & '\uffff';
        if (d[var2] == null) {
            char[] var3 = c[var2].toCharArray();
            short var10000;
            switch(var3[0] & 255) {
                case 0:
                    var10000 = 181;
                    break;
                case 1:
                    var10000 = 149;
                    break;
                case 2:
                    var10000 = 85;
                    break;
                case 3:
                    var10000 = 171;
                    break;
                case 4:
                    var10000 = 128;
                    break;
                case 5:
                    var10000 = 103;
                    break;
                case 6:
                    var10000 = 238;
                    break;
                case 7:
                    var10000 = 159;
                    break;
                case 8:
                    var10000 = 225;
                    break;
                case 9:
                    var10000 = 234;
                    break;
                case 10:
                    var10000 = 14;
                    break;
                case 11:
                    var10000 = 200;
                    break;
                case 12:
                    var10000 = 138;
                    break;
                case 13:
                    var10000 = 205;
                    break;
                case 14:
                    var10000 = 127;
                    break;
                case 15:
                    var10000 = 50;
                    break;
                case 16:
                    var10000 = 186;
                    break;
                case 17:
                    var10000 = 169;
                    break;
                case 18:
                    var10000 = 68;
                    break;
                case 19:
                    var10000 = 61;
                    break;
                case 20:
                    var10000 = 10;
                    break;
                case 21:
                    var10000 = 46;
                    break;
                case 22:
                    var10000 = 121;
                    break;
                case 23:
                    var10000 = 230;
                    break;
                case 24:
                    var10000 = 80;
                    break;
                case 25:
                    var10000 = 89;
                    break;
                case 26:
                    var10000 = 0;
                    break;
                case 27:
                    var10000 = 24;
                    break;
                case 28:
                    var10000 = 167;
                    break;
                case 29:
                    var10000 = 5;
                    break;
                case 30:
                    var10000 = 132;
                    break;
                case 31:
                    var10000 = 53;
                    break;
                case 32:
                    var10000 = 81;
                    break;
                case 33:
                    var10000 = 231;
                    break;
                case 34:
                    var10000 = 141;
                    break;
                case 35:
                    var10000 = 251;
                    break;
                case 36:
                    var10000 = 241;
                    break;
                case 37:
                    var10000 = 219;
                    break;
                case 38:
                    var10000 = 173;
                    break;
                case 39:
                    var10000 = 20;
                    break;
                case 40:
                    var10000 = 38;
                    break;
                case 41:
                    var10000 = 182;
                    break;
                case 42:
                    var10000 = 229;
                    break;
                case 43:
                    var10000 = 67;
                    break;
                case 44:
                    var10000 = 183;
                    break;
                case 45:
                    var10000 = 188;
                    break;
                case 46:
                    var10000 = 222;
                    break;
                case 47:
                    var10000 = 107;
                    break;
                case 48:
                    var10000 = 248;
                    break;
                case 49:
                    var10000 = 244;
                    break;
                case 50:
                    var10000 = 156;
                    break;
                case 51:
                    var10000 = 88;
                    break;
                case 52:
                    var10000 = 246;
                    break;
                case 53:
                    var10000 = 240;
                    break;
                case 54:
                    var10000 = 13;
                    break;
                case 55:
                    var10000 = 211;
                    break;
                case 56:
                    var10000 = 49;
                    break;
                case 57:
                    var10000 = 144;
                    break;
                case 58:
                    var10000 = 40;
                    break;
                case 59:
                    var10000 = 21;
                    break;
                case 60:
                    var10000 = 130;
                    break;
                case 61:
                    var10000 = 179;
                    break;
                case 62:
                    var10000 = 202;
                    break;
                case 63:
                    var10000 = 194;
                    break;
                case 64:
                    var10000 = 201;
                    break;
                case 65:
                    var10000 = 174;
                    break;
                case 66:
                    var10000 = 117;
                    break;
                case 67:
                    var10000 = 99;
                    break;
                case 68:
                    var10000 = 137;
                    break;
                case 69:
                    var10000 = 6;
                    break;
                case 70:
                    var10000 = 12;
                    break;
                case 71:
                    var10000 = 153;
                    break;
                case 72:
                    var10000 = 213;
                    break;
                case 73:
                    var10000 = 206;
                    break;
                case 74:
                    var10000 = 93;
                    break;
                case 75:
                    var10000 = 249;
                    break;
                case 76:
                    var10000 = 33;
                    break;
                case 77:
                    var10000 = 28;
                    break;
                case 78:
                    var10000 = 120;
                    break;
                case 79:
                    var10000 = 95;
                    break;
                case 80:
                    var10000 = 37;
                    break;
                case 81:
                    var10000 = 4;
                    break;
                case 82:
                    var10000 = 55;
                    break;
                case 83:
                    var10000 = 237;
                    break;
                case 84:
                    var10000 = 102;
                    break;
                case 85:
                    var10000 = 196;
                    break;
                case 86:
                    var10000 = 34;
                    break;
                case 87:
                    var10000 = 216;
                    break;
                case 88:
                    var10000 = 143;
                    break;
                case 89:
                    var10000 = 98;
                    break;
                case 90:
                    var10000 = 133;
                    break;
                case 91:
                    var10000 = 94;
                    break;
                case 92:
                    var10000 = 203;
                    break;
                case 93:
                    var10000 = 254;
                    break;
                case 94:
                    var10000 = 92;
                    break;
                case 95:
                    var10000 = 2;
                    break;
                case 96:
                    var10000 = 16;
                    break;
                case 97:
                    var10000 = 124;
                    break;
                case 98:
                    var10000 = 48;
                    break;
                case 99:
                    var10000 = 11;
                    break;
                case 100:
                    var10000 = 3;
                    break;
                case 101:
                    var10000 = 163;
                    break;
                case 102:
                    var10000 = 221;
                    break;
                case 103:
                    var10000 = 195;
                    break;
                case 104:
                    var10000 = 192;
                    break;
                case 105:
                    var10000 = 59;
                    break;
                case 106:
                    var10000 = 119;
                    break;
                case 107:
                    var10000 = 161;
                    break;
                case 108:
                    var10000 = 72;
                    break;
                case 109:
                    var10000 = 29;
                    break;
                case 110:
                    var10000 = 160;
                    break;
                case 111:
                    var10000 = 224;
                    break;
                case 112:
                    var10000 = 198;
                    break;
                case 113:
                    var10000 = 41;
                    break;
                case 114:
                    var10000 = 42;
                    break;
                case 115:
                    var10000 = 65;
                    break;
                case 116:
                    var10000 = 114;
                    break;
                case 117:
                    var10000 = 136;
                    break;
                case 118:
                    var10000 = 176;
                    break;
                case 119:
                    var10000 = 22;
                    break;
                case 120:
                    var10000 = 122;
                    break;
                case 121:
                    var10000 = 209;
                    break;
                case 122:
                    var10000 = 129;
                    break;
                case 123:
                    var10000 = 100;
                    break;
                case 124:
                    var10000 = 112;
                    break;
                case 125:
                    var10000 = 82;
                    break;
                case 126:
                    var10000 = 43;
                    break;
                case 127:
                    var10000 = 35;
                    break;
                case 128:
                    var10000 = 83;
                    break;
                case 129:
                    var10000 = 189;
                    break;
                case 130:
                    var10000 = 255;
                    break;
                case 131:
                    var10000 = 78;
                    break;
                case 132:
                    var10000 = 239;
                    break;
                case 133:
                    var10000 = 52;
                    break;
                case 134:
                    var10000 = 252;
                    break;
                case 135:
                    var10000 = 116;
                    break;
                case 136:
                    var10000 = 60;
                    break;
                case 137:
                    var10000 = 193;
                    break;
                case 138:
                    var10000 = 207;
                    break;
                case 139:
                    var10000 = 101;
                    break;
                case 140:
                    var10000 = 142;
                    break;
                case 141:
                    var10000 = 51;
                    break;
                case 142:
                    var10000 = 74;
                    break;
                case 143:
                    var10000 = 76;
                    break;
                case 144:
                    var10000 = 154;
                    break;
                case 145:
                    var10000 = 145;
                    break;
                case 146:
                    var10000 = 105;
                    break;
                case 147:
                    var10000 = 30;
                    break;
                case 148:
                    var10000 = 31;
                    break;
                case 149:
                    var10000 = 27;
                    break;
                case 150:
                    var10000 = 204;
                    break;
                case 151:
                    var10000 = 54;
                    break;
                case 152:
                    var10000 = 7;
                    break;
                case 153:
                    var10000 = 110;
                    break;
                case 154:
                    var10000 = 166;
                    break;
                case 155:
                    var10000 = 123;
                    break;
                case 156:
                    var10000 = 150;
                    break;
                case 157:
                    var10000 = 208;
                    break;
                case 158:
                    var10000 = 115;
                    break;
                case 159:
                    var10000 = 75;
                    break;
                case 160:
                    var10000 = 134;
                    break;
                case 161:
                    var10000 = 36;
                    break;
                case 162:
                    var10000 = 199;
                    break;
                case 163:
                    var10000 = 125;
                    break;
                case 164:
                    var10000 = 210;
                    break;
                case 165:
                    var10000 = 109;
                    break;
                case 166:
                    var10000 = 17;
                    break;
                case 167:
                    var10000 = 71;
                    break;
                case 168:
                    var10000 = 152;
                    break;
                case 169:
                    var10000 = 104;
                    break;
                case 170:
                    var10000 = 178;
                    break;
                case 171:
                    var10000 = 44;
                    break;
                case 172:
                    var10000 = 165;
                    break;
                case 173:
                    var10000 = 87;
                    break;
                case 174:
                    var10000 = 235;
                    break;
                case 175:
                    var10000 = 1;
                    break;
                case 176:
                    var10000 = 220;
                    break;
                case 177:
                    var10000 = 108;
                    break;
                case 178:
                    var10000 = 106;
                    break;
                case 179:
                    var10000 = 148;
                    break;
                case 180:
                    var10000 = 56;
                    break;
                case 181:
                    var10000 = 15;
                    break;
                case 182:
                    var10000 = 250;
                    break;
                case 183:
                    var10000 = 62;
                    break;
                case 184:
                    var10000 = 151;
                    break;
                case 185:
                    var10000 = 26;
                    break;
                case 186:
                    var10000 = 243;
                    break;
                case 187:
                    var10000 = 57;
                    break;
                case 188:
                    var10000 = 172;
                    break;
                case 189:
                    var10000 = 66;
                    break;
                case 190:
                    var10000 = 197;
                    break;
                case 191:
                    var10000 = 223;
                    break;
                case 192:
                    var10000 = 228;
                    break;
                case 193:
                    var10000 = 63;
                    break;
                case 194:
                    var10000 = 19;
                    break;
                case 195:
                    var10000 = 70;
                    break;
                case 196:
                    var10000 = 126;
                    break;
                case 197:
                    var10000 = 164;
                    break;
                case 198:
                    var10000 = 212;
                    break;
                case 199:
                    var10000 = 158;
                    break;
                case 200:
                    var10000 = 227;
                    break;
                case 201:
                    var10000 = 139;
                    break;
                case 202:
                    var10000 = 111;
                    break;
                case 203:
                    var10000 = 91;
                    break;
                case 204:
                    var10000 = 23;
                    break;
                case 205:
                    var10000 = 253;
                    break;
                case 206:
                    var10000 = 147;
                    break;
                case 207:
                    var10000 = 170;
                    break;
                case 208:
                    var10000 = 226;
                    break;
                case 209:
                    var10000 = 97;
                    break;
                case 210:
                    var10000 = 39;
                    break;
                case 211:
                    var10000 = 155;
                    break;
                case 212:
                    var10000 = 79;
                    break;
                case 213:
                    var10000 = 247;
                    break;
                case 214:
                    var10000 = 215;
                    break;
                case 215:
                    var10000 = 233;
                    break;
                case 216:
                    var10000 = 218;
                    break;
                case 217:
                    var10000 = 118;
                    break;
                case 218:
                    var10000 = 175;
                    break;
                case 219:
                    var10000 = 32;
                    break;
                case 220:
                    var10000 = 135;
                    break;
                case 221:
                    var10000 = 18;
                    break;
                case 222:
                    var10000 = 69;
                    break;
                case 223:
                    var10000 = 168;
                    break;
                case 224:
                    var10000 = 242;
                    break;
                case 225:
                    var10000 = 86;
                    break;
                case 226:
                    var10000 = 245;
                    break;
                case 227:
                    var10000 = 45;
                    break;
                case 228:
                    var10000 = 25;
                    break;
                case 229:
                    var10000 = 236;
                    break;
                case 230:
                    var10000 = 180;
                    break;
                case 231:
                    var10000 = 77;
                    break;
                case 232:
                    var10000 = 157;
                    break;
                case 233:
                    var10000 = 73;
                    break;
                case 234:
                    var10000 = 187;
                    break;
                case 235:
                    var10000 = 214;
                    break;
                case 236:
                    var10000 = 232;
                    break;
                case 237:
                    var10000 = 64;
                    break;
                case 238:
                    var10000 = 131;
                    break;
                case 239:
                    var10000 = 9;
                    break;
                case 240:
                    var10000 = 146;
                    break;
                case 241:
                    var10000 = 58;
                    break;
                case 242:
                    var10000 = 47;
                    break;
                case 243:
                    var10000 = 191;
                    break;
                case 244:
                    var10000 = 140;
                    break;
                case 245:
                    var10000 = 185;
                    break;
                case 246:
                    var10000 = 177;
                    break;
                case 247:
                    var10000 = 8;
                    break;
                case 248:
                    var10000 = 90;
                    break;
                case 249:
                    var10000 = 96;
                    break;
                case 250:
                    var10000 = 190;
                    break;
                case 251:
                    var10000 = 184;
                    break;
                case 252:
                    var10000 = 113;
                    break;
                case 253:
                    var10000 = 162;
                    break;
                case 254:
                    var10000 = 217;
                    break;
                default:
                    var10000 = 84;
            }

            short var4 = var10000;
            int var5 = (var1 & 255) - var4;
            if (var5 < 0) {
                var5 += 256;
            }

            int var6 = ((var1 & '\uffff') >>> 8) - var4;
            if (var6 < 0) {
                var6 += 256;
            }

            for(int var7 = 0; var7 < var3.length; ++var7) {
                int var8 = var7 % 2;
                char var10002 = var3[var7];
                if (var8 == 0) {
                    var3[var7] = (char)(var10002 ^ var5);
                    var5 = ((var5 >>> 3 | var5 << 5) ^ var3[var7]) & 255;
                } else {
                    var3[var7] = (char)(var10002 ^ var6);
                    var6 = ((var6 >>> 3 | var6 << 5) ^ var3[var7]) & 255;
                }
            }

            d[var2] = (new String(var3)).intern();
        }

        return d[var2];
    }
}

反编译之后有1000行左右

static静态代码块采用异或的方式进行解密,并将结果存到静态变量数组c中

a方法采用流密码方式进行解密,第一个是数组偏移量,第二个是解密密钥。

简单分析之后,可以写出如下代码

package com.vvvtimes.main;

public class ZKMDeCodeString {
	private static String dexor(String str) { // 静态代码块改写,使用此方法可得到静态变量的字符串,但是有的是明文有的是密文
		char key[] = new char[] { 116, 91, 57, 40, 121, 92, 118 };
		char arr[] = str.toCharArray();
		for (int i = 0; i < arr.length; i++) {
			arr[i] ^= key[i % 7];
		}
		return new String(arr);
	}

	private static String decryption(int iv, String str) {// a方法改写,去掉第一个变量,增加需要解密的字符串参数

		char[] ch = str.toCharArray();
		short key[] = new short[] { 181, 149, 85, 171, 128, 103, 238, 159, 225, 234, 14, 200, 138, 205, 127, 50, 186,
				169, 68, 61, 10, 46, 121, 230, 80, 89, 0, 24, 167, 5, 132, 53, 81, 231, 141, 251, 241, 219, 173, 20, 38,
				182, 229, 67, 183, 188, 222, 107, 248, 244, 156, 88, 246, 240, 13, 211, 49, 144, 40, 21, 130, 179, 202,
				194, 201, 174, 117, 99, 137, 6, 12, 153, 213, 206, 93, 249, 33, 28, 120, 95, 37, 4, 55, 237, 102, 196,
				34, 216, 143, 98, 133, 94, 203, 254, 92, 2, 16, 124, 48, 11, 3, 163, 221, 195, 192, 59, 119, 161, 72,
				29, 160, 224, 198, 41, 42, 65, 114, 136, 176, 22, 122, 209, 129, 100, 112, 82, 43, 35, 83, 189, 255, 78,
				239, 52, 252, 116, 60, 193, 207, 101, 142, 51, 74, 76, 154, 145, 105, 30, 31, 27, 204, 54, 7, 110, 166,
				123, 150, 208, 115, 75, 134, 36, 199, 125, 210, 109, 17, 71, 152, 104, 178, 44, 165, 87, 235, 1, 220,
				108, 106, 148, 56, 15, 250, 62, 151, 26, 243, 57, 172, 66, 197, 223, 228, 63, 19, 70, 126, 164, 212,
				158, 227, 139, 111, 91, 23, 253, 147, 170, 226, 97, 39, 155, 79, 247, 215, 233, 218, 118, 175, 32, 135,
				18, 69, 168, 242, 86, 245, 45, 25, 236, 180, 77, 157, 73, 187, 214, 232, 64, 131, 9, 146, 58, 47, 191,
				140, 185, 177, 8, 90, 96, 190, 184, 113, 162, 217, 84 };

		short v0 = key[ch[0] & 255]; // v0取字符串低8位,取映射
		int v1 = (iv & 255) - v0; // iv取低8位 -v0
		if (v1 < 0) {
			v1 += 256; // 这里相当于&0xff,因为上面做减法位数拓展,通过这个转回
		}

		int v2 = ((iv & '\uffff') >>> 8) - v0; // iv取高8位 -v0
		if (v2 < 0) {
			v2 += 256;
		}
		
		for (int i = 0; i < ch.length; ++i) {
			if (i % 2 == 0) {
				ch[i] = (char) (ch[i] ^ v1);
				v1 = ((v1 >>> 3 | v1 << 5) ^ ch[i]) & 255;
			} else {
				ch[i] = (char) (ch[i] ^ v2);
				v2 = ((v2 >>> 3 | v2 << 5) ^ ch[i]) & 255;
			}
		}
		return new String(ch);
	}

	public static void main(String args[]) {
		String cipherText = "\u0093íè[Í\u0005ükçÀú";
		String[] cipherArray = new String[] { cipherText.substring(0, 5), cipherText.substring(6, 11) };

		System.out.println(cipherArray[0]); // “íè[Í --> ç¶Ñs´ --> Hello
		System.out.println(dexor(cipherArray[0]));
		System.out.println(decryption(8444, dexor(cipherArray[0])));

		System.out.println(cipherArray[1]); // ükçÀú --> ˆ0Þè --> World
		System.out.println(dexor(cipherArray[1]));
		System.out.println(decryption(-25829, dexor(cipherArray[1])));

	}
}

输出结果如下

QQ截图20180426191854.png


后记20180430:找到一个去ZKM字符串混淆的工具,还没试过,有兴趣的读者可以尝试下:https://github.com/GraxCode/ZKM-8-String-Deobfuscator




猜你喜欢

转载自blog.51cto.com/7317859/2108290