java 混淆字符串_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
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字符串混淆与还原相关推荐
- java 数组 字符串 编程_Java语言基础知识之字符串数组
Java语言基础知识之字符串数组 java语言中,数组是一种最简单的复合数据类型.数组是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和下标来唯一地确定数组中的元素.数组有 ...
- java 正则表达式语法_Java 正则表达式基础语法
基础符号 首尾匹配^:匹配输入字符串开始的位置 $:匹配输入字符串结尾的位置 例:"^hello$"含义为该字符串开头必须为h,结尾必须为oprivate static void ...
- java手机教程_Java手机基础教程 (普通高等教育“十二五”规划教材(动漫游戏类))...
丛书序 前言 第1章 程序设计概述 1.1 程序设计语言的分类 1.1.1 按发展过程分类 1.1.2 按执行方式分类 1.1.3 按思维模式分类 1.2 Java的简介 1.2.1 Java的历史和 ...
- 零基础java自学就业_java零基础到就业需要多长时间呢?
展开全部 先以肯定的语气说明一下自学e68a84e8a2ad62616964757a686964616f31333433663030Java,多久可以找到工作: 按照目前Java的体系来说,Java的 ...
- java时间戳龙_Java时间戳与日期格式字符串的互转
Java时间戳与日期格式字符串的互转 import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { ...
- java入门考点_java入门基础知识点总结
JavaScript他是一种描述性语言,其实他并不难学,只要用心学,一定会学好,我相信大家在看这篇文章的时候,一定也学过HTML吧,使用JavaScript就是为了能和网页有更好的交互,下面切入主题. ...
- java输入数字返回字符串_java Scanner输入数字、字符串
package java05; import java.util.Scanner;//1.导包 /* Scanner类的功能,可以实现键盘输入数据,到程序当中 引用类型的一班使用步骤: 1.导包 2. ...
- python中abc属于字符串吗_Python基础学习:字符串
Python 版本: 3.6.2 操作系统: Windows 作者: SmallWZQ 在 Python 中,字符串也是一种数据类型.相比其它数据类型,字符串算是比较复杂的.为 何呢?因为字符串不仅包 ...
- java逆向_Java逆向基础之异常
异常 由之前月份处理修改的例子 //清单1IncorrectMonthException.javapublic class IncorrectMonthException extends Except ...
最新文章
- 2023年中国AI论文影响力超越美国?网友:长期看,数量不等于质量
- C++11判断inf, nan
- Bash脚本教程之函数
- 注意力公式步骤每一步的含义,总共三步
- MySql 安装 Win python3
- 推荐:没有项目经验,可以读一下这几个开源的企业级项目...
- 计算机崩溃用英语怎么说,“我要崩溃了”英语怎么说?
- 编译原理第四章课后题答案
- 5个免费音效素材网站
- linux tar命令将压缩包解压到指定位置,用tar命令把目标压缩包解压到指定位置
- linaro交叉编译工具安装配置
- 数据库管理工具 FreeSQL
- R语言实战-第九章 R in action-chapter9
- 在微信公众号中添加外部的链接图文教程
- LinQ,WCF,ExtJs之”初吻“
- 石油、化工 工程上都在用的地下管线探测仪---TFN A1200
- oracle wd2go 转_WD2go的作用是()。
- 【转】评论:诺基亚缺乏“谎言” 苹果因此得胜
- 微信也能设置彩色昵称,你知道吗?
- 15款最好用的思维导图(心智图 )工具
热门文章
- 电脑公司最新GHOST WIN7系统32,64位优化精简版下载
- 数据分析——确定分析思路
- 【Pytorch】对比CrossEntropyLoss与NLLLoss
- 第二篇:Go基础入门
- jarvisoj_level6_x64(buuctf)--unlink利用
- 魔兽世界3.3.5 TrinityCore - 自定义珠宝商人
- CentOS 7.6 下搭建Socks 5服务
- Android 集成华为推送,集成小米推送,集成OPPO推送,集成vivo推送
- python爬虫(十四)selenium(select、17素材网、模拟登录豆瓣和QQ空间、获取cookie、行为链)
- python图像锐化滤波_OpenCV-Python学习(九):图像滤波