1
2
3
4
5
6
7
8
9
10
11 package com.jsql.util;
12
13 import com.jsql.util.bruter.Base16;
14 import com.jsql.util.bruter.Base58;
15 import org.apache.commons.codec.binary.Base32;
16 import org.apache.commons.lang3.ArrayUtils;
17 import org.apache.commons.lang3.StringUtils;
18 import org.apache.commons.text.StringEscapeUtils;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.mozilla.universalchardet.UniversalDetector;
22
23 import java.awt.*;
24 import java.io.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.net.URLDecoder;
28 import java.net.URLEncoder;
29 import java.nio.charset.StandardCharsets;
30 import java.util.ArrayList;
31 import java.util.Base64;
32 import java.util.List;
33 import java.util.zip.DeflaterOutputStream;
34 import java.util.zip.InflaterOutputStream;
35
36
37
38
39
40 public final class StringUtil {
41
42
43
44
45 private static final Logger LOGGER = LogManager.getRootLogger();
46
47
48 private static final CharEncoder DECIMAL_HTML_ENCODER = new CharEncoder("&#", ";", 10);
49 public static final String GET = "GET";
50 public static final String POST = "POST";
51 public static final String INFORMATION_SCHEMA = "information_schema";
52 public static final String APP_NAME = "jSQL Injection";
53
54
55
56
57
58 private static class CharEncoder {
59
60 private final String prefix;
61 private final String suffix;
62 private final int radix;
63
64 public CharEncoder(String prefix, String suffix, int radix) {
65 this.prefix = prefix;
66 this.suffix = suffix;
67 this.radix = radix;
68 }
69
70 protected void encode(char c, StringBuilder buff) {
71 buff
72 .append(this.prefix)
73 .append(Integer.toString(c, this.radix))
74 .append(this.suffix);
75 }
76 }
77
78 private StringUtil() {
79
80 }
81
82
83
84
85
86
87 public static String toHtmlDecimal(String text) {
88 return StringUtil.encode(text);
89 }
90
91
92
93
94
95
96 private static String encode(String text) {
97 var buff = new StringBuilder();
98 for (var i = 0 ; i < text.length() ; i++) {
99 if (text.charAt(i) > 128) {
100 StringUtil.DECIMAL_HTML_ENCODER.encode(text.charAt(i), buff);
101 } else {
102 buff.append(text.charAt(i));
103 }
104 }
105 return buff.toString();
106 }
107
108
109
110
111
112
113 public static String hexstr(String hex) {
114 var bytes = new byte[hex.length() / 2];
115 for (var i = 0 ; i < bytes.length ; i++) {
116 bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
117 }
118 return new String(bytes, StandardCharsets.UTF_8);
119 }
120
121 public static boolean isUtf8(String text) {
122 if (text == null) {
123 return false;
124 }
125
126 var detector = new UniversalDetector(null);
127 detector.handleData(text.getBytes(StandardCharsets.UTF_8), 0, text.length() - 1);
128 detector.dataEnd();
129 String encoding = detector.getDetectedCharset();
130 return encoding != null;
131 }
132
133 public static String detectUtf8(String text) {
134 if (text == null) {
135 return StringUtils.EMPTY;
136 }
137
138 String encoding = null;
139
140
141 try {
142 var detector = new UniversalDetector(null);
143 detector.handleData(text.getBytes(StandardCharsets.UTF_8), 0, text.length() - 1);
144 detector.dataEnd();
145 encoding = detector.getDetectedCharset();
146
147 } catch (ArrayIndexOutOfBoundsException e) {
148 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
149 }
150
151 String result = text;
152 if (encoding != null) {
153 result = new String(text.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
154 }
155 return result;
156 }
157
158 public static String base32Encode(String s) {
159 var base32 = new Base32();
160 return base32.encodeToString(StringUtil.getBytesUtf8(s));
161 }
162
163 public static String base32Decode(String s) {
164 var base32 = new Base32();
165 return StringUtil.newStringUtf8(base32.decode(s));
166 }
167
168 public static String base58Encode(String s) {
169 return Base58.encode(StringUtil.getBytesUtf8(s));
170 }
171
172 public static String base58Decode(String s) {
173 return StringUtil.newStringUtf8(Base58.decode(s));
174 }
175
176 public static String base16Encode(String s) {
177 var base16 = new Base16();
178 return base16.encodeToString(StringUtil.getBytesUtf8(s));
179 }
180
181 public static String base16Decode(String s) {
182 var base16 = new Base16();
183 return StringUtil.newStringUtf8(base16.decode(s));
184 }
185
186 public static String base64Decode(String s) {
187 return StringUtil.newStringUtf8(Base64.getDecoder().decode(s));
188 }
189
190 public static String base64Encode(String s) {
191 return Base64.getEncoder().encodeToString(StringUtil.getBytesUtf8(s));
192 }
193
194 public static String toHex(String text) {
195 return StringUtil.encodeHexString(text.getBytes(StandardCharsets.UTF_8));
196 }
197
198 public static String fromHex(String text) {
199 byte[] hex = StringUtil.decodeHexString(text);
200 return new String(hex, StandardCharsets.UTF_8);
201 }
202
203 public static String toHexZip(String text) throws IOException {
204 byte[] zip = StringUtil.compress(text);
205 return StringUtil.encodeHexString(zip);
206 }
207
208 public static String fromHexZip(String text) throws IOException {
209 return new String(StringUtil.decompress(StringUtil.decodeHexString(text)), StandardCharsets.UTF_8);
210 }
211
212 public static String toBase64Zip(String text) throws IOException {
213 return new String(Base64.getEncoder().encode(StringUtil.compress(text)));
214 }
215
216 public static String fromBase64Zip(String text) throws IOException {
217 byte[] decompressedBArray = StringUtil.decompress(Base64.getDecoder().decode(text));
218 return new String(decompressedBArray, StandardCharsets.UTF_8);
219 }
220
221 public static String toHtml(String text) {
222 return StringEscapeUtils.escapeHtml4(text);
223 }
224
225 public static String fromHtml(String text) {
226 return StringEscapeUtils.unescapeHtml4(text);
227 }
228
229 public static String toUrl(String text) {
230 return URLEncoder.encode(text, StandardCharsets.UTF_8);
231 }
232
233 public static String fromUrl(String text) {
234 return URLDecoder.decode(text, StandardCharsets.UTF_8);
235 }
236
237 public static String cleanSql(String query) {
238 return StringUtil.removeSqlComment(query)
239 .replaceAll("(?s)([^\\s\\w])(\\s+)", "$1")
240 .replaceAll("(?s)(\\s+)([^\\s\\w])", "$2")
241 .replaceAll("(?s)\\s+", " ")
242 .trim();
243 }
244
245
246
247
248
249
250 public static String removeSqlComment(String query) {
251 return query.replaceAll(
252 "(?s)(?!/\\*\\*/|/\\*!.*\\*/)/\\*.*?\\*/",
253 StringUtils.EMPTY
254 );
255 }
256
257 public static String formatReport(Color color, String text) {
258 return String.format(
259 "<span style=color:rgb(%s,%s,%s)>%s</span>",
260 color.getRed(),
261 color.getGreen(),
262 color.getBlue(),
263 text
264 );
265 }
266
267
268
269
270 private static byte[] compress(String text) throws IOException {
271 ByteArrayOutputStream os = new ByteArrayOutputStream();
272 try (DeflaterOutputStream dos = new DeflaterOutputStream(os)) {
273 dos.write(text.getBytes());
274 }
275 return os.toByteArray();
276 }
277
278 private static byte[] decompress(byte[] compressedTxt) throws IOException {
279 ByteArrayOutputStream os = new ByteArrayOutputStream();
280 try (OutputStream ios = new InflaterOutputStream(os)) {
281 ios.write(compressedTxt);
282 }
283 return os.toByteArray();
284 }
285
286 private static byte hexToByte(String hexString) {
287 int firstDigit = StringUtil.toDigit(hexString.charAt(0));
288 int secondDigit = StringUtil.toDigit(hexString.charAt(1));
289 return (byte) ((firstDigit << 4) + secondDigit);
290 }
291
292 private static int toDigit(char hexChar) {
293 int digit = Character.digit(hexChar, 16);
294 if (digit == -1) {
295 throw new IllegalArgumentException("Invalid Hexadecimal Character: "+ hexChar);
296 }
297 return digit;
298 }
299
300 private static String byteToHex(byte num) {
301 char[] hexDigits = new char[2];
302 hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
303 hexDigits[1] = Character.forDigit((num & 0xF), 16);
304 return new String(hexDigits);
305 }
306
307 private static String encodeHexString(byte[] byteArray) {
308 StringBuilder hexStringBuffer = new StringBuilder();
309 for (byte b : byteArray) {
310 hexStringBuffer.append(StringUtil.byteToHex(b));
311 }
312 return hexStringBuffer.toString();
313 }
314
315 private static byte[] decodeHexString(String hexString) {
316 if (hexString.length() % 2 == 1) {
317 throw new IllegalArgumentException("Invalid hexadecimal String supplied.");
318 }
319 byte[] bytes = new byte[hexString.length() / 2];
320 for (int i = 0; i < hexString.length(); i += 2) {
321 bytes[i / 2] = StringUtil.hexToByte(hexString.substring(i, i + 2));
322 }
323 return bytes;
324 }
325
326 private static byte[] getBytesUtf8(String string) {
327 return string == null ? null : string.getBytes(StandardCharsets.UTF_8);
328 }
329
330 private static String newStringUtf8(byte[] bytes) {
331 return bytes == null ? null : new String(bytes, StandardCharsets.UTF_8);
332 }
333
334 public static byte[] xor(byte[] plaintext, int key) {
335 var ciphertext = new byte[plaintext.length];
336 for (var i = 0; i < plaintext.length; i++) {
337 ciphertext[i] = (byte) (plaintext[i] ^ (key >>> (8 * (i % 4))));
338 }
339 return ciphertext;
340 }
341
342 public static List<String> toHexChunks(byte[] fileData) {
343 StringBuilder hexString = new StringBuilder();
344 for (byte b : fileData) {
345 hexString.append(String.format("%02X", b));
346 }
347 int chunkSize = 900;
348 List<String> chunks = new ArrayList<>();
349 for (int i = 0; i < hexString.length(); i += chunkSize) {
350 int endIndex = Math.min(i + chunkSize, hexString.length());
351 chunks.add(hexString.substring(i, endIndex));
352 }
353 return chunks;
354 }
355
356 public static byte[] uncloak(byte[] fileData) {
357 fileData = StringUtil.xor(fileData, 353837730);
358 ArrayUtils.reverse(fileData);
359 return fileData;
360 }
361 }