mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2024-11-27 10:50:50 +01:00
Add shockwave crypto
This commit is contained in:
parent
b1d5faef11
commit
e126048fe4
23
G-Earth/src/main/java/gearth/encoding/HexEncoding.java
Normal file
23
G-Earth/src/main/java/gearth/encoding/HexEncoding.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package gearth.encoding;
|
||||||
|
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class HexEncoding {
|
||||||
|
|
||||||
|
public static byte[] toBytes(String s) {
|
||||||
|
return Hex.decode(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] toHex(byte[] bytes, boolean upperCase) {
|
||||||
|
String data = Hex.toHexString(bytes);
|
||||||
|
|
||||||
|
if (upperCase) {
|
||||||
|
data = data.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,7 +24,7 @@ public class HConnection {
|
|||||||
|
|
||||||
private volatile ExtensionHandler extensionHandler = null;
|
private volatile ExtensionHandler extensionHandler = null;
|
||||||
|
|
||||||
private volatile Object[] trafficObservables = {new Observable<TrafficListener>(), new Observable<TrafficListener>(), new Observable<TrafficListener>()};
|
private volatile Observable<TrafficListener>[] trafficObservables = new Observable[]{new Observable<TrafficListener>(), new Observable<TrafficListener>(), new Observable<TrafficListener>()};
|
||||||
private volatile Observable<StateChangeListener> stateObservable = new Observable<>();
|
private volatile Observable<StateChangeListener> stateObservable = new Observable<>();
|
||||||
private volatile Observable<Consumer<Boolean>> developerModeChangeObservable = new Observable<>();
|
private volatile Observable<Consumer<Boolean>> developerModeChangeObservable = new Observable<>();
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ public class HConnection {
|
|||||||
return extensionHandler;
|
return extensionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object[] getTrafficObservables() {
|
public Observable<TrafficListener>[] getTrafficObservables() {
|
||||||
return trafficObservables;
|
return trafficObservables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ public class ShockwaveProxy implements ProxyProvider, ConnectionInterceptorCallb
|
|||||||
final Semaphore abort = new Semaphore(0);
|
final Semaphore abort = new Semaphore(0);
|
||||||
|
|
||||||
final ShockwavePacketOutgoingHandler outgoingHandler = new ShockwavePacketOutgoingHandler(server.getOutputStream(), hConnection.getExtensionHandler(), hConnection.getTrafficObservables());
|
final ShockwavePacketOutgoingHandler outgoingHandler = new ShockwavePacketOutgoingHandler(server.getOutputStream(), hConnection.getExtensionHandler(), hConnection.getTrafficObservables());
|
||||||
final ShockwavePacketIncomingHandler incomingHandler = new ShockwavePacketIncomingHandler(client.getOutputStream(), hConnection.getExtensionHandler(), hConnection.getTrafficObservables());
|
final ShockwavePacketIncomingHandler incomingHandler = new ShockwavePacketIncomingHandler(client.getOutputStream(), hConnection.getExtensionHandler(), hConnection.getTrafficObservables(), outgoingHandler);
|
||||||
|
|
||||||
// TODO: Non hardcoded version "20". Not exactly sure yet how to deal with this for now.
|
// TODO: Non hardcoded version "20". Not exactly sure yet how to deal with this for now.
|
||||||
// Lets revisit when origins is more mature.
|
// Lets revisit when origins is more mature.
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package gearth.protocol.memory.habboclient.macOs;
|
package gearth.protocol.memory.habboclient.macOs;
|
||||||
|
|
||||||
|
import gearth.encoding.HexEncoding;
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
import gearth.protocol.memory.habboclient.HabboClient;
|
import gearth.protocol.memory.habboclient.HabboClient;
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ public class MacOsHabboClient extends HabboClient {
|
|||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
|
||||||
for (String s : possibleResults)
|
for (String s : possibleResults)
|
||||||
result.add(hexStringToByteArray(s));
|
result.add(HexEncoding.toBytes(s));
|
||||||
} catch (IOException | URISyntaxException e) {
|
} catch (IOException | URISyntaxException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -124,25 +126,11 @@ public class MacOsHabboClient extends HabboClient {
|
|||||||
ArrayList<String> possibleData = readPossibleBytes(false);
|
ArrayList<String> possibleData = readPossibleBytes(false);
|
||||||
|
|
||||||
for (String possibleHexStr : possibleData) {
|
for (String possibleHexStr : possibleData) {
|
||||||
result.add(hexStringToByteArray(possibleHexStr));
|
result.add(HexEncoding.toBytes(possibleHexStr));
|
||||||
}
|
}
|
||||||
} catch (IOException | URISyntaxException e) {
|
} catch (IOException | URISyntaxException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] hexStringToByteArray(String s) {
|
|
||||||
int len = s.length();
|
|
||||||
if (len % 2 == 1) {
|
|
||||||
s = "0" + s;
|
|
||||||
len += 1;
|
|
||||||
}
|
|
||||||
byte[] data = new byte[len / 2];
|
|
||||||
for (int i = 0; i < len; i += 2) {
|
|
||||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
|
||||||
+ Character.digit(s.charAt(i+1), 16));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package gearth.protocol.memory.habboclient.rust;
|
package gearth.protocol.memory.habboclient.rust;
|
||||||
|
|
||||||
|
import gearth.encoding.HexEncoding;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.memory.habboclient.HabboClient;
|
import gearth.protocol.memory.habboclient.HabboClient;
|
||||||
|
|
||||||
@ -48,18 +49,8 @@ public class RustHabboClient extends HabboClient {
|
|||||||
List<byte[]> ret = new ArrayList<>();
|
List<byte[]> ret = new ArrayList<>();
|
||||||
|
|
||||||
for (String possibleHexStr : possibleData)
|
for (String possibleHexStr : possibleData)
|
||||||
ret.add(hexStringToByteArray(possibleHexStr));
|
ret.add(HexEncoding.toBytes(possibleHexStr));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] hexStringToByteArray(String s) {
|
|
||||||
int len = s.length();
|
|
||||||
byte[] data = new byte[len / 2];
|
|
||||||
for (int i = 0; i < len; i += 2) {
|
|
||||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
|
||||||
+ Character.digit(s.charAt(i+1), 16));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package gearth.protocol.memory.habboclient.windows;
|
package gearth.protocol.memory.habboclient.windows;
|
||||||
|
|
||||||
|
import gearth.encoding.HexEncoding;
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
@ -44,7 +45,7 @@ public class WindowsHabboClient extends HabboClient {
|
|||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
|
||||||
for (String s : possibleResults)
|
for (String s : possibleResults)
|
||||||
result.add(hexStringToByteArray(s));
|
result.add(HexEncoding.toBytes(s));
|
||||||
} catch (IOException | URISyntaxException e) {
|
} catch (IOException | URISyntaxException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -126,21 +127,11 @@ public class WindowsHabboClient extends HabboClient {
|
|||||||
ArrayList<String> possibleData = readPossibleBytes(false);
|
ArrayList<String> possibleData = readPossibleBytes(false);
|
||||||
|
|
||||||
for (String possibleHexStr : possibleData) {
|
for (String possibleHexStr : possibleData) {
|
||||||
result.add(hexStringToByteArray(possibleHexStr));
|
result.add(HexEncoding.toBytes(possibleHexStr));
|
||||||
}
|
}
|
||||||
} catch (IOException | URISyntaxException e) {
|
} catch (IOException | URISyntaxException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] hexStringToByteArray(String s) {
|
|
||||||
int len = s.length();
|
|
||||||
byte[] data = new byte[len / 2];
|
|
||||||
for (int i = 0; i < len; i += 2) {
|
|
||||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
|
||||||
+ Character.digit(s.charAt(i+1), 16));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,27 @@
|
|||||||
package gearth.protocol.packethandler.shockwave;
|
package gearth.protocol.packethandler.shockwave;
|
||||||
|
|
||||||
|
import gearth.encoding.HexEncoding;
|
||||||
|
import gearth.misc.listenerpattern.Observable;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
import gearth.protocol.HPacket;
|
import gearth.protocol.HPacket;
|
||||||
|
import gearth.protocol.TrafficListener;
|
||||||
import gearth.protocol.packethandler.PacketHandler;
|
import gearth.protocol.packethandler.PacketHandler;
|
||||||
import gearth.protocol.packethandler.shockwave.buffers.ShockwaveBuffer;
|
import gearth.protocol.packethandler.shockwave.buffers.ShockwaveBuffer;
|
||||||
|
import gearth.protocol.packethandler.shockwave.crypto.RC4Shockwave;
|
||||||
import gearth.services.extension_handler.ExtensionHandler;
|
import gearth.services.extension_handler.ExtensionHandler;
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public abstract class ShockwavePacketHandler extends PacketHandler {
|
public abstract class ShockwavePacketHandler extends PacketHandler {
|
||||||
|
|
||||||
|
// The first 20 bytes of the artificialKey.
|
||||||
|
public static final byte[] ARTIFICIAL_KEY = Hex.decode("14d288cdb0bc08c274809a7802962af98b41dec8");
|
||||||
|
|
||||||
protected static final Logger logger = LoggerFactory.getLogger(ShockwavePacketHandler.class);
|
protected static final Logger logger = LoggerFactory.getLogger(ShockwavePacketHandler.class);
|
||||||
|
|
||||||
private final HMessage.Direction direction;
|
private final HMessage.Direction direction;
|
||||||
@ -21,19 +30,53 @@ public abstract class ShockwavePacketHandler extends PacketHandler {
|
|||||||
|
|
||||||
protected final OutputStream outputStream;
|
protected final OutputStream outputStream;
|
||||||
|
|
||||||
ShockwavePacketHandler(HMessage.Direction direction, ShockwaveBuffer payloadBuffer, OutputStream outputStream, ExtensionHandler extensionHandler, Object[] trafficObservables) {
|
private boolean isEncrypted;
|
||||||
|
private final RC4Shockwave decryptCipher;
|
||||||
|
private final RC4Shockwave encryptCipher;
|
||||||
|
|
||||||
|
ShockwavePacketHandler(HMessage.Direction direction, ShockwaveBuffer payloadBuffer, OutputStream outputStream, ExtensionHandler extensionHandler, Observable<TrafficListener>[] trafficObservables) {
|
||||||
super(extensionHandler, trafficObservables);
|
super(extensionHandler, trafficObservables);
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
this.payloadBuffer = payloadBuffer;
|
this.payloadBuffer = payloadBuffer;
|
||||||
this.outputStream = outputStream;
|
this.outputStream = outputStream;
|
||||||
this.flushLock = new Object();
|
this.flushLock = new Object();
|
||||||
|
this.isEncrypted = false;
|
||||||
|
this.decryptCipher = new RC4Shockwave(0, ARTIFICIAL_KEY);
|
||||||
|
this.encryptCipher = new RC4Shockwave(0, ARTIFICIAL_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setEncrypted() {
|
||||||
|
isEncrypted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sendToStream(byte[] buffer) {
|
||||||
|
return sendToStream(buffer, isEncrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendToStream(byte[] buffer, boolean isEncrypted) {
|
||||||
|
synchronized (sendLock) {
|
||||||
|
try {
|
||||||
|
if (!isEncrypted) {
|
||||||
|
outputStream.write(buffer);
|
||||||
|
} else {
|
||||||
|
outputStream.write(HexEncoding.toHex(encryptCipher.crypt(buffer), true));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Failed to send packet to stream", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void act(byte[] buffer) throws IOException {
|
public void act(byte[] buffer) throws IOException {
|
||||||
logger.info("Direction {} Received {} bytes", this.direction, buffer.length);
|
if (!isEncrypted) {
|
||||||
|
|
||||||
payloadBuffer.push(buffer);
|
payloadBuffer.push(buffer);
|
||||||
|
} else {
|
||||||
|
payloadBuffer.push(decryptCipher.crypt(Hex.decode(buffer)));
|
||||||
|
}
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
@ -43,6 +86,8 @@ public abstract class ShockwavePacketHandler extends PacketHandler {
|
|||||||
final HPacket[] packets = payloadBuffer.receive();
|
final HPacket[] packets = payloadBuffer.receive();
|
||||||
|
|
||||||
for (final HPacket packet : packets){
|
for (final HPacket packet : packets){
|
||||||
|
packet.setIdentifierDirection(direction);
|
||||||
|
|
||||||
final HMessage message = new HMessage(packet, direction, currentIndex);
|
final HMessage message = new HMessage(packet, direction, currentIndex);
|
||||||
|
|
||||||
awaitListeners(message, x -> sendToStream(x.getPacket().toBytes()));
|
awaitListeners(message, x -> sendToStream(x.getPacket().toBytes()));
|
||||||
|
@ -1,28 +1,47 @@
|
|||||||
package gearth.protocol.packethandler.shockwave;
|
package gearth.protocol.packethandler.shockwave;
|
||||||
|
|
||||||
|
import gearth.misc.listenerpattern.Observable;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
|
import gearth.protocol.TrafficListener;
|
||||||
|
import gearth.protocol.packethandler.ByteArrayUtils;
|
||||||
import gearth.protocol.packethandler.shockwave.buffers.ShockwaveInBuffer;
|
import gearth.protocol.packethandler.shockwave.buffers.ShockwaveInBuffer;
|
||||||
|
import gearth.protocol.packethandler.shockwave.packets.ShockPacket;
|
||||||
import gearth.services.extension_handler.ExtensionHandler;
|
import gearth.services.extension_handler.ExtensionHandler;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class ShockwavePacketIncomingHandler extends ShockwavePacketHandler {
|
public class ShockwavePacketIncomingHandler extends ShockwavePacketHandler {
|
||||||
public ShockwavePacketIncomingHandler(OutputStream outputStream, ExtensionHandler extensionHandler, Object[] trafficObservables) {
|
|
||||||
|
private static final byte[] PACKET_END = new byte[] {0x01};
|
||||||
|
private static final int ID_SECRET_KEY = 1;
|
||||||
|
|
||||||
|
public ShockwavePacketIncomingHandler(OutputStream outputStream, ExtensionHandler extensionHandler, Observable<TrafficListener>[] trafficObservables, ShockwavePacketHandler outgoingHandler) {
|
||||||
super(HMessage.Direction.TOCLIENT, new ShockwaveInBuffer(), outputStream, extensionHandler, trafficObservables);
|
super(HMessage.Direction.TOCLIENT, new ShockwaveInBuffer(), outputStream, extensionHandler, trafficObservables);
|
||||||
|
|
||||||
|
trafficObservables[0].addListener(new TrafficListener() {
|
||||||
|
@Override
|
||||||
|
public void onCapture(HMessage message) {
|
||||||
|
if (!(message.getPacket() instanceof ShockPacket)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ShockPacket packet = (ShockPacket) message.getPacket();
|
||||||
|
|
||||||
|
if (!packet.canSendToClient()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.headerId() == ID_SECRET_KEY) {
|
||||||
|
logger.info("Received SECRET_KEY from server, enabling encryption / decryption.");
|
||||||
|
trafficObservables[0].removeListener(this);
|
||||||
|
outgoingHandler.setEncrypted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendToStream(byte[] buffer) {
|
public boolean sendToStream(byte[] packet) {
|
||||||
synchronized (sendLock) {
|
return super.sendToStream(ByteArrayUtils.combineByteArrays(packet, PACKET_END));
|
||||||
try {
|
|
||||||
outputStream.write(buffer);
|
|
||||||
outputStream.write(new byte[] {0x01});
|
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error while sending packet to stream.", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,25 @@
|
|||||||
package gearth.protocol.packethandler.shockwave;
|
package gearth.protocol.packethandler.shockwave;
|
||||||
|
|
||||||
import gearth.encoding.Base64Encoding;
|
import gearth.encoding.Base64Encoding;
|
||||||
|
import gearth.misc.listenerpattern.Observable;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
|
import gearth.protocol.TrafficListener;
|
||||||
|
import gearth.protocol.packethandler.ByteArrayUtils;
|
||||||
import gearth.protocol.packethandler.shockwave.buffers.ShockwaveOutBuffer;
|
import gearth.protocol.packethandler.shockwave.buffers.ShockwaveOutBuffer;
|
||||||
import gearth.services.extension_handler.ExtensionHandler;
|
import gearth.services.extension_handler.ExtensionHandler;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class ShockwavePacketOutgoingHandler extends ShockwavePacketHandler {
|
public class ShockwavePacketOutgoingHandler extends ShockwavePacketHandler {
|
||||||
public ShockwavePacketOutgoingHandler(OutputStream outputStream, ExtensionHandler extensionHandler, Object[] trafficObservables) {
|
public ShockwavePacketOutgoingHandler(OutputStream outputStream, ExtensionHandler extensionHandler, Observable<TrafficListener>[] trafficObservables) {
|
||||||
super(HMessage.Direction.TOSERVER, new ShockwaveOutBuffer(), outputStream, extensionHandler, trafficObservables);
|
super(HMessage.Direction.TOSERVER, new ShockwaveOutBuffer(), outputStream, extensionHandler, trafficObservables);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendToStream(byte[] buffer) {
|
public boolean sendToStream(byte[] packet) {
|
||||||
synchronized (sendLock) {
|
byte[] bufferLen = Base64Encoding.encode(packet.length, 3);
|
||||||
try {
|
byte[] buffer = ByteArrayUtils.combineByteArrays(bufferLen, packet);
|
||||||
byte[] bufferLen = Base64Encoding.encode(buffer.length, 3);
|
|
||||||
|
|
||||||
outputStream.write(bufferLen);
|
return super.sendToStream(buffer);
|
||||||
outputStream.write(buffer);
|
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error while sending packet to stream.", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package gearth.protocol.packethandler.shockwave.crypto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Habbo Shockwave RC4 is broken, meaning this is not a standard RC4 implementation.
|
||||||
|
* Thanks to <a href="https://github.com/aromaa">Joni</a> and <a href="https://github.com/scottstamp">DarkStar851</a> for discovering this.
|
||||||
|
*/
|
||||||
|
public class RC4Shockwave {
|
||||||
|
|
||||||
|
private static final int TABLE_SIZE = 256;
|
||||||
|
|
||||||
|
private final int[] table;
|
||||||
|
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
|
||||||
|
public RC4Shockwave(int key, byte[] artificialKey) {
|
||||||
|
this.table = buildTable(key, artificialKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] crypt(byte[] data) {
|
||||||
|
byte[] result = new byte[data.length];
|
||||||
|
|
||||||
|
for (int i = 0; i < data.length; i++) {
|
||||||
|
x = (x + 1) % TABLE_SIZE;
|
||||||
|
y = (y + table[x] & 0xff) % TABLE_SIZE;
|
||||||
|
|
||||||
|
swap(table, x, y);
|
||||||
|
|
||||||
|
int xorIndex = ((table[x] & 0xff) + (table[y] & 0xff)) % TABLE_SIZE;
|
||||||
|
|
||||||
|
result[i] = (byte) (data[i] ^ table[xorIndex & 0xff]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] buildTable(int key, byte[] artificialKey) {
|
||||||
|
byte[] modKey = new byte[20];
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < modKey.length; i++, j++) {
|
||||||
|
if (j >= artificialKey.length) {
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
modKey[i] = (byte) (key & modKey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] table = new int[TABLE_SIZE];
|
||||||
|
|
||||||
|
for (int i = 0; i < TABLE_SIZE; i++) {
|
||||||
|
table[i] = (byte) i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int q = 0, j = 0; q < TABLE_SIZE; q++) {
|
||||||
|
j = (j + (table[q] & 0xff) + modKey[q % modKey.length]) % TABLE_SIZE;
|
||||||
|
|
||||||
|
swap(table, q, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void swap(int[] table, int i, int j) {
|
||||||
|
int temp = table[i];
|
||||||
|
table[i] = table[j];
|
||||||
|
table[j] = temp;
|
||||||
|
}
|
||||||
|
}
|
@ -36,18 +36,17 @@ public class AdminService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onMessage(HMessage message) {
|
public void onMessage(HMessage message) {
|
||||||
|
if (!enabled) return;
|
||||||
HPacket packet = message.getPacket();
|
HPacket packet = message.getPacket();
|
||||||
if (message.getDestination() == HMessage.Direction.TOCLIENT
|
if (message.getDestination() == HMessage.Direction.TOCLIENT
|
||||||
&& (originalPacket == null || packet.headerId() == originalPacket.headerId())
|
&& (originalPacket == null || packet.headerId() == originalPacket.headerId())
|
||||||
&& packet.length() == 11 && (packet.readByte(14) == 0 || packet.readByte(14) == 1)) {
|
&& packet.length() == 11 && (packet.readByte(14) == 0 || packet.readByte(14) == 1)) {
|
||||||
originalPacket = new HPacket(packet);
|
originalPacket = new HPacket(packet);
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
packet.replaceInt(6, 7);
|
packet.replaceInt(6, 7);
|
||||||
packet.replaceInt(10, 7);
|
packet.replaceInt(10, 7);
|
||||||
packet.replaceBoolean(14, true);
|
packet.replaceBoolean(14, true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user