Definitely not base 64!
The tool is java-based, so much easier to reverse engineer.
You can unpack LaunchFUW.exe with 7zip.
Navigate to com\apc\microlink\fwtool.
Open each class files with in
Recaf.
There's some interesting stuff:
DESEncrypter.classpublic class DESEncrypter
implements IEncrypter {
private static final String kENCPREFIX = "SOELM";
private static final String kENCSUFFIX = "EOELM";
private static final String kKEY = "H25s@ase";
public String doEncrypt(String plainText) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
byte[] keyBytes = kKEY.getBytes();
DESKeySpec desKeySpec = new DESKeySpec(keyBytes);
SecretKeyFactory secKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = secKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(1, key);
byte[] textBytes = plainText.getBytes();
String encryptedText = kENCPREFIX + this.byteToHexString(cipher.doFinal(textBytes)) + kENCSUFFIX;
return encryptedText;
}
private String byteToHexString(byte[] byteBlock) {
StringBuilder hexString = new StringBuilder();
int i = 0;
while (i < byteBlock.length) {
byte b = byteBlock[i];
String str = Integer.toHexString(b);
if (str.length() > 2) {
str = str.substring(str.length() - 2);
}
if (str.length() < 2) {
str = "0" + str;
}
hexString.append(str);
++i;
}
return hexString.toString().toUpperCase();
}
}
FWToolConstants.class public static final String kHashPassword = "o9aZNAPyYcxs86ysOpGUdg==";
public static final String kSecretKey = "apcschneider@2021";
UtilType.class private static int deviceID = 0;
String originalString = "apc@123";
private static SecretKeySpec secretKey;
private static byte[] key;
VerifyFileCompatibility.classSome stuff going on here, too.
VerifyFileCompatibility$FileHeader.classHere you can see the firmware file has a 128 byte header, might include a key, keep searching in other class files and you migh find out.
Also there're some details about how to parse the file:
public void parseData(byte[] data) {
this.version = data[0];
this.command = data[1];
byte[] size = new byte[4];
System.arraycopy(data, 6, size, 0, 4);
this.fileSize = this.unsignedBytesToInt(size);
byte[] id = new byte[2];
System.arraycopy(data, 12, id, 0, 2);
this.deviceID = this.unsignedTwoByteArrayToInt(id);
UtilType.setDevideId((int)this.deviceID);
FWToolApp.theLogger.debugMsg("deviceID:" + this.deviceID);
byte[] filecheck = new byte[2];
System.arraycopy(data, 16, filecheck, 0, 2);
this.fileChecksum = this.unsignedTwoByteArrayToInt(filecheck);
this.index = data[18];
this.fwversionStringSize = data[19];
this.fwversionString = this.setValueFromByteArray(data, this.fwversionStringSize, 20);
FWToolApp.theLogger.debugMsg("fw version String:" + this.fwversionString);
this.byte64 = data[64];
byte[] check = new byte[2];
System.arraycopy(data, 126, check, 0, 2);
this.headerChecksum = this.unsignedTwoByteArrayToInt(check);
byte[] xmodemstring = new byte[33];
System.arraycopy(data, 68, xmodemstring, 0, 33);
this.stringToWaitfor = this.setValueFromByteArray(xmodemstring, 33, 0);
if (this.stringToWaitfor.equals(Messages.getString((String)"VerifyFileCompatibility.45"))) {
this.stringToWaitfor = null;
}
}
Also:
calculatefilechecksum,
calculateheaderchecksum.