JAVAでファイルを読み込み変換する

Go down

JAVAでファイルを読み込み変換する

投稿 by 構築さん on 2014-06-03, 17:04

気付いた人もいるかも知れませんが、これはJMSのパケットです。

JAVAでデコードするプログラムを作ってみましたが、20パケット位でプログラムが大きすぎる(64KB以上!?)との警告が出てコンパイルが出来なくなるので、ファイル読み込みに変更したいと思いここで質問しましたが、もう時間に余裕が無くなったのであきらめます。

わかったパケットの範囲ではいい所まで動いた感じなのですが…

思ったのは、JMSのリパックが無かったためなのか、通信の暗号化やクライアントの解析対策があまいのかも。^^;


JMS185の場合:











1キャラクタ目はダミーです。実際にキャラクタ登録を行うと止まってしまいます。^^

以下※

下の内容が書かれたファイルを読み込んで、byte[] を返すプログラムを考えてもらえないでしょうか。

byte[0] = Mode: 8(I: の場合), 2(S: の場合), 4(R: の場合)
byte[1] = 0x00 (固定)
byte[2:3]= バイト数(byte[2]が下位バイト,byte[3]が上位バイト,俗に言うリトルエンディアンです)
byte[4~]= 読み込んだバイトDATA
※(空白行)が現れたらreturnする。
※何行目まで読み込んだのかは自分で覚えておく

自分はファイルの扱いに慣れていないので、お願いします。

Code:
/* Frame (69 bytes) */
I:
byte pkt240[] = {
0x0d, 0x00, /* BH#..... */
0x91, 0x00, 0x00, 0x00, 0xe9, 0x74, 0xbe, 0x6b, /* .....t.k */
0x83, 0x12, 0x21, 0x59, 0x03 /* ..!Y. */
};

/* Frame (60 bytes) */
S:
byte pkt260[] = {
0x4f, 0xa6, /* BH....O. */
0x4d, 0xa6, 0xf0, 0x50 /* M..P */
};

/* Frame (60 bytes) */
R:
byte pkt261[] = {
0x2f, 0x6b, /* ..v.../k */
0x2d, 0x6b, 0x53, 0xd7 /* -kS. */
};

このファイルは、

Code:
"/* Frame (**** bytes) */"
"I:" or "S:" or "R:"
"byte pkt****[] = {"
"(バイトdata群) /* .... */"
"};"
"(空白行)"

を繰り返します。

何となく動いたとしか言えませんが載せておきます。(勝手に仕様を変更しています)
import しているものは、XeonMSが参考になるかと思います。

Code:
package aes;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import mina.MaplePacketDecoder;
import mina.MaplePacketEncoder;
import tools.MapleAESOFB;
import tools.HexTool;

public class AES {
public final static boolean JMS = true;

final static int HEADLEN = 54;
final static int MAXLEN = 1414; // at GMS or JMS V145,V185
//final static int MAXLEN = 1360; // at JMS V306,V307

public static void main(String[] args) {
final byte key[] = {(byte)0x13, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x00, (byte)0x00, (byte)0x00, (byte) (byte)0xB4, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1B, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0F, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x33, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x52, (byte)0x00, (byte)0x00, (byte)0x00};
final byte dummy[] = {0x0d,0x00, 0x7f,0x00, 0x00,0x00, 0,0,0,0, 0,0,0,0, 3};


// Crypt定義
MapleAESOFB sendCipher = InitDecode(key, dummy, true);
MapleAESOFB recvCipher = InitDecode(key, dummy, false);

int length = 0;
int pos = 0;
boolean decFlag = false;
boolean convFlag = false;
boolean decStop = false;
byte[] tmp = new byte[199999];
//byte[] line = new byte[1468];
byte[] line = new byte[99999]; // 1468bytes 以上のパケットが存在する

try {
FileReader fr = new FileReader("in_185.txt");
BufferedReader abc = new BufferedReader(fr);
FileWriter fw = new FileWriter("out_185.txt");

String s1 = "/* Frame (";
String s2a = "I:";
String s2b = "S:";
String s2c = "R:";
String s3 = "byte pkt";
String s4 = "};";
String s5 = "0x";

byte[] pkts = {' ', 'S', ':', ' '};
byte[] pktr = {' ', 'R', ':', ' '};

int i = 1;
String s;
String sc = null;
while((s = abc.readLine())!=null) {
if(Compare(s.getBytes(), s1.getBytes())) {
http://System.out.println("Comment");
} else if(Compare(s.getBytes(), s2a.getBytes())) {
http://System.out.println("I^^");
} else if(Compare(s.getBytes(), s2b.getBytes())) {
http://System.out.println("W^^");
} else if(Compare(s.getBytes(), s2c.getBytes())) {
http://System.out.println("R^^");
} else if(Compare(s.getBytes(), s3.getBytes())) {
http://System.out.println("Start!");
sc = s;
pos=0;
} else if(Compare(s.getBytes(), s4.getBytes())) {
http://System.out.println("End!");
if(pos == HEADLEN) {
pos = 0;
} else if(pos > HEADLEN) {
pos -= HEADLEN;
http://System.out.println("LENGTH="+length+", POS="+pos+".");
System.arraycopy(line, HEADLEN, tmp, length, pos);
length += pos;
if(pos == MAXLEN) {
decStop = true;
} else {
decStop = false;
}
} else {
pos = 0;
tmp[0] = 0x00;
}
} else if(s.getBytes().length == 0) {
http://System.out.println("null!");
if( ((tmp[0] == 0x0D) || (tmp[0] == 0x0E)) && (tmp[1] == 0x00)) {
decFlag = true;
}
if( decFlag && (pos != 0) && (pos != MAXLEN) && !decStop && (length > 4)) {
http://System.out.println("LENGTH2="+length+", POS="+pos+", FLAG=" + (decFlag) + ".");
byte[] pkt = new byte[length];
byte[] pktc = new byte[length];
System.arraycopy(tmp, 0, pkt, 0, length);

if( ((pkt[0] == 0x0D) || (pkt[0] == 0x0E)) && (pkt[1] == 0x00)) {
sendCipher = InitDecode(key, pkt, true);
recvCipher = InitDecode(key, pkt, false);
System.arraycopy(pkt, 0, pktc, 0, length);
convFlag = true;
} else {
byte[] pktd = new byte[length];
System.arraycopy(pkt, 0, pktd, 0, length);
//int head = ((int)pktd[0]<<24) | ((int)pktd[1]<<16) | ((int)pktd[2]<<8) | ((int)pktd[3]);
int head = (pktd[0]<<24) & 0xFF000000 | (pktd[1]<<16) & 0x00FF0000 | (pktd[2]<<8) & 0x0000FF00 | (pktd[3]) & 0x000000FF;

if(sendCipher.checkPacket(head)) {
SendDecode(sendCipher, pktd, "Send");
System.arraycopy(pkts, 0, pktc, 0, 4);
System.arraycopy(pktd, 0, pktc, 4, length - 4);
convFlag = true;
} else if(recvCipher.checkPacket(head)) {
RecvDecode(recvCipher, pktd, "Recv");
System.arraycopy(pktr, 0, pktc, 0, 4);
System.arraycopy(pktd, 0, pktc, 4, length - 4);
convFlag = true;
} else {
//convFlag = false;
System.arraycopy(pktd, 0, pktc, 0, length);
convFlag = false;
}
}
http://fw.write(HexTool.toString(pktc) + "\r\n");
if(convFlag) {
http://System.out.println(i + "行: /* " + sc + " */");
fw.write("/* " + sc + " */\r\n");
fw.write(HexTool.toString(pktc) + "\r\n");
}
}
if((pos != 0) && (pos != MAXLEN) && !decStop) {
http://System.out.println("LENGTH3="+length+", POS="+pos+".");
length = 0;
}
http://System.out.println(i + "行目");
//pos = 0;
} else {
int len = s.getBytes().length;
byte[] work = new byte[len];
System.arraycopy(s.getBytes(), 0, work, 0, len);

/* 0x 変換 */
int flag = 9;
int num = 0;
for(int j=0; j<len; j++) {
if(work[j] == '0') {
if(flag == 9) {
flag = 0;
}
}
if(('0'<=work[j] && work[j]<='9')) {
if(flag == 1) {
num = (work[j] - '0') & 0x0F;
flag = 2;
} else if(flag == 2) {
num = (num << 4) & 0xF0 | (work[j] - '0') & 0x0F;
line[pos] = (byte)(num & 0xFF);
pos++;
flag = 3;
}
}
if(('a'<=work[j] && work[j]<='f')) {
if(flag == 1) {
num = (work[j] - 'a' + 10) & 0x0F;
flag = 2;
} else if(flag == 2) {
num = (num << 4) & 0xF0 | (work[j] - 'a' + 10) & 0x0F;
line[pos] = (byte)(num & 0xFF);
pos++;
flag = 3;
}
}

switch(work[j]) {
case '/':
flag = 5;
break;
case ' ':
case ',':
if(flag < 5) {
flag = 9;
}
break;
case 'x':
if(flag == 0) {
flag = 1;
}
break;
}
}
}
i++;
}
fr.close();
fw.close();
} catch(IOException e) {
}
}

private static MapleAESOFB InitDecode(byte[] key, byte[] pkt, boolean mode) {
http://System.out.println("Login/Channel Server");
MapleAESOFB cipher;

System.out.println("");
System.out.println("I: " + HexTool.toString(pkt));
short version = (short)(((pkt[3]<<8)&0xFF00) | (pkt[2]&0x00FF));
if(mode) {
byte[] ivSend = new byte[4];
if((pkt[0] == (byte)0x0d) && (pkt[1] == (byte)0x00)) {
System.arraycopy(pkt, 10, ivSend, 0, 4);
cipher = new MapleAESOFB(key, ivSend, (short) (0xFFFF - version));
return cipher;
} else if((pkt[0] == (byte)0x0e) && (pkt[1] == (byte)0x00)) {
System.arraycopy(pkt, 11, ivSend, 0, 4);
cipher = new MapleAESOFB(key, ivSend, (short) (0xFFFF - version));
return cipher;
} else {
return null;
}
} else {
byte[] ivRecv = new byte[4];
if((pkt[0] == (byte)0x0d) && (pkt[1] == (byte)0x00)) {
System.arraycopy(pkt, 6, ivRecv, 0, 4);
cipher = new MapleAESOFB(key, ivRecv, (short) version);
return cipher;
} else if((pkt[0] == (byte)0x0e) && (pkt[1] == (byte)0x00)) {
System.arraycopy(pkt, 7, ivRecv, 0, 4);
cipher = new MapleAESOFB(key, ivRecv, (short) version);
return cipher;
} else {
return null;
}
}
}

private static void SendDecode(MapleAESOFB cipher, byte[] pkt, String name) {
// Crypt定義
MaplePacketDecoder recvcrypt = new MaplePacketDecoder();
for(int pos = 0; pos < pkt.length; ) {
http://System.out.println("pkt.length=" + pkt.length + ", packetlength=" + recvcrypt.packetlength + ".");
byte[] pktwork = new byte[pkt.length - pos];
System.arraycopy(pkt, pos, pktwork, 0, pkt.length - pos);
byte[] pktworkdec = recvcrypt.doDecode(cipher, pktwork);
byte[] work = new byte[recvcrypt.packetlength];
System.arraycopy(pktworkdec, 0, work, 0, recvcrypt.packetlength);
http://System.out.println("pkt" + name + "_" + HexTool.toString(pos) + ":" + HexTool.toString(pktwork));
http://System.out.println("pkt" + name + "_" + HexTool.toString(pos) + "dec S: " + HexTool.toString(work));
System.out.println("S: " + HexTool.toString(work));
pos += recvcrypt.packetlength + 4;
}
}

private static void RecvDecode(MapleAESOFB cipher, byte[] pkt, String name) {
// Crypt定義
MaplePacketDecoder recvcrypt = new MaplePacketDecoder();
for(int pos = 0; pos < pkt.length; ) {
http://System.out.println("pkt.length=" + pkt.length + ", packetlength=" + recvcrypt.packetlength + ".");
byte[] pktwork = new byte[pkt.length - pos];
System.arraycopy(pkt, pos, pktwork, 0, pkt.length - pos);
byte[] pktworkdec = recvcrypt.doDecode(cipher, pktwork);
byte[] work = new byte[recvcrypt.packetlength];
System.arraycopy(pktworkdec, 0, work, 0, recvcrypt.packetlength);
http://System.out.println("pkt" + name + "_" + HexTool.toString(pos) + ":" + HexTool.toString(pktwork));
http://System.out.println("pkt" + name + "_" + HexTool.toString(pos) + "dec R: " + HexTool.toString(work));
System.out.println("R: " + HexTool.toString(work));
pos += recvcrypt.packetlength + 4;
}
}

private static boolean Compare(byte[] stream1, byte[] stream2) {
if(stream1.length < stream2.length) {
return false;
}
for (int pos = 0; pos < stream2.length; pos++) {
if (stream1[pos] != stream2[pos] ) {
return false;

}
return true;
}
}
[
avatar
構築さん
Admin

Posts : 193
Join date : 2014/05/29

http://maplescience.forumjap.com

トップに戻る Go down

トップに戻る


 
Permissions in this forum:
返信投稿: 不可