challenge descriptionAGZ Crackme 4, some fun in here if you can get past the byte code mashup. Would love an keygen and also a roadmap on how you got there. Have fun folks!"Byte code mashup" sounds like obfuscation, but we'll see about that.
main(String[])public static final void main(final String[] array) {
exit(5);
System.out.println(getRuntime(I.I(1)));
final String equals = equals();
System.out.println(getRuntime(I.I(14)));
final String equals2 = equals();
if (!append(equals2)) {
System.out.println(I.I(35));
} else {
final double double1 = Double.parseDouble(equals2);
final double decode = decode(double1);
final double decode2 = decode(availableProcessors(equals));
final int n = (int)decode2;
final int n2 = (int)decode;
length(getDecoder(decode2, double1));
}
in();
}
getRuntime()private static String getRuntime(final String s) {
return new String(Base64.getDecoder().decode(s));
}
I.classpublic class I {
static byte[] getResourceAsStream;
static String[] intern;
static int[] read;
// Static initialization
static {
I.intern = new String[256];
I.read = new int[256];
try {
// Open I.gif as stream of bytes
final InputStream resourceAsStream = new I().getClass().getResourceAsStream(
new StringBuffer().append('I').append('.').append('g').append('i').append('f').toString()
);
if (resourceAsStream != null) {
// Read the first 3 bytes of I.gif as a integer
int i = resourceAsStream.read() << 16 | resourceAsStream.read() << 8 | resourceAsStream.read();
I.getResourceAsStream = new byte[i];
int j = 0;
// Casting i as (byte) it takes the LOBYTE of the three byte value
final byte b = (byte)i;
final byte[] getResourceAsStream = I.getResourceAsStream;
// Outer loop, "chunkifies" the I.gif data
while (i != 0) {
final int read = resourceAsStream.read(getResourceAsStream, j, i);
if (read == -1) {
break;
}
i -= read;
// Inner loop decrypts the chunk, by the LOBYTE of the data length
while (j < read + j) {
final byte[] array = getResourceAsStream;
final int n = j;
array[n] ^= b;
++j;
}
}
resourceAsStream.close();
}
} catch (Exception ex) {}
}
// Parser
public static final synchronized String I(int n) {
final int n2 = n & 0xFF;
if (I.read[n2] != n) {
if ((I.read[n2] = n) < 0) {
n & 0xFFFF;
}
// this is basically a String.substring(int, int) implementation
I.intern[n2] = new String(I.getResourceAsStream, n, I.getResourceAsStream[n - 1] & 0xFF).intern();
}
return I.intern[n2];
}
}
decrypted string | description |
---|---|
VXNlcm5hbWU= | decrypted to "Username" |
RW50ZXIgYSBudW1iZXI= | decrypted to "Enter a number" |
Sorry, only Double accepted. | Input validation error |
Got the solution? | Exit message, line 1 |
ship it off to me then.. | Exit message, line 2 |
crackme [at] agz [dot] name | Exit message, line 3 |
https://www.agz.name | Exit message, line 4 |
https://www.facebook.com/AGZ.name/ | Exit message, line 5 |
Q29uZ3JhdHosIG5vdyB3cml0ZSBtZSBhbmQg a2V5Z2VuIHdpdGggYSBleHBsYW5hdGlvbg== | decrypted to "Congratz, now write me and keygen with a explanation". That's the good end. |
U29ycnkgbGFkZGllLCBuZWVkIHNvbWUgbW9y ZSBkZWJ1Z2dpbmcgaGVyZS4uLg== | decrypted to "Sorry laddie, need some more debugging here...". That's the bad end. |
U29ycnksIHlvdSBuZWVkIHRvIGVudGVyIGFuIGNvZGU= | decrypted to "Sorry, you need to enter an code". Input validation error. |
AGZ Crackme no | Welcome message, line 1. The 5 comes as a integer. |
There will be some fun in here | Welcome message, line 2. |
See if you can beat the encryption | Welcome message, line 3. |
s// Welcome message lines 1, 2 and 3
// I can ignore all these
private static void exit(final int n) {
System.out.println("");
System.out.println(I.I(364) + n); // AGZ Crackme no 5
System.out.println(I.I(380)); // There will be some fun in here
System.out.println(I.I(411)); // See if you can beat the encryption
System.out.println("");
}
// Exit message lines 1, 2, 3, 4 and 5
// The whole function can go away
private static void in() {
System.out.println("");
System.out.println(I.I(65)); // "Got the solution?"
System.out.println(I.I(83)); // "ship it off to me then.."
System.out.println(I.I(108)); // "crackme [at] agz [dot] name"
System.out.println(I.I(125)); // "https://www.agz.name"
System.out.println(I.I(146)); // "https://www.facebook.com/AGZ.name/"
}
// This is basically is_string_double() implementation
// And since I already know the correct password is a Double, I can strip the input validation entirely
private static boolean append(final String s) {
try {
Double.parseDouble(s);
return true;
} catch (Exception ex) {
return false;
}
}
// That's the user data input prompt
// I'll hardcode my username and password so this can go away too
private static String equals() {
return new Scanner(System.in).nextLine();
}
// That's printing the good or bad message, based on a Boolean argument
// I'll move that code to the main() method and remove this one
private static void length(final boolean b) {
if (b) {
System.out.println(getRuntime(I.I(181))); // "Congratz, now write me and keygen with a explanation"
} else {
System.out.println(getRuntime(I.I(254))); // "Sorry laddie, need some more debugging here..."
}
}
// This is just converting a Double to its String representation
// So, I'll just replace it around the code with Double.toString() and remove this
private static String doubleValue(final double n) {
return Double.toString(n);
}
// This is just a comparison of two Doubles converted to strings
// I can remove this code entirely, and just use Double.toString(n).equals(Double.toString(n2)) in main()
private static boolean getDecoder(final double n, final double n2) {
return doubleValue(n).equals(doubleValue(n2));
}
main(String[]), deobfuscatedpublic static final void main(final String[] array) {
final String username = "XpoZed";
final String password = "3.14";
final double password_gen = decode(availableProcessors(username));
if (Double.toString(password_gen).equals(password)) {
System.out.println("Congratz, now write me and keygen with a explanation");
} else {
System.out.println("Sorry laddie, need some more debugging here...");
}
}
availableProcessors(String)private static double availableProcessors(final String s) {
final StringBuilder sb = new StringBuilder();
final char[] charArray = s.toCharArray();
for (int length = charArray.length, i = 0; i < length; ++i) {
sb.append((int)charArray[i]);
}
return new Double(sb.toString());
}
Username char | ASCII value | Char to ASCII string | Double representation | |
---|---|---|---|---|
X | => 88 | => 8811211190101100 | => 8.8112111901011E15 | |
p | => 112 | |||
o | => 111 | |||
Z | => 90 | |||
e | => 101 | |||
d | => 100 |
decode()private static double decode(final double n) {
if (n == 0.0) {
System.out.println(getRuntime(I.I(319))); // "Sorry, you need to enter an code"
System.exit(0);
return 0.0;
}
final double n2 = Runtime.getRuntime().availableProcessors();
final double n3 = Runtime.getRuntime().totalMemory();
return n - n3 / 1.0E8 + n2 * 28.0 + n3 / 107543.0 - n3 / Double.toString(n).length();
}
So this function will slightly modify the Double we got from our username, by using system specific information like the number of CPUs and total memory available values.TheClueCreator's AGZ Crackme 5 keygen/** TheClueCreator's AGZ Crackme 5
*
* keygen solution by XpoZed / nullsecurity.org / 03 May, 2018
*
*/
package keygen;
public class main {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage example: java -cp . keygen.main USERNAME");
return;
}
String username = args[0];
// Generate the username's hash string
StringBuilder username_hash_str = new StringBuilder();
for (int i = 0; i < username.length(); i++) {
username_hash_str.append((int)username.charAt(i));
}
// Convert it to Double
double username_hash = Double.parseDouble(username_hash_str.toString());
// System specific modifier
double mod_cpu = Runtime.getRuntime().availableProcessors();
double mod_ram = Runtime.getRuntime().totalMemory();
double password = username_hash - mod_ram / 1.0E8 + mod_cpu * 28.0 +
mod_ram / 107543.0 - mod_ram / Double.toString(username_hash).length();
// Print the result
System.out.println(String.format("Username: %s\nPassword: %s", username, Double.toString(password)));
}
}
Comments
* You have an opinion? Let us all hear it!