Added quest decrypt/encrypt and savedata decrypt.

Rewrote crypt package and updated file headers.
This commit is contained in:
codestation 2011-03-01 03:30:37 +00:00
parent 3367863918
commit 0f0d6ca0f4
24 changed files with 688 additions and 226 deletions

View file

@ -1,4 +1,4 @@
/* MHTRANS v1.0
/* MHTrans - MH Utilities
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
@ -21,7 +21,7 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
public abstract class HelperDec extends EndianFixer {
public abstract class HelperDec extends MHUtils {
/**
* The "readUTF8" function of java expects a different format of the
* string so i have to make a custom one

View file

@ -1,4 +1,4 @@
/* MHTRANS v1.0
/* MHTrans - MH Utilities
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
@ -21,7 +21,7 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
public abstract class HelperEnc extends EndianFixer {
public abstract class HelperEnc extends MHUtils {
protected String readString(RandomAccessFile file) throws IOException {
byte[] buffer = new byte[1024];
byte data = 0;

View file

@ -1,4 +1,4 @@
/* MHTRANS v1.0
/* MHTrans - MH Utilities
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
@ -18,14 +18,15 @@
package base;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public abstract class EndianFixer {
public abstract class MHUtils {
protected int readInt(InputStream file) throws IOException, EOFException {
public static int readInt(InputStream file) throws IOException, EOFException {
int ch1 = file.read();
int ch2 = file.read();
int ch3 = file.read();
@ -36,7 +37,7 @@ public abstract class EndianFixer {
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
}
protected int readInt(RandomAccessFile file) throws IOException, EOFException {
public static int readInt(RandomAccessFile file) throws IOException, EOFException {
int ch1 = file.read();
int ch2 = file.read();
int ch3 = file.read();
@ -47,7 +48,7 @@ public abstract class EndianFixer {
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
}
protected int readShort(InputStream file) throws IOException, EOFException {
public static int readShort(InputStream file) throws IOException, EOFException {
int ch1 = file.read();
int ch2 = file.read();
if ((ch1 | ch2) < 0) {
@ -56,7 +57,7 @@ public abstract class EndianFixer {
return (ch2 << 8) + (ch1 << 0);
}
protected void writeShort(OutputStream file, int value) throws IOException {
public static void writeShort(OutputStream file, int value) throws IOException {
int ch1 = (byte) (value >>> 8);
int ch2 = (byte) value;
file.write(ch2);
@ -71,7 +72,7 @@ public abstract class EndianFixer {
* @throws IOException
* if any error occur while writing
*/
protected void writeInt(OutputStream file, int value) throws IOException {
public static void writeInt(OutputStream file, int value) throws IOException {
int ch1 = (byte) (value >>> 24);
int ch2 = (byte) (value >>> 16);
int ch3 = (byte) (value >>> 8);
@ -82,7 +83,7 @@ public abstract class EndianFixer {
file.write(ch1);
}
protected void writeInt(RandomAccessFile file, int value) throws IOException {
public static void writeInt(RandomAccessFile file, int value) throws IOException {
int ch1 = (byte) (value >>> 24);
int ch2 = (byte) (value >>> 16);
int ch3 = (byte) (value >>> 8);
@ -92,4 +93,24 @@ public abstract class EndianFixer {
file.write(ch2);
file.write(ch1);
}
public static int extractNumber(String filename) {
return Integer.parseInt(filename.substring(filename.indexOf(".") - 4,
filename.indexOf(".")));
}
public static int getOffset(int value) throws EOFException,
FileNotFoundException, IOException {
int res = -1;
if (value == 0) {
res = 0;
} else {
RandomAccessFile table = new RandomAccessFile("index.bin", "r");
table.seek(value * 4 - 4);
res = readInt(table);
table.close();
}
return res;
}
}

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MHP2G xxxx.bin language table extractor/rebuilder/encrypter/decrypter
Copyright (C) 2008 Codestation
/* MHTrans - MH Utilities
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -25,6 +25,8 @@ import java.io.IOException;
import crypt.Decrypter;
import crypt.Encrypter;
import crypt.QuestCypher;
import crypt.SavedataCypher;
import dec.ExtractPluginA;
import dec.ExtractPluginB;
import dec.ExtractPluginC;
@ -123,6 +125,11 @@ public class Mhtrans {
System.err.println(" java -jar mhtrans.jar --gen-index <data.bin>");
System.err.println(" java -jar mhtrans.jar --dec-all <data.bin> <path to output folder>");
System.err.println(" java -jar mhtrans.jar --create-patch <xxxx.bin.enc> [ ... <xxxx.bin.enc>] <output_file>");
System.err.println(" java -jar mhtrans.jar --decrypt-quest <mxxxxx.mib>");
System.err.println(" java -jar mhtrans.jar --encrypt-quest <mxxxxx.mib>");
//System.err.println(" java -jar mhtrans.jar --update-sha1 <mxxxxx.mib>");
System.err.println(" java -jar mhtrans.jar --decrypt-save <xxxxx.bin>");
//System.err.println(" java -jar mhtrans.jar --encrypt-save <xxxxx.bin>");
System.exit(1);
} else {
if (args[0].equals("--extract")) {
@ -174,6 +181,16 @@ public class Mhtrans {
new Decrypter().decrypt_whole(args[1], args[2]);
} else if(args[0].equals("--create-patch")) {
new PatchBuilder().create(args);
} else if(args[0].equals("--encrypt-quest")) {
new QuestCypher().encrypt(args[1]);
} else if(args[0].equals("--decrypt-quest")) {
new QuestCypher().decrypt(args[1]);
//} else if(args[0].equals("--update-sha1")) {
// new QuestCypher().update_sha1(args[1]);
//} else if(args[0].equals("--encrypt-save")) {
// new SavedataCypher().encrypt(args[1]);
} else if(args[0].equals("--decrypt-save")) {
new SavedataCypher().decrypt(args[1]);
} else {
System.err.println("Unknown parameter: " + args[0]);
System.exit(1);

View file

@ -1,3 +1,20 @@
/* MHTrans - MH Utilities
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package base;
import java.io.BufferedReader;
@ -15,9 +32,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Vector;
import crypt.DecryptTable;
public class PatchBuilder extends DecryptTable {
public class PatchBuilder{// extends DecryptTable {
public void create(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList(args));
list.remove(0);
@ -34,13 +49,13 @@ public class PatchBuilder extends DecryptTable {
out.setLength(table_size);
out.seek(0);
long current = 0;
writeInt(out, list.size());
MHUtils.writeInt(out, list.size());
for (String file : list) {
int offset = getOffset(extractNumber(file)) << 11;
writeInt(out, offset);
int offset = MHUtils.getOffset(MHUtils.extractNumber(file)) << 11;
MHUtils.writeInt(out, offset);
InputStream in = new FileInputStream(file);
int len = (int)new File(file).length();
writeInt(out, (int)len);
MHUtils.writeInt(out, (int)len);
System.out.println(file + ", offset: " + offset + ", size: " + len);
current = out.getFilePointer();
byte buffer[] = new byte[1024];
@ -50,7 +65,7 @@ public class PatchBuilder extends DecryptTable {
in.close();
out.seek(current);
}
writeInt(out, 0);
MHUtils.writeInt(out, 0);
install_tables(out, list);
out.close();
}catch(FileNotFoundException e) {
@ -83,21 +98,21 @@ public class PatchBuilder extends DecryptTable {
}
Vector<String> install_uniq = new Vector<String>(new LinkedHashSet<String>(install_files));
while(install_uniq.remove("NONE"));
writeInt(out, install_uniq.size());
MHUtils.writeInt(out, install_uniq.size());
int install_count = 0;
String match = install_files.firstElement();
out.write(match.getBytes());
writeInt(out, install_count);
MHUtils.writeInt(out, install_count);
for(String file : install_files) {
if(!file.equals("NONE") && !match.equals(file)) {
out.write(file.getBytes());
match = file;
writeInt(out, install_count);
MHUtils.writeInt(out, install_count);
}
install_count++;
}
for(String trans_file : list) {
int index = patch_files.indexOf(extractNumber(trans_file));
int index = patch_files.indexOf(MHUtils.extractNumber(trans_file));
int offset = -1;
if(index != -1) {
// UGH!!, 11 years and the Integer.parseInt bug isn't fixed
@ -107,7 +122,7 @@ public class PatchBuilder extends DecryptTable {
} else {
System.out.println("Install info not found for " + trans_file);
}
writeInt(out, offset);
MHUtils.writeInt(out, offset);
}
long filelength = out.length();
if(filelength % 16 > 0) {
@ -121,24 +136,4 @@ public class PatchBuilder extends DecryptTable {
e.printStackTrace();
}
}
/**
* The "writeInt" function of java writes in BigEndian mode but we need
* LittleEndian so i made a custom function for that
*
* @param file
* @throws IOException
* if any error occur while writing
*/
private void writeInt(RandomAccessFile file, int value)
throws IOException {
int ch1 = (byte) (value >>> 24);
int ch2 = (byte) (value >>> 16);
int ch3 = (byte) (value >>> 8);
int ch4 = (byte) value;
file.write(ch4);
file.write(ch3);
file.write(ch2);
file.write(ch1);
}
}

View file

@ -0,0 +1,90 @@
/* MHTrans - MH decrypter utilities
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package crypt;
public abstract class DecryptUtils {
protected byte decrypt_table[];
private long lower_offset;
private long upper_offset;
private long seed_key_a;
private long seed_key_b;
private long mod_a;
private long mod_b;
abstract protected byte[] getDecryptTable();
abstract protected long getSeedKeyA();
abstract protected long getSeedKeyB();
abstract protected long getModA();
abstract protected long getModB();
public DecryptUtils() {
decrypt_table = getDecryptTable();
seed_key_a = getSeedKeyA();
seed_key_b = getSeedKeyB();
mod_a = getModA();
mod_b = getModB();
}
protected void initSeed(long seed) {
lower_offset = seed & 0xFFFF;
upper_offset = seed >> 0x10 & 0xFFFF;
if (lower_offset == 0) {
lower_offset = seed_key_a;
}
if (upper_offset == 0) {
upper_offset = seed_key_b;
}
}
protected long getBeta() {
lower_offset = (lower_offset * seed_key_a) % mod_a;
upper_offset = (upper_offset * seed_key_b) % mod_b;
return lower_offset + (upper_offset << 0x10);
}
protected void set_table_value(byte table[], int pos, long value) {
table[pos] = (byte) value;
table[pos + 1] = (byte) (value >> 8);
table[pos + 2] = (byte) (value >> 16);
table[pos + 3] = (byte) (value >> 24);
}
protected long get_table_value(byte table[], int pos) {
return (table[pos] & 0xFF) + ((long) (table[pos + 1] & 0xFF) << 8)
+ ((long) (table[pos + 2] & 0xFF) << 16)
+ ((long) (table[pos + 3] & 0xFF) << 24);
}
protected void get_table_value(byte table[], byte buffer[]) {
buffer[0] = table[buffer[0] & 0xFF];
buffer[1] = table[buffer[1] & 0xFF];
buffer[2] = table[buffer[2] & 0xFF];
buffer[3] = table[buffer[3] & 0xFF];
}
protected void set_table_data(byte table[], int i) {
table[i] = decrypt_table[table[i] & 0xFF];
table[i + 1] = decrypt_table[table[i + 1] & 0xFF];
table[i + 2] = decrypt_table[table[i + 2] & 0xFF];
table[i + 3] = decrypt_table[table[i + 3] & 0xFF];
}
}

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MH data.bin/xxxx.bin decrypter
Copyright (C) 2008 Codestation
/* MHTrans - MH data.bin/xxxx.bin decrypter
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -23,7 +23,12 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Decrypter extends DecryptTable {
import keys.DataKeys;
import base.MHUtils;
public class Decrypter extends DecryptUtils implements DataKeys {
private byte png[] = {(byte) 0x89, 0x50, 0x4e, 0x47};
private byte gif[] = {0x47, 0x49, 0x46, 0x38};
private byte tmh[] = {0x2e, 0x54, 0x4d, 0x48};
@ -33,6 +38,31 @@ public class Decrypter extends DecryptTable {
private byte dbst[] = {0x64, 0x62, 0x73, 0x54};
private byte wav[] = {0x52, 0x49, 0x46, 0x46};
@Override
protected byte[] getDecryptTable() {
return decrypter_table;
}
@Override
protected long getSeedKeyA() {
return 0x7F8D;
}
@Override
protected long getSeedKeyB() {
return 0x2345;
}
@Override
protected long getModA() {
return 0xFFF1;
}
@Override
protected long getModB() {
return 0xFFD9;
}
public void decrypt_index(String in, ByteArrayOutputStream index_buffer) {
try {
RandomAccessFile filein = new RandomAccessFile(in, "r");
@ -46,10 +76,7 @@ public class Decrypter extends DecryptTable {
int i = 0;
while (!table_end) {
filein.read(buffer);
buffer[0] = decrypt_table[buffer[0] & 0xFF];
buffer[1] = decrypt_table[buffer[1] & 0xFF];
buffer[2] = decrypt_table[buffer[2] & 0xFF];
buffer[3] = decrypt_table[buffer[3] & 0xFF];
get_table_value(decrypt_table, buffer);
long beta = getBeta();
long alpha = get_table_value(buffer, 0);
long gamma = alpha ^ beta;
@ -172,10 +199,7 @@ public class Decrypter extends DecryptTable {
int read = filein.read(buffer);
size -= read;
for (int i = 0; i < read; i += 4) {
buffer[i] = decrypt_table[buffer[i] & 0xFF];
buffer[i + 1] = decrypt_table[buffer[i + 1] & 0xFF];
buffer[i + 2] = decrypt_table[buffer[i + 2] & 0xFF];
buffer[i + 3] = decrypt_table[buffer[i + 3] & 0xFF];
set_table_data(buffer, i);
long alpha = get_table_value(buffer, i);
long beta = getBeta();
long gamma = alpha ^ beta;
@ -209,7 +233,7 @@ public class Decrypter extends DecryptTable {
try {
filein = new RandomAccessFile(in, "r");
System.out.print("Decrypting " + out + " ... ");
decrypt_internal(filein, getOffset(extractNumber(in)),
decrypt_internal(filein, MHUtils.getOffset(MHUtils.extractNumber(in)),
filein.length(), out, true);
} catch (FileNotFoundException e) {

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MHP2G data.bin/xxxx.bin encrypter
Copyright (C) 2008 Codestation
/* MHTrans - MH data.bin/xxxx.bin decrypter
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -21,10 +21,39 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Encrypter extends DecryptTable {
import keys.DataKeys;
import base.MHUtils;
public class Encrypter extends DecryptUtils implements DataKeys {
private byte[] encrypt_table;
@Override
protected byte[] getDecryptTable() {
return decrypter_table;
}
@Override
protected long getSeedKeyA() {
return 0x7F8D;
}
@Override
protected long getSeedKeyB() {
return 0x2345;
}
@Override
protected long getModA() {
return 0xFFF1;
}
@Override
protected long getModB() {
return 0xFFD9;
}
public Encrypter() {
encrypt_table = new byte[256];
for (int i = 0; i < 256; i++) {
@ -36,9 +65,9 @@ public class Encrypter extends DecryptTable {
try {
RandomAccessFile filein = new RandomAccessFile(in, "r");
RandomAccessFile fileout = new RandomAccessFile(out, "rw");
int file_number = extractNumber(in);
int file_number = MHUtils.extractNumber(in);
long file_len = filein.length();
long table_len = (getOffset(file_number + 1) << 11) - (getOffset(file_number) << 11);
long table_len = (MHUtils.getOffset(file_number + 1) << 11) - (MHUtils.getOffset(file_number) << 11);
if(file_len < table_len) {
System.out.println(in + " filesize is less than the stored table by " +
(table_len - file_len) + " bytes, fill the file with 0x00 at the end");
@ -48,7 +77,7 @@ public class Encrypter extends DecryptTable {
(file_len - table_len) + " bytes, aborting");
System.exit(1);
}
initSeed(getOffset(file_number));
initSeed(MHUtils.getOffset(file_number));
byte[] buffer = new byte[4];
System.out.println("Encrypting " + in);
while (filein.read(buffer) >= 0) {
@ -56,10 +85,7 @@ public class Encrypter extends DecryptTable {
long beta = getBeta();
long alpha = beta ^ gamma;
set_table_value(buffer, 0, alpha);
buffer[0] = encrypt_table[buffer[0] & 0xFF];
buffer[1] = encrypt_table[buffer[1] & 0xFF];
buffer[2] = encrypt_table[buffer[2] & 0xFF];
buffer[3] = encrypt_table[buffer[3] & 0xFF];
get_table_value(encrypt_table, buffer);
fileout.write(buffer);
}
filein.close();

150
src/crypt/QuestCypher.java Normal file
View file

@ -0,0 +1,150 @@
/* MHTrans - MH quest decrypter/encrypter
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package crypt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import keys.QuestKeys;
public class QuestCypher implements QuestKeys {
private short key_var_table[] = {0, 0, 0, 0};
public boolean decrypt(String filein) {
try {
File fd = new File(filein);
FileInputStream in = new FileInputStream(fd);
byte byte_bt[] = new byte[(int)fd.length()];
in.read(byte_bt);
in.close();
ByteBuffer bt = ByteBuffer.wrap(byte_bt);
bt.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer sb = bt.asShortBuffer();
short short_bt[] = new short[byte_bt.length/2];
sb.get(short_bt);
decrypt_quest(short_bt);
sb.rewind();
sb.put(short_bt);
FileOutputStream out = new FileOutputStream(filein + ".dec");
out.write(byte_bt);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public boolean encrypt(String filein) {
try {
File fd = new File(filein);
FileInputStream in = new FileInputStream(fd);
byte byte_bt[] = new byte[(int)fd.length()];
in.read(byte_bt);
in.close();
update_sha1(byte_bt);
ByteBuffer bt = ByteBuffer.wrap(byte_bt);
bt.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer sb = bt.asShortBuffer();
short short_bt[] = new short[byte_bt.length/2];
sb.get(short_bt);
encrypt_quest(short_bt);
sb.rewind();
sb.put(short_bt);
FileOutputStream out = new FileOutputStream(filein + ".enc");
out.write(byte_bt);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
private void decrypt_quest(short pData[]) {
calc_key(key_var_table, pData);
for(int i = 8; i < pData.length*2; i += 2) {
int index = (i >> 1);
int key = get_xor_key(key_var_table, index & 0x03);
pData[index] ^= (short)(key & 0xFFFF);
}
}
private void encrypt_quest(short pData[]) {
decrypt_quest(pData);
}
private void calc_key(short pTable[], short pData[]) {
for(int i = 0; i < 4; i++) {
pTable[i] = pData[i];
if (pTable[i] == 0){
pTable[i] = (short)(seed_0[i] & 0xFFFF);
}
}
}
int i = 0;
private int get_xor_key(short pTable[], int pos) {
int key = (int) ((long)(pTable[pos] & 0xFFFF) * (long)(seed_0[pos] & 0xFFFF) % (seed_1[pos] & 0xFFFF));
pTable[pos] = (short)(key & 0xFFFF);
return key;
}
public void update_sha1(String file) {
try {
RandomAccessFile fd = new RandomAccessFile(file, "rw");
byte byte_bt[] = new byte[(int)fd.length()];
fd.read(byte_bt);
fd.seek(0);
update_sha1(byte_bt);
fd.write(byte_bt);
fd.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void update_sha1(byte buf[]) {
int len = ((buf[8+3] << 24) & 0xFFFFFFFF) + ((buf[8+2] << 16) & 0xFFFFFF) + ((buf[8+1] << 8) & 0xFFFF) + ((buf[8+0] << 0) & 0xFF);
len += 0x10;
byte buffer[] = new byte[len];
System.arraycopy(buf, 0x20, buffer, 0, len-0x10);
System.arraycopy(quest_sha1_key.getBytes(), 0, buffer, len-0x10, 0x10);
try {
MessageDigest md = MessageDigest.getInstance("sha-1");
byte digest[] = md.digest(buffer);
System.arraycopy(digest, 0, buf, 12, 0x10);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,87 @@
/* MHTrans - MH savedata decrypter/encrypter
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package crypt;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import keys.SavedataKeys;
public class SavedataCypher extends DecryptUtils implements SavedataKeys {
@Override
protected byte[] getDecryptTable() {
return decrypter_table;
}
@Override
protected long getSeedKeyA() {
return seed_a;
}
@Override
protected long getSeedKeyB() {
return seed_b;
}
@Override
protected long getModA() {
return mod_a;
}
@Override
protected long getModB() {
return mod_b;
}
public boolean decrypt(String file) {
try {
RandomAccessFile fd = new RandomAccessFile(file, "rw");
byte byte_bt[] = new byte[(int)fd.length()];
fd.read(byte_bt);
fd.seek(0);
decrypt_buffer(byte_bt);
fd.write(byte_bt);
fd.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
private void decrypt_buffer(byte buffer[]) {
int len = buffer.length - 4;
byte seed[] = new byte[4];
System.arraycopy(buffer, len, seed, 0, 4);
get_table_value(decrypt_table, seed);
get_table_value(decrypt_table, seed);
long alpha = get_table_value(seed, 0);
initSeed(alpha);
for (int i = 0; i < len; i += 4) {
set_table_data(buffer, i);
alpha = get_table_value(buffer, i);
long beta = getBeta();
long gamma = alpha ^ beta;
set_table_value(buffer, i, gamma);
set_table_data(buffer, i);
}
}
}

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MHP2G 0016/0017/475x.bin language table extractor
Copyright (C) 2008-2010 Codestation
/* MHTrans - MHP2G 0016/0017/475x.bin language table extractor
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MHP2G 53xx.bin language table extractor
Copyright (C) 2008 Codestation
/* MHTrans - MHP2G 53xx.bin language table extractor
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MHP2G 537x.bin language table extractor
Copyright (C) 2008 Codestation
/* MHTrans - MHP2G 537x.bin language table extractor
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,4 +1,4 @@
/* MHP2GDEC v1.0 - MH TMH image extractor
/* MHTrans - MH TMH image extractor
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
@ -30,14 +30,14 @@ import javax.imageio.ImageIO;
import base.Decoder;
import base.EndianFixer;
import base.MHUtils;
/**
* ExtractPluginD v1.0
*
* @author Codestation
*/
public class ExtractPluginD extends EndianFixer implements Decoder {
public class ExtractPluginD extends MHUtils implements Decoder {
@Override
public void extract(String filename) {

View file

@ -1,4 +1,4 @@
/* MHP2GDEC v1.0 - MH TMH image extractor
/* MHTrans - MH TMH image extractor
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
@ -24,7 +24,7 @@ import java.io.IOException;
import java.io.RandomAccessFile;
import base.Decoder;
import base.EndianFixer;
import base.MHUtils;
/**
@ -32,7 +32,7 @@ import base.EndianFixer;
*
* @author Codestation
*/
public class ExtractPluginE extends EndianFixer implements Decoder {
public class ExtractPluginE extends MHUtils implements Decoder {
byte pmo[] = {0x70, 0x6d, 0x6f, 0x00};
byte tmh[] = {0x2E, 0x54, 0x4D, 0x48};

View file

@ -1,5 +1,5 @@
/* MHP2GENC v1.0 - MHP 0016/475x/0017.bin language table rebuilder
Copyright (C) 2008-2010 codestation
/* MHTrans - MHP 0016/475x/0017.bin language table rebuilder
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
/* MHP2GENC v1.0 - MHP2G 53xx.bin language table rebuilder
Copyright (C) 2008 Codestation
/* MHTrans - MHP2G 53xx.bin language table rebuilder
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
/* MHP2GENC v1.0 - MHP2G 537x.bin language table rebuilder
Copyright (C) 2008 Codestation
/* MHTrans - MHP2G 537x.bin language table rebuilder
Copyright (C) 2008-2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
/* MHP2GENC v1.0 - TMH image rebuilder
Copyright (C) 2008-2010 codestation
/* MHTrans - TMH image rebuilder
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -33,14 +33,14 @@ import javax.imageio.ImageIO;
import base.Encoder;
import base.EndianFixer;
import base.MHUtils;
/**
* RebuildPluginD v1.0
*
* @author Codestation
*/
public class RebuildPluginD extends EndianFixer implements Encoder {
public class RebuildPluginD extends MHUtils implements Encoder {
private byte id[] = {0x2e, 0x54, 0x4d, 0x48, 0x30, 0x2e, 0x31, 0x34};

View file

@ -1,5 +1,5 @@
/* MHP2GENC v1.0 - PAK rebuilder
Copyright (C) 2008-2010 codestation
/* MHTrans - PAK rebuilder
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,14 +28,14 @@ import java.util.Comparator;
import java.util.Vector;
import base.Encoder;
import base.EndianFixer;
import base.MHUtils;
/**
* RebuildPluginE v1.0
*
* @author Codestation
*/
public class RebuildPluginE extends EndianFixer implements Encoder {
public class RebuildPluginE extends MHUtils implements Encoder {
@Override
public void compile(String filepath) {

View file

@ -1,3 +1,20 @@
/* MHTrans - GIM image creator
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package img;
import java.io.EOFException;
@ -5,9 +22,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import base.EndianFixer;
import base.MHUtils;
public class Gim extends EndianFixer {
public class Gim extends MHUtils {
public static final int RGBA8888 = 3;
public static final int RGBA5551 = 1;

View file

@ -1,5 +1,5 @@
/* MHP2GDEC v1.0 - MH data.bin/xxxx.bin encrypter/decrypter
Copyright (C) 2008 codestation
/* MHTrans - MHP3 data keys
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -15,17 +15,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package crypt;
package keys;
//import java.io.EOFException;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public abstract class DecryptTable {
protected final byte decrypt_table[] = { (byte) 0xCB, (byte) 0x96,
public interface DataKeys {
final byte decrypter_table[] = { (byte) 0xCB, (byte) 0x96,
(byte) 0x85, (byte) 0xA6, (byte) 0x5F, (byte) 0x3E, (byte) 0xAB,
(byte) 0x03, (byte) 0x50, (byte) 0xB7, (byte) 0x9C, (byte) 0x5C,
(byte) 0xB2, (byte) 0x40, (byte) 0xEF, (byte) 0xF6, (byte) 0xFF,
@ -78,70 +71,9 @@ public abstract class DecryptTable {
(byte) 0x60, (byte) 0xEE, (byte) 0x98, (byte) 0x6B, (byte) 0x0D,
(byte) 0x99, (byte) 0xEA, (byte) 0xC5, (byte) 0xAC };
private long lower_offset;
private long upper_offset;
final long seed_a = 0x7F8D;
final long seed_b = 0x2345;
final long mod_a = 0xFFF1;
final long mod_b = 0xFFD9;
protected void initSeed(long seed) {
lower_offset = seed & 0xFFFF;
upper_offset = seed >> 0x10 & 0xFFFF;
if (lower_offset == 0) {
lower_offset = 0x7F8D;
}
if (upper_offset == 0) {
upper_offset = 0x2345;
}
}
protected long getBeta() {
lower_offset = (lower_offset * 0x7F8D) % 0xFFF1;
upper_offset = (upper_offset * 0x2345) % 0xFFD9;
return lower_offset + (upper_offset << 0x10);
}
protected void set_table_value(byte table[], int pos, long value) {
table[pos] = (byte) value;
table[pos + 1] = (byte) (value >> 8);
table[pos + 2] = (byte) (value >> 16);
table[pos + 3] = (byte) (value >> 24);
}
protected long get_table_value(byte table[], int pos) {
return (table[pos] & 0xFF) + ((long) (table[pos + 1] & 0xFF) << 8)
+ ((long) (table[pos + 2] & 0xFF) << 16)
+ ((long) (table[pos + 3] & 0xFF) << 24);
}
/*
* Can't use the RandomAccessFile readInt func as we need the bytes in
* reverse order
*/
private int readInt(RandomAccessFile file) throws IOException, EOFException {
int ch1 = file.read();
int ch2 = file.read();
int ch3 = file.read();
int ch4 = file.read();
if ((ch1 | ch2 | ch3 | ch4) < 0) {
throw new EOFException();
}
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
}
protected int getOffset(int value) throws EOFException,
FileNotFoundException, IOException {
int res = -1;
if (value == 0) {
res = 0;
} else {
RandomAccessFile table = new RandomAccessFile("index.bin", "r");
table.seek(value * 4 - 4);
res = readInt(table);
table.close();
}
return res;
}
protected int extractNumber(String filename) {
return Integer.parseInt(filename.substring(filename.indexOf(".") - 4,
filename.indexOf(".")));
}
}

25
src/keys/QuestKeys.java Normal file
View file

@ -0,0 +1,25 @@
/* MHTrans - MHP3 quest keys
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package keys;
public interface QuestKeys {
final int seed_0[] = {0x3DF3, 0x1709, 0xB381, 0x747B};
final int seed_1[] = {0xFFA9, 0xFF9D, 0xFFF1, 0xFFC7};
final String quest_sha1_key = "sR2Tf4eLAj8b3TH7";
}

View file

@ -0,0 +1,78 @@
/* MHTrans - MHP3 savedata keys
Copyright (C) 2011 Codestation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package keys;
public interface SavedataKeys {
final byte decrypter_table[] = { (byte) 0xA6, (byte) 0x21,
(byte) 0x22, (byte) 0xF9, (byte) 0x3D, (byte) 0xFB, (byte) 0xF5,
(byte) 0x06, (byte) 0x87, (byte) 0x54, (byte) 0x76, (byte) 0x75,
(byte) 0xED, (byte) 0x16, (byte) 0x33, (byte) 0x2E, (byte) 0x5A,
(byte) 0x17, (byte) 0x50, (byte) 0x1C, (byte) 0xDE, (byte) 0xAF,
(byte) 0x73, (byte) 0x39, (byte) 0xB5, (byte) 0x28, (byte) 0xD9,
(byte) 0xF1, (byte) 0xCD, (byte) 0x98, (byte) 0x5F, (byte) 0x2D,
(byte) 0x78, (byte) 0x62, (byte) 0x29, (byte) 0xC9, (byte) 0xFD,
(byte) 0xEA, (byte) 0x32, (byte) 0xCC, (byte) 0x31, (byte) 0x70,
(byte) 0x34, (byte) 0x61, (byte) 0xAE, (byte) 0x4D, (byte) 0xFE,
(byte) 0xC2, (byte) 0x45, (byte) 0x24, (byte) 0xF8, (byte) 0xFC,
(byte) 0xD7, (byte) 0x2F, (byte) 0xD8, (byte) 0x26, (byte) 0x59,
(byte) 0xA0, (byte) 0xBD, (byte) 0xA5, (byte) 0x01, (byte) 0x18,
(byte) 0xA1, (byte) 0x95, (byte) 0xEE, (byte) 0x4B, (byte) 0x1A,
(byte) 0x7A, (byte) 0x5B, (byte) 0xDB, (byte) 0xF0, (byte) 0x27,
(byte) 0xE6, (byte) 0xF4, (byte) 0xB2, (byte) 0xAD, (byte) 0x4A,
(byte) 0x14, (byte) 0x9A, (byte) 0x20, (byte) 0xB9, (byte) 0x36,
(byte) 0x4F, (byte) 0x3B, (byte) 0xCA, (byte) 0xE4, (byte) 0x41,
(byte) 0x85, (byte) 0x3A, (byte) 0x46, (byte) 0x5C, (byte) 0xCB,
(byte) 0x3C, (byte) 0xEC, (byte) 0x63, (byte) 0x84, (byte) 0x66,
(byte) 0xC4, (byte) 0xEB, (byte) 0x25, (byte) 0xAA, (byte) 0x7E,
(byte) 0xC3, (byte) 0x47, (byte) 0x9B, (byte) 0x74, (byte) 0x8B,
(byte) 0x5D, (byte) 0x23, (byte) 0x8F, (byte) 0x72, (byte) 0x81,
(byte) 0x8C, (byte) 0x56, (byte) 0xC6, (byte) 0xD4, (byte) 0x40,
(byte) 0x60, (byte) 0xA2, (byte) 0x6D, (byte) 0xE5, (byte) 0xB0,
(byte) 0x15, (byte) 0x58, (byte) 0x52, (byte) 0x0F, (byte) 0x7D,
(byte) 0x67, (byte) 0xEF, (byte) 0xD2, (byte) 0x0B, (byte) 0xCF,
(byte) 0x0D, (byte) 0xD6, (byte) 0x2B, (byte) 0x0A, (byte) 0x9F,
(byte) 0x80, (byte) 0x5E, (byte) 0x3F, (byte) 0x71, (byte) 0x68,
(byte) 0x05, (byte) 0x86, (byte) 0xBB, (byte) 0x38, (byte) 0xCE,
(byte) 0x7F, (byte) 0xF3, (byte) 0x83, (byte) 0x03, (byte) 0x48,
(byte) 0xD3, (byte) 0xFA, (byte) 0x35, (byte) 0xDF, (byte) 0x44,
(byte) 0x7C, (byte) 0x82, (byte) 0x93, (byte) 0x53, (byte) 0xA3,
(byte) 0x09, (byte) 0x6A, (byte) 0x77, (byte) 0x13, (byte) 0x55,
(byte) 0xDD, (byte) 0xBE, (byte) 0x00, (byte) 0x9C, (byte) 0xB4,
(byte) 0xE3, (byte) 0x9E, (byte) 0xBC, (byte) 0x96, (byte) 0xA7,
(byte) 0xE2, (byte) 0x42, (byte) 0x4E, (byte) 0x37, (byte) 0x0E,
(byte) 0xF6, (byte) 0x9D, (byte) 0x1B, (byte) 0x2A, (byte) 0x79,
(byte) 0xBF, (byte) 0xDC, (byte) 0xA9, (byte) 0x88, (byte) 0x4C,
(byte) 0xD0, (byte) 0xAB, (byte) 0xC5, (byte) 0x69, (byte) 0xD1,
(byte) 0xE1, (byte) 0xAC, (byte) 0xE9, (byte) 0xC1, (byte) 0xB6,
(byte) 0x7B, (byte) 0x57, (byte) 0x90, (byte) 0x07, (byte) 0x30,
(byte) 0x92, (byte) 0xB7, (byte) 0x1E, (byte) 0xDA, (byte) 0x49,
(byte) 0x0C, (byte) 0xB8, (byte) 0xA4, (byte) 0xFF, (byte) 0xB3,
(byte) 0xF2, (byte) 0x64, (byte) 0x8A, (byte) 0xC7, (byte) 0x02,
(byte) 0x6C, (byte) 0x08, (byte) 0x6F, (byte) 0xF7, (byte) 0x89,
(byte) 0xC0, (byte) 0x10, (byte) 0xA8, (byte) 0x8D, (byte) 0xBA,
(byte) 0x91, (byte) 0x43, (byte) 0x6B, (byte) 0x3E, (byte) 0xD5,
(byte) 0x65, (byte) 0xE0, (byte) 0x6E, (byte) 0x12, (byte) 0x2C,
(byte) 0x94, (byte) 0x99, (byte) 0xE8, (byte) 0x1F, (byte) 0xC8,
(byte) 0x11, (byte) 0x8E, (byte) 0xB1, (byte) 0xE7, (byte) 0x51,
(byte) 0x1D, (byte) 0x97, (byte) 0x04, (byte) 0x19 };
final long seed_a = 0x215F;
final long seed_b = 0xDFA3;
final long mod_a = 0xFF8F;
final long mod_b = 0xFFEF;
}