diff --git a/G-Earth/src/main/java/gearth/misc/StringUtils.java b/G-Earth/src/main/java/gearth/misc/StringUtils.java new file mode 100644 index 0000000..660447f --- /dev/null +++ b/G-Earth/src/main/java/gearth/misc/StringUtils.java @@ -0,0 +1,22 @@ +package gearth.misc; + +/** + * Contains utility methods for {@link String} conversions. + */ +public final class StringUtils { + + /** + * Interprets the argued {@link String} as a hex-string and converts it to a byte array. + * @param hexString the {@link String} to be converted. + * @return a byte array containing the converted hex string values. + */ + public static byte[] hexStringToByteArray(String hexString) { + int len = hexString.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + + Character.digit(hexString.charAt(i+1), 16)); + } + return data; + } +} diff --git a/G-Earth/src/main/java/gearth/protocol/HConnection.java b/G-Earth/src/main/java/gearth/protocol/HConnection.java index 495481f..9263687 100644 --- a/G-Earth/src/main/java/gearth/protocol/HConnection.java +++ b/G-Earth/src/main/java/gearth/protocol/HConnection.java @@ -20,7 +20,7 @@ import java.util.function.Consumer; public class HConnection { public static volatile boolean DECRYPTPACKETS = true; - public static volatile boolean DEBUG = false; + public static volatile boolean DEBUG = true; private volatile ExtensionHandler extensionHandler = null; @@ -255,4 +255,12 @@ public class HConnection { public ProxyProvider getProxyProvider() { return proxyProvider; } + + @Override + public String toString() { + return "HConnection{" + + "state=" + state + + ", proxy=" + proxy + + '}'; + } } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/HProxy.java b/G-Earth/src/main/java/gearth/protocol/connection/HProxy.java index 57d6d62..e565b5d 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/HProxy.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/HProxy.java @@ -116,4 +116,21 @@ public class HProxy { public PacketInfoManager getPacketInfoManager() { return packetInfoManager; } + + @Override + public String toString() { + return "HProxy{" + + "hClient=" + hClient + + ", input_domain='" + input_domain + '\'' + + ", actual_domain='" + actual_domain + '\'' + + ", actual_port=" + actual_port + + ", intercept_port=" + intercept_port + + ", intercept_host='" + intercept_host + '\'' + + ", proxy_server=" + proxy_server + + ", inHandler=" + inHandler + + ", outHandler=" + outHandler + + ", hotelVersion='" + hotelVersion + '\'' + + ", clientIdentifier='" + clientIdentifier + '\'' + + '}'; + } } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/FlashProxyProvider.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/FlashProxyProvider.java index 6df5f7a..dedddde 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/FlashProxyProvider.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/FlashProxyProvider.java @@ -7,18 +7,18 @@ import gearth.protocol.connection.HState; import gearth.protocol.connection.HStateSetter; import gearth.protocol.connection.proxy.ProxyProvider; import gearth.protocol.memory.Rc4Obtainer; +import gearth.protocol.packethandler.flash.FlashPacketHandler; import gearth.protocol.packethandler.flash.IncomingFlashPacketHandler; import gearth.protocol.packethandler.flash.OutgoingFlashPacketHandler; -import gearth.protocol.packethandler.flash.FlashPacketHandler; import gearth.ui.titlebar.TitleBarController; import gearth.ui.translations.LanguageBundle; import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.Label; -import javafx.scene.image.Image; import javafx.scene.layout.Region; -import javafx.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.Socket; @@ -27,6 +27,7 @@ import java.util.concurrent.Semaphore; public abstract class FlashProxyProvider implements ProxyProvider { + protected final Logger logger = LoggerFactory.getLogger(getClass()); protected final HProxySetter proxySetter; protected final HStateSetter stateSetter; protected final HConnection hConnection; @@ -47,7 +48,8 @@ public abstract class FlashProxyProvider implements ProxyProvider { client.setSoTimeout(0); server.setSoTimeout(0); - if (HConnection.DEBUG) System.out.println(server.getLocalAddress().getHostAddress() + ": " + server.getLocalPort()); + logger.debug("Starting proxy thread at {}:{}", server.getLocalAddress().getHostAddress(), server.getLocalPort()); + Rc4Obtainer rc4Obtainer = new Rc4Obtainer(hConnection); OutgoingFlashPacketHandler outgoingHandler = new OutgoingFlashPacketHandler(server.getOutputStream(), hConnection.getTrafficObservables(), hConnection.getExtensionHandler()); @@ -73,13 +75,13 @@ public abstract class FlashProxyProvider implements ProxyProvider { try { if (!server.isClosed()) server.close(); if (!client.isClosed()) client.close(); - if (HConnection.DEBUG) System.out.println("STOP"); + logger.debug("Closed server {} and client {}, dataStreams {}", server, client, datastream); if (datastream[0]) { onConnectEnd(); }; } catch (IOException e) { - e.printStackTrace(); + logger.error("Failed to gracefully stop", e); } } @@ -95,8 +97,7 @@ public abstract class FlashProxyProvider implements ProxyProvider { } } catch (IOException ignore) { -// System.err.println(packetHandler instanceof IncomingPacketHandler ? "incoming" : "outgoing"); -// ignore.printStackTrace(); +// logger.error("Failed to read input stream from socket {}", socket, ignore); } finally { abort.release(); } @@ -132,9 +133,8 @@ public abstract class FlashProxyProvider implements ProxyProvider { try { TitleBarController.create(alert).showAlert(); } catch (IOException e) { - e.printStackTrace(); + logger.error("Failed to create invalid connection error alert", e); } }); } - } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java index 49b4c6e..4404cf4 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java @@ -1,6 +1,5 @@ package gearth.protocol.connection.proxy.flash; -import gearth.GEarth; import gearth.misc.Cacher; import gearth.protocol.HConnection; import gearth.protocol.connection.*; @@ -14,8 +13,6 @@ import gearth.ui.titlebar.TitleBarController; import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; -import javafx.scene.image.Image; -import javafx.stage.Stage; import java.io.IOException; import java.net.*; @@ -26,7 +23,6 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { private List potentialHosts; - private static final HostReplacer hostsReplacer = HostReplacerFactory.get(); private volatile boolean hostRedirected = false; @@ -113,7 +109,7 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { try { TitleBarController.create(a).showAlertAndWait(); } catch (IOException ex) { - ex.printStackTrace(); + logger.error("Failed to create port in use error alert", ex); } }); throw new IOException(e); @@ -128,8 +124,7 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { Socket client = proxy_server.accept(); proxy = potentialProxy; closeAllProxies(proxy); - if (HConnection.DEBUG) System.out.println("accepted a proxy"); - + logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})",proxy, useSocks); new Thread(() -> { try { Socket server; @@ -152,18 +147,14 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { // should only happen when SOCKS configured badly showInvalidConnectionError(); abort(); - e.printStackTrace(); + logger.error("Failed to configure SOCKS proxy", e); } catch (InterruptedException | IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + logger.error("An unexpected exception occurred", e); } }).start(); - - } catch (IOException e1) { - // TODO Auto-generated catch block -// e1.printStackTrace(); + logger.error("An unexpected exception occurred", e1); } } } catch (Exception e) { @@ -171,10 +162,7 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { } }).start(); } - - - if (HConnection.DEBUG) System.out.println("done waiting for clients with: " + hConnection.getState() ); - + logger.debug("Done waiting for clients with connection state {}", hConnection.getState()); } @Override @@ -233,12 +221,10 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { try { proxy.getProxy_server().close(); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + logger.error("Failed to close all proxies", e); } } } } -// potentialProxies = Collections.singletonList(except); } } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/unix/LinuxRawIpFlashProxyProvider.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/unix/LinuxRawIpFlashProxyProvider.java index 3b31f78..95337fd 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/unix/LinuxRawIpFlashProxyProvider.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/unix/LinuxRawIpFlashProxyProvider.java @@ -54,7 +54,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { maybeAddMapping(); - if (HConnection.DEBUG) System.out.println("Added mapping for raw IP"); + logger.debug("Added mapping for raw IP"); ServerSocket proxy_server = new ServerSocket(proxy.getIntercept_port(), 10, InetAddress.getByName(proxy.getIntercept_host())); proxy.initProxy(proxy_server); @@ -62,10 +62,10 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { stateSetter.setState(HState.WAITING_FOR_CLIENT); while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxy_server.isClosed()) { try { - if (HConnection.DEBUG) System.out.println("try accept proxy"); + logger.debug("Trying to accept a new proxy from {}", proxy_server); Socket client = proxy_server.accept(); - if (HConnection.DEBUG) System.out.println("accepted a proxy"); + logger.debug("Accepted a proxy {}", client); new Thread(() -> { try { @@ -82,7 +82,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { } catch (Exception e) { - e.printStackTrace(); + logger.error("An unexpected exception occurred in proxy listener", e); } }).start(); } @@ -114,7 +114,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { try { proxy.getProxy_server().close(); } catch (IOException e) { - e.printStackTrace(); + logger.error("Failed to close proxy server", e); } } } @@ -136,6 +136,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { } catch (SocketTimeoutException e) { showInvalidConnectionError(); + logger.error("Connection to proxy {} timed out", proxy, e); return false; } @@ -151,7 +152,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { createSocksProxyThread(client); } else if (preConnectedServerConnections.isEmpty()) { - if (HConnection.DEBUG) System.out.println("pre-made server connections ran out of stock"); + logger.error("pre-made server connections ran out of stock"); } else { startProxyThread(client, preConnectedServerConnections.poll(), proxy); @@ -165,6 +166,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { maybeRemoveMapping(); stateSetter.setState(HState.NOT_CONNECTED); showInvalidConnectionError(); + logger.error("Failed to create socks proxy thread because configuration is null"); return; } @@ -177,7 +179,7 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { maybeRemoveMapping(); stateSetter.setState(HState.NOT_CONNECTED); showInvalidConnectionError(); - e.printStackTrace(); + logger.error("Failed to create socks proxy thread", e); } } @@ -188,7 +190,5 @@ public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider { protected void maybeRemoveMapping() { ipMapper.deleteMapping(proxy.getActual_domain(), proxy.getActual_port(), proxy.getIntercept_port()); - } - } diff --git a/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java b/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java index cc9ea5e..4754cbf 100644 --- a/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java +++ b/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java @@ -1,14 +1,21 @@ package gearth.protocol.hostreplacer.hostsfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * Created by Jonas on 04/04/18. */ class UnixHostReplacer implements HostReplacer { + private static final Logger LOGGER = LoggerFactory.getLogger(UnixHostReplacer.class); + protected String hostsFileLocation; UnixHostReplacer() { @@ -17,23 +24,24 @@ class UnixHostReplacer implements HostReplacer { @Override public void addRedirect(String[] lines) { - List adders = new ArrayList<>(); - for (int i = 0; i < lines.length; i++) { - adders.add(lines[i] + "\t# G-Earth replacement"); - } - FileReader fr = null; - BufferedReader br = null; - FileWriter fw = null; - BufferedWriter out = null; + final List adders = appendCommentToEachLine(lines); + FileReader fr; + BufferedReader br; + FileWriter fw; + BufferedWriter out; try { - ArrayList fileLines = new ArrayList<>(); - File f1 = new File(hostsFileLocation); - fr = new FileReader(f1); + final ArrayList fileLines = new ArrayList<>(); + final File hostsFile = new File(hostsFileLocation); + + LOGGER.debug("Replacing hosts at {}", hostsFile.getAbsolutePath()); + + fr = new FileReader(hostsFile); br = new BufferedReader(fr); - String line = null; + + String line; while ((line = br.readLine()) != null) { adders.remove(line); @@ -42,7 +50,7 @@ class UnixHostReplacer implements HostReplacer { fr.close(); br.close(); - fw = new FileWriter(f1); + fw = new FileWriter(hostsFile); out = new BufferedWriter(fw); for (String li : adders) { @@ -58,29 +66,26 @@ class UnixHostReplacer implements HostReplacer { } catch (Exception ex) { - ex.printStackTrace(); + LOGGER.error("Failed to add host redirects", ex); } } @Override public void removeRedirect(String[] lines) { - ArrayList removers = new ArrayList<>(); - for (int i = 0; i < lines.length; i++) { - removers.add(lines[i] + "\t# G-Earth replacement"); - } + final List removers = appendCommentToEachLine(lines); - FileReader fr = null; - BufferedReader br = null; - FileWriter fw = null; - BufferedWriter out = null; + FileReader fr; + BufferedReader br; + FileWriter fw; + BufferedWriter out; try { - ArrayList fileLines = new ArrayList(); - File f1 = new File(hostsFileLocation); - fr = new FileReader(f1); + final ArrayList fileLines = new ArrayList<>(); + final File hostsFile = new File(hostsFileLocation); + fr = new FileReader(hostsFile); br = new BufferedReader(fr); - String line = null; + String line; while ((line = br.readLine()) != null) { if (!removers.contains(line)) @@ -89,12 +94,13 @@ class UnixHostReplacer implements HostReplacer { fr.close(); br.close(); - fw = new FileWriter(f1); + fw = new FileWriter(hostsFile); out = new BufferedWriter(fw); for (int i = 0; i < fileLines.size(); i++) { out.write(fileLines.get(i)); - if (i != fileLines.size() - 1) out.write(System.getProperty("line.separator")); + if (i != fileLines.size() - 1) + out.write(System.getProperty("line.separator")); } out.flush(); fw.close(); @@ -102,7 +108,14 @@ class UnixHostReplacer implements HostReplacer { } catch (Exception ex) { - ex.printStackTrace(); + LOGGER.error("Failed to remove host replace lines", ex); } } + + private static List appendCommentToEachLine(String[] lines) { + return Arrays + .stream(lines) + .map(line -> line + "\t# G-Earth replacement") + .collect(Collectors.toList()); + } } diff --git a/G-Earth/src/main/java/gearth/protocol/memory/Rc4Obtainer.java b/G-Earth/src/main/java/gearth/protocol/memory/Rc4Obtainer.java index 616354c..debd252 100644 --- a/G-Earth/src/main/java/gearth/protocol/memory/Rc4Obtainer.java +++ b/G-Earth/src/main/java/gearth/protocol/memory/Rc4Obtainer.java @@ -18,6 +18,8 @@ import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.layout.FlowPane; import javafx.scene.layout.Region; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Arrays; @@ -25,7 +27,9 @@ import java.util.List; public class Rc4Obtainer { - public static final boolean DEBUG = false; + private static final Logger LOGGER = LoggerFactory.getLogger(Rc4Obtainer.class); + + public static final boolean DEBUG = true; private final HabboClient client; private List flashPacketHandlers; @@ -58,8 +62,7 @@ public class Rc4Obtainer { new Thread(() -> { long startTime = System.currentTimeMillis(); - if (DEBUG) System.out.println("[+] send encrypted"); - + LOGGER.debug("[+] send encrypted"); boolean worked = false; int i = 0; while (!worked && i < 4) { @@ -70,8 +73,7 @@ public class Rc4Obtainer { } if (!worked) { - System.err.println("COULD NOT FIND RC4 TABLE"); - + LOGGER.error("COULD NOT FIND RC4 TABLE"); Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.WARNING, LanguageBundle.get("alert.somethingwentwrong.title"), ButtonType.OK); @@ -90,14 +92,13 @@ public class Rc4Obtainer { try { TitleBarController.create(alert).showAlert(); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Failed to create error alert", e); } }); } final long endTime = System.currentTimeMillis(); - if (DEBUG) - System.out.println("Cracked RC4 in " + (endTime - startTime) + "ms"); + LOGGER.debug("Cracked RC4 in " + (endTime - startTime) + "ms"); flashPacketHandlers.forEach(FlashPacketHandler::unblock); }).start(); diff --git a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/HabboClientFactory.java b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/HabboClientFactory.java index 48cba93..512c21a 100644 --- a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/HabboClientFactory.java +++ b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/HabboClientFactory.java @@ -3,7 +3,7 @@ package gearth.protocol.memory.habboclient; import gearth.misc.OSValidator; import gearth.protocol.HConnection; import gearth.protocol.memory.habboclient.linux.LinuxHabboClient; -import gearth.protocol.memory.habboclient.macOs.MacOsHabboClient; +import gearth.protocol.memory.habboclient.macos.MacOSHabboClient; import gearth.protocol.memory.habboclient.windows.WindowsHabboClient; /** @@ -15,7 +15,7 @@ public class HabboClientFactory { public static HabboClient get(HConnection connection) { if (OSValidator.isUnix()) return new LinuxHabboClient(connection); if (OSValidator.isWindows()) return new WindowsHabboClient(connection); - if (OSValidator.isMac()) return new MacOsHabboClient(connection); + if (OSValidator.isMac()) return new MacOSHabboClient(connection); // todo use rust if beneficial diff --git a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macOs/MacOsHabboClient.java b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macOs/MacOsHabboClient.java deleted file mode 100644 index 5cdcd0f..0000000 --- a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macOs/MacOsHabboClient.java +++ /dev/null @@ -1,144 +0,0 @@ -package gearth.protocol.memory.habboclient.macOs; - -import gearth.misc.Cacher; -import gearth.protocol.HConnection; -import gearth.protocol.HMessage; -import gearth.protocol.memory.habboclient.HabboClient; -import org.json.JSONArray; -import org.json.JSONObject; - - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; -import java.util.StringJoiner; - -public class MacOsHabboClient extends HabboClient { - - public MacOsHabboClient(HConnection connection) { - super(connection); - - connection.addTrafficListener(0, message -> { - if (message.getDestination() == HMessage.Direction.TOSERVER && message.getPacket().headerId() == PRODUCTION_ID) { - production = message.getPacket().readString(); - } - }); - } - - - private static final String OFFSETS_CACHE_KEY = "RC4Offsets"; - private static final int PRODUCTION_ID = 4000; - private String production = ""; - - @Override - public List getRC4cached() { - List result = new ArrayList<>(); - try { - List possibleResults = readPossibleBytes(true); - - if (possibleResults == null) - return new ArrayList<>(); - - for (String s : possibleResults) - result.add(hexStringToByteArray(s)); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - return result; - } - - private ArrayList readPossibleBytes(boolean useCache) throws IOException, URISyntaxException { - ProcessBuilder pb; - - JSONObject revisionList = (JSONObject) Cacher.get(OFFSETS_CACHE_KEY); - if (revisionList == null) { - Cacher.put(OFFSETS_CACHE_KEY, new JSONObject()); - revisionList = (JSONObject) Cacher.get(OFFSETS_CACHE_KEY); - } - - assert revisionList != null; - JSONArray cachedOffsets; - if (revisionList.has(production)) - cachedOffsets = (JSONArray) revisionList.get(production); - else - cachedOffsets = null; - - StringJoiner joiner = new StringJoiner(" "); - - if (useCache) { - if (cachedOffsets == null) { - return null; - } - - for (Object s : cachedOffsets) { - joiner.add((String)s); - } - } - - String g_mem = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + "/G-Mem"; - if (!useCache) - pb = new ProcessBuilder(g_mem, hConnection.getClientHost() , Integer.toString(hConnection.getClientPort())); - else - pb = new ProcessBuilder(g_mem, hConnection.getClientHost() , Integer.toString(hConnection.getClientPort()), "-c" + joiner.toString()); - - - Process p = pb.start(); - BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); - - String line; - ArrayList possibleData = new ArrayList<>(); - - if (cachedOffsets == null) { - cachedOffsets = new JSONArray(); - } - - - int count = 0; - while((line = reader.readLine()) != null) { - if (line.length() > 1) { - if (!useCache && (count++ % 2 == 0)) { - if (!cachedOffsets.toList().contains(line)) { - cachedOffsets.put(line); - System.out.println("[+] " + line); - } - } - else - possibleData.add(line); - } - } - - revisionList.put(production, cachedOffsets); - Cacher.put(OFFSETS_CACHE_KEY, revisionList); - p.destroy(); - return possibleData; - } - - @Override - public List getRC4possibilities() { - List result = new ArrayList<>(); - try { - ArrayList possibleData = readPossibleBytes(false); - - for (String possibleHexStr : possibleData) { - result.add(hexStringToByteArray(possibleHexStr)); - } - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - 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; - } -} diff --git a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java new file mode 100644 index 0000000..95420e9 --- /dev/null +++ b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java @@ -0,0 +1,104 @@ +package gearth.protocol.memory.habboclient.macos; + +import gearth.misc.StringUtils; +import gearth.protocol.HConnection; +import gearth.protocol.HMessage; +import gearth.protocol.HPacket; +import gearth.protocol.memory.habboclient.HabboClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a {@link HabboClient} implementation for the MacOS operating system. + * + * @author sirjonasxx / dorving (revised) + */ +public class MacOSHabboClient extends HabboClient { + + private static final Logger LOGGER = LoggerFactory.getLogger(MacOSHabboClient.class); + + private static final String G_MEM_EXECUTABLE_FILE_NAME = "/g_mem_mac"; + + /** + * The header id (opcode) of the packet that contains the value for the {@link #production} field. + */ + private static final int PRODUCTION_ID = 4000; + + private String production = ""; + + /** + * Create a new {@link MacOSHabboClient} instance. + * + * @param connection the {@link HConnection connection} with the Habbo server. + */ + public MacOSHabboClient(HConnection connection) { + super(connection); + listenForProductionPacket(connection); + } + + private void listenForProductionPacket(HConnection connection) { + connection.addTrafficListener(0, message -> { + if (message.getDestination() == HMessage.Direction.TOSERVER) { + final HPacket packet = message.getPacket(); + if (packet.headerId() == PRODUCTION_ID) { + production = packet.readString(); + LOGGER.debug("Read production packet from connection {}, set `production` to {}", connection, production); + } + } + }); + } + + @Override + public List getRC4cached() { + return new ArrayList<>(); + } + + + @Override + public List getRC4possibilities() { + final List result = new ArrayList<>(); + try { + for (String possibleHexStr : readPossibleBytes()) + result.add(StringUtils.hexStringToByteArray(possibleHexStr)); + } catch (IOException | URISyntaxException e) { + LOGGER.error("Failed to parse line as hex string", e); + } + return result; + } + + private ArrayList readPossibleBytes() throws IOException, URISyntaxException { + final String pathToGMemExecutable = getPathToGMemExecutable(); + final String clientHost = hConnection.getClientHost(); + final String clientPort = Integer.toString(hConnection.getClientPort()); + LOGGER.debug("Attempting to execute G-Mem executable {} with host {} at port {}", pathToGMemExecutable, clientHost, clientPort); + final Process process = new ProcessBuilder(pathToGMemExecutable, clientHost, clientPort) + .start(); + final ArrayList possibleData = new ArrayList<>(); + try(BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + int count = 0; + String line; + while((line = reader.readLine()) != null) { + if (line.length() > 1 && (count++ % 2 != 0)) + possibleData.add(line); + } + } catch (Exception e) { + LOGGER.error("Failed to execute G-Mem", e); + } finally { + process.destroy(); + } + LOGGER.debug("Read {} from G-Mem output stream", possibleData); + return possibleData; + } + + private String getPathToGMemExecutable() throws URISyntaxException { + return new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + G_MEM_EXECUTABLE_FILE_NAME; + } +} diff --git a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/rust/RustHabboClient.java b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/rust/RustHabboClient.java index b5c88a8..79ba40b 100644 --- a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/rust/RustHabboClient.java +++ b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/rust/RustHabboClient.java @@ -1,5 +1,6 @@ package gearth.protocol.memory.habboclient.rust; +import gearth.misc.StringUtils; import gearth.protocol.HConnection; import gearth.protocol.memory.habboclient.HabboClient; @@ -48,18 +49,9 @@ public class RustHabboClient extends HabboClient { List ret = new ArrayList<>(); for (String possibleHexStr : possibleData) - ret.add(hexStringToByteArray(possibleHexStr)); + ret.add(StringUtils.hexStringToByteArray(possibleHexStr)); 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; - } } diff --git a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/windows/WindowsHabboClient.java b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/windows/WindowsHabboClient.java index 7178b06..32bb362 100644 --- a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/windows/WindowsHabboClient.java +++ b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/windows/WindowsHabboClient.java @@ -1,6 +1,7 @@ package gearth.protocol.memory.habboclient.windows; import gearth.misc.Cacher; +import gearth.misc.StringUtils; import gearth.protocol.HConnection; import gearth.protocol.HMessage; import gearth.protocol.memory.habboclient.HabboClient; @@ -44,7 +45,7 @@ public class WindowsHabboClient extends HabboClient { return new ArrayList<>(); for (String s : possibleResults) - result.add(hexStringToByteArray(s)); + result.add(StringUtils.hexStringToByteArray(s)); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } @@ -124,23 +125,12 @@ public class WindowsHabboClient extends HabboClient { List result = new ArrayList<>(); try { ArrayList possibleData = readPossibleBytes(false); - for (String possibleHexStr : possibleData) { - result.add(hexStringToByteArray(possibleHexStr)); + result.add(StringUtils.hexStringToByteArray(possibleHexStr)); } } catch (IOException | URISyntaxException e) { e.printStackTrace(); } 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; - } } diff --git a/G-Earth/src/main/java/gearth/protocol/packethandler/flash/FlashPacketHandler.java b/G-Earth/src/main/java/gearth/protocol/packethandler/flash/FlashPacketHandler.java index 98b7ffe..e4d2743 100644 --- a/G-Earth/src/main/java/gearth/protocol/packethandler/flash/FlashPacketHandler.java +++ b/G-Earth/src/main/java/gearth/protocol/packethandler/flash/FlashPacketHandler.java @@ -16,7 +16,7 @@ import java.util.List; public abstract class FlashPacketHandler extends PacketHandler { - protected static final boolean DEBUG = false; + protected static final boolean DEBUG = true; private volatile OutputStream out; private volatile boolean isTempBlocked = false;