为了防止静态分析,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

var5 += 256;

}

int var6 = ((var1 & '\uffff') >>> 8) - var4;

if (var6

var6 += 256;

}

for(int var7 = 0; var7

int var8 = var7 % 2;

char var10002 = var3[var7];

if (var8 == 0) {

var3[var7] = (char)(var10002 ^ var5);

var5 = ((var5 >>> 3 | var5 <

} else {

var3[var7] = (char)(var10002 ^ var6);

var6 = ((var6 >>> 3 | var6 <

}

}

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[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

v1 += 256; // 这里相当于&0xff,因为上面做减法位数拓展,通过这个转回

}

int v2 = ((iv & '\uffff') >>> 8) - v0; // iv取高8位 -v0

if (v2

v2 += 256;

}

for (int i = 0; i

if (i % 2 == 0) {

ch[i] = (char) (ch[i] ^ v1);

v1 = ((v1 >>> 3 | v1 <

} else {

ch[i] = (char) (ch[i] ^ v2);

v2 = ((v2 >>> 3 | v2 <

}

}

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])));

}

}

输出结果如下

java 混淆字符串_Java逆向基础之ZKM字符串混淆与还原相关推荐

  1. java 数组 字符串 编程_Java语言基础知识之字符串数组

    Java语言基础知识之字符串数组 java语言中,数组是一种最简单的复合数据类型.数组是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和下标来唯一地确定数组中的元素.数组有 ...

  2. java 正则表达式语法_Java 正则表达式基础语法

    基础符号 首尾匹配^:匹配输入字符串开始的位置 $:匹配输入字符串结尾的位置 例:"^hello$"含义为该字符串开头必须为h,结尾必须为oprivate static void ...

  3. java手机教程_Java手机基础教程 (普通高等教育“十二五”规划教材(动漫游戏类))...

    丛书序 前言 第1章 程序设计概述 1.1 程序设计语言的分类 1.1.1 按发展过程分类 1.1.2 按执行方式分类 1.1.3 按思维模式分类 1.2 Java的简介 1.2.1 Java的历史和 ...

  4. 零基础java自学就业_java零基础到就业需要多长时间呢?

    展开全部 先以肯定的语气说明一下自学e68a84e8a2ad62616964757a686964616f31333433663030Java,多久可以找到工作: 按照目前Java的体系来说,Java的 ...

  5. java时间戳龙_Java时间戳与日期格式字符串的互转

    Java时间戳与日期格式字符串的互转 import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { ...

  6. java入门考点_java入门基础知识点总结

    JavaScript他是一种描述性语言,其实他并不难学,只要用心学,一定会学好,我相信大家在看这篇文章的时候,一定也学过HTML吧,使用JavaScript就是为了能和网页有更好的交互,下面切入主题. ...

  7. java输入数字返回字符串_java Scanner输入数字、字符串

    package java05; import java.util.Scanner;//1.导包 /* Scanner类的功能,可以实现键盘输入数据,到程序当中 引用类型的一班使用步骤: 1.导包 2. ...

  8. python中abc属于字符串吗_Python基础学习:字符串

    Python 版本: 3.6.2 操作系统: Windows 作者: SmallWZQ 在 Python 中,字符串也是一种数据类型.相比其它数据类型,字符串算是比较复杂的.为 何呢?因为字符串不仅包 ...

  9. java逆向_Java逆向基础之异常

    异常 由之前月份处理修改的例子 //清单1IncorrectMonthException.javapublic class IncorrectMonthException extends Except ...

最新文章

  1. 2023年中国AI论文影响力超越美国?网友:长期看,数量不等于质量
  2. C++11判断inf, nan
  3. Bash脚本教程之函数
  4. 注意力公式步骤每一步的含义,总共三步
  5. MySql 安装 Win python3
  6. 推荐:没有项目经验,可以读一下这几个开源的企业级项目...
  7. 计算机崩溃用英语怎么说,“我要崩溃了”英语怎么说?
  8. 编译原理第四章课后题答案
  9. 5个免费音效素材网站
  10. linux tar命令将压缩包解压到指定位置,用tar命令把目标压缩包解压到指定位置
  11. linaro交叉编译工具安装配置
  12. 数据库管理工具 FreeSQL
  13. R语言实战-第九章 R in action-chapter9
  14. 在微信公众号中添加外部的链接图文教程
  15. LinQ,WCF,ExtJs之”初吻“
  16. 石油、化工 工程上都在用的地下管线探测仪---TFN A1200
  17. oracle wd2go 转_WD2go的作用是()。
  18. 【转】评论:诺基亚缺乏“谎言” 苹果因此得胜
  19. 微信也能设置彩色昵称,你知道吗?
  20. 15款最好用的思维导图(心智图 )工具

热门文章

  1. 电脑公司最新GHOST WIN7系统32,64位优化精简版下载
  2. 数据分析——确定分析思路
  3. 【Pytorch】对比CrossEntropyLoss与NLLLoss
  4. 第二篇:Go基础入门
  5. jarvisoj_level6_x64(buuctf)--unlink利用
  6. 魔兽世界3.3.5 TrinityCore - 自定义珠宝商人
  7. CentOS 7.6 下搭建Socks 5服务
  8. Android 集成华为推送,集成小米推送,集成OPPO推送,集成vivo推送
  9. python爬虫(十四)selenium(select、17素材网、模拟登录豆瓣和QQ空间、获取cookie、行为链)
  10. python图像锐化滤波_OpenCV-Python学习(九):图像滤波