Initial commit

This commit is contained in:
Michael Wain 2024-05-25 19:07:15 +03:00
commit cd94600651
34 changed files with 5770 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

13
.idea/cody_history.xml generated Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChatHistory">
<chats>
<list>
<chat>
<accountId value="VXNlcjozMDAyODA=" />
<internalId value="eec60712-2317-460c-b295-51e67491362f" />
</chat>
</list>
</chats>
</component>
</project>

10
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/proto" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/target/generated-resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/target/generated-sources/protobuf/java" charset="UTF-8" />
</component>
</project>

13
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,13 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_20" default="true" project-jdk-name="openjdk-20" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

5
login.reg Normal file
View File

@ -0,0 +1,5 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Blizzard Entertainment\Battle.net\Launch Options\WTCG]
"REGION"="EU"
"HBS_TOKENX"="ABC123"

142
pom.xml Normal file
View File

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alterdekim</groupId>
<artifactId>jstud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<exec.mainClass>com.alterdekim.Main</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.58</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.24.4</version>
</dependency>
<dependency>
<groupId>org.ektorp</groupId>
<artifactId>org.ektorp</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.nanohttpd</groupId>
<artifactId>nanohttpd</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<type>maven-plugin</type>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.1</version>
</extension>
</extensions>
<plugins>
<!--<plugin>
<groupId>com.github.os72</groupId>
<artifactId>protoc-jar-maven-plugin</artifactId>
<version>3.11.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<addProtoSources>all</addProtoSources>
<includeMavenTypes>direct</includeMavenTypes>
<optimizeCodegen>false</optimizeCodegen>
<includeStdTypes>true</includeStdTypes>
<protocArtifact>com.google.protobuf:protoc:3.14.0</protocArtifact>
<inputDirectories>
<inputDirectory>${project.basedir}/src/main/proto</inputDirectory>
</inputDirectories>
<includeDirectories>
<includeDirectory>${project.basedir}/src/main/proto</includeDirectory>
</includeDirectories>
</configuration>
</execution>
</executions>
</plugin>-->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.12.2:exe:${os.detected.classifier}</protocArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
com.alterdekim.Main
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

BIN
protoc.exe Normal file

Binary file not shown.

View File

@ -0,0 +1,124 @@
package com.alterdekim;
import com.alterdekim.db.Database;
import com.alterdekim.login.LoginServer;
import com.alterdekim.services.*;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Compute32;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class Connection extends Thread {
/*
All files were merged into protocol.proto
*/
private static final Logger log = LoggerFactory.getLogger(Connection.class);
private final SSLSocket fromClient;
private OutputStream outToClient;
private Map<Integer, Service> services;
private final Database db;
public Connection(SSLSocket socket, Database db) {
this.fromClient = socket;
this.db = db;
this.init();
this.start();
}
public void stopListeningAndDisconnect() {
log.warn("Tried to stopListening");
}
public Map<Integer, Service> getServices() {
return services;
}
public void send(BattleNetPacket bp) throws Exception {
// log.info("Sending response: " + bp.getHeader().getServiceId() + " / " + bp.getHeader().getMethodId());
this.outToClient.write(bp.Encode());
this.outToClient.flush();
}
public void _send( byte[] b ) throws Exception {
this.outToClient.write(b);
this.outToClient.flush();
}
public Database getDb() {
return db;
}
private void init() {
this.services = new HashMap<>();
this.services.put(0, new ConnectionService(""));
this.services.put(1, new AuthService("bnet.protocol.authentication.AuthenticationClient")); // Compute32.Hash("bnet.protocol.authentication.AuthenticationServer")
this.services.put(17, new AccountService("bnet.protocol.account.AccountNotify")); // Compute32.Hash("bnet.protocol.account.AccountService")
this.services.put(4, new PresenceService("bnet.protocol.presence.PresenceService")); // Compute32.Hash("bnet.protocol.presence.PresenceService")
this.services.put(6, new FriendsService("bnet.protocol.friends.FriendsNotify")); // Compute32.Hash("bnet.protocol.friends.FriendsService")
this.services.put(7, new ChannelService("bnet.protocol.channel.Channel")); // Compute32.Hash("bnet.protocol.channel.Channel")
this.services.put(16, new ResourcesService("bnet.protocol.resources.Resources"));
this.services.put(9, new GameUtilitiesService("bnet.protocol.game_utilities.GameUtilities"));
}
private void processPacket( BattleNetPacket packet ) {
try {
Service is = this.services.get(Integer.parseUnsignedInt(Integer.toUnsignedString(packet.getHeader().getServiceId())));
if( is == null ) {
log.error("Can't process weird ServiceId: " + Integer.parseUnsignedInt(Integer.toUnsignedString(packet.getHeader().getServiceId())));
return;
}
log.info("Incoming: " + is.getClass().getSimpleName() + " / " + packet.getHeader().getMethodId() + " (Token: " + packet.getHeader().getToken() + ")");
is.process(packet, this);
} catch ( Exception e ) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
InputStream is = fromClient.getInputStream();
outToClient = fromClient.getOutputStream();
while (true) {
try {
int count;
byte[] buffer = new byte[4096]; // or 4096, or more
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((count = is.read(buffer)) > 0) {
baos.write(buffer, 0, count);
byte[] r = baos.toByteArray();
BattleNetPacket bp = new BattleNetPacket();
int offset = 0;
while( offset < r.length ) {
offset += bp.Decode(r, offset, r.length);
processPacket(bp);
}
baos.reset();
}
baos.close();
} catch (Exception e) {
e.printStackTrace();
break;
}
}
} catch ( Exception e ) {
e.printStackTrace();
}
/*
br.close();
fromClient.close();
*/
}
}

View File

@ -0,0 +1,41 @@
package com.alterdekim;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
new Server(1119).startListening();
/* System.out.println(Util.bytesToHex(exampleProtocol.Test.newBuilder()
.setA(9999)
.setB("testing")
.setC(7777)
.build().toByteArray()));*/
/* Scanner scanner = new Scanner(System.in);
String s = "";
while( (s = scanner.nextLine()) != null ) {
try {
byte[] arr = Util.hexStringToByteArray(s);
int offset = 0;
while( offset < arr.length ) {
BattleNetPacket bp = new BattleNetPacket();
offset += bp.Decode(arr, offset, arr.length);
log.warn( offset + " " + arr.length);
log.info(bp.getHeader().toString());
log.info("Body.Length = " + bp.getBody().length);
log.info(Util.bytesToHex(bp.getBody()));
}
} catch ( Exception e ) {
e.printStackTrace();
}
}*/
}
}

View File

@ -0,0 +1,96 @@
package com.alterdekim;
import com.alterdekim.db.Database;
import com.alterdekim.login.LoginServer;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.IOException;
import java.util.LinkedList;
public class Server implements Runnable {
private static final Logger log = LoggerFactory.getLogger(Server.class);
private SSLServerSocket serverSocket;
private int portNumber;
private Thread acceptThread;
private LinkedList<Connection> connections;
private Database db;
public Server(int port) {
portNumber = port;
connections = new LinkedList<>();
db = new Database("localhost", 5984, "hs_lobby");
try {
//SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
serverSocket = (SSLServerSocket) Util.getSocketFactory(
"test.com.crt",
"test.com.crt",
"test.com.key",
""
).createServerSocket(portNumber,15);
db.start();
} catch (Exception e) {
log.error("Init failed: " + e.getMessage());
}
}
public void startListening() {
acceptThread = new Thread(this);
acceptThread.start();
try {
new LoginServer(8080);
} catch ( Exception e ) {
e.printStackTrace();
}
}
public void stopListening() {
for(Connection c:connections) {
c.stopListeningAndDisconnect();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while(true) {
SSLSocket s = (SSLSocket) serverSocket.accept();
Connection c = new Connection(s, db);
connections.add(c);
log.info("New Connection Established From "+s.getInetAddress().toString());
}
} catch(java.net.SocketException e) {
log.error("Listening thread terminated with exception: " + e.getMessage());
} catch(IOException e) {
log.error(e.getMessage());
}
}
public void removeConnection(Connection c) {
connections.remove(c);
}
public void printConnections() {
log.info("Number of connections "+connections.toString());
for(int i=0; i<connections.size(); i++) {
log.info(connections.toString());
}
}
}

View File

@ -0,0 +1,45 @@
package com.alterdekim.db;
import org.ektorp.CouchDbConnector;
import org.ektorp.CouchDbInstance;
import org.ektorp.http.HttpClient;
import org.ektorp.http.StdHttpClient;
import org.ektorp.impl.StdCouchDbConnector;
import org.ektorp.impl.StdCouchDbInstance;
import org.ektorp.support.DesignDocument;
import org.ektorp.support.DesignDocumentFactory;
import org.ektorp.support.View;
public class Database {
private CouchDbConnector lobbyConnector;
private String host;
private int port;
private String lobby_name;
public Database( String host, int port, String lobby_name ) {
this.host = host;
this.port = port;
this.lobby_name = lobby_name;
}
public void start() throws Exception {
/* HttpClient httpClient = new StdHttpClient.Builder()
.url("http://"+host+":"+port)
.username("admin")
.password("")
.build();
CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector db = new StdCouchDbConnector(lobby_name, dbInstance);
db.createDatabaseIfNotExists();
this.lobbyConnector = db;
DesignDocument dd = new DesignDocument("test");
db.create(dd);*/
}
}

View File

@ -0,0 +1,17 @@
package com.alterdekim.login;
import fi.iki.elonen.NanoHTTPD;
import java.io.IOException;
public class LoginServer extends NanoHTTPD {
public LoginServer(int port) throws IOException {
super(port);
start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
}
@Override
public Response serve(IHTTPSession session) {
return newChunkedResponse(Response.Status.OK, "text/html", Thread.currentThread().getContextClassLoader().getResourceAsStream("login.html"));
}
}

View File

@ -0,0 +1,64 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AccountService extends Service {
private static final Logger log = LoggerFactory.getLogger(AccountService.class);
public AccountService(String export_name) {
super(export_name);
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 30:
// Protocol.GetAccountStateRequest getAccountStateRequest = Protocol.GetAccountStateRequest.parseFrom(packet.getBody());
// log.info(getAccountStateRequest.toString());
Protocol.GetAccountStateResponse getAccountStateResponse = Protocol.GetAccountStateResponse
.newBuilder()
.setState(Protocol.AccountState.newBuilder()
.setAccountLevelInfo(Protocol.AccountLevelInfo.newBuilder()
.setDefaultCurrency(4543826)
.setPreferredRegion(1)
.setCountry("SVK")
.build())
.build())
.setTags(Protocol.AccountFieldTags.newBuilder()
.setAccountLevelInfoTag(-577802125).build())
.build();
Protocol.Header header = Protocol.Header.newBuilder(packet.getHeader())
.setSize(getAccountStateResponse.getSerializedSize())
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, getAccountStateResponse.toByteArray()));
break;
case 34:
Protocol.Header header1 = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(53)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, Util.hexStringToByteArray("12331880B5B9F50E221F0A0D36322E3139372E3234332E383810CBA6011A0A4272617469736C617661280030003800409AE5A1B905")));
break;
default:
log.error("Can't process weird AccountService method: " + packet.getHeader().getMethodId());
break;
}
}
}

View File

@ -0,0 +1,162 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Compute32;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
public class AuthService extends Service {
private static final Logger log = LoggerFactory.getLogger(AuthService.class);
public AuthService(String export_name) {
super(export_name);
}
private void logonRequest( BattleNetPacket packet, Connection conn ) throws Exception {
// Protocol.LogonRequest lr = Protocol.LogonRequest.parseFrom(packet.getBody());
Protocol.Header h = Protocol.Header.newBuilder()
.setServiceId(254)
.setObjectId(0)
.setToken(packet.getHeader().getToken())
.setStatus(0)
.setSize(0)
.build();
conn.send(new BattleNetPacket(h, new byte[0]));
byte[] b = Util.hexStringToByteArray("080110C383A8F4CEBDCC021800");
h = Protocol.Header.newBuilder()
.setServiceId(1)
.setObjectId(0)
.setToken(0)
.setMethodId(12)
.setStatus(0)
.setSize(b.length)
.build();
conn.send(new BattleNetPacket(h, b));
h = Protocol.Header.newBuilder()
.setServiceId(1)
.setObjectId(0)
.setToken(1)
.setMethodId(13)
.setStatus(0)
.setSize(0)
.build();
conn.send(new BattleNetPacket(h, new byte[0]));
//120C7765625F617574685F75726C1A16687474703A2F2F68732F6C6F67696E2F7A2E68746D6C
byte[] us = "http://10.66.66.3:8080".getBytes(StandardCharsets.UTF_8);
byte[] bb = Util.hexStringToByteArray("120C7765625F617574685F75726C1A"+Util.intToHex(us.length)+Util.bytesToHex(us));
h = Protocol.Header.newBuilder()
.setServiceId(8)
.setObjectId(0)
.setToken(2)
.setMethodId(3)
.setStatus(0)
.setSize(bb.length)
.build();
conn.send(new BattleNetPacket(h, bb));
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 1:
logonRequest(packet, conn);
break;
case 4:
Protocol.Header nnh = Protocol.Header.newBuilder()
.setStatus(0)
.setServiceId(254)
.setObjectId(0)
.setToken(packet.getHeader().getToken())
.setSize(0)
.build();
conn.send(new BattleNetPacket(nnh, new byte[0]));
break;
case 7:
Protocol.VerifyWebCredentialsRequest verifyWebCredentialsRequest
= Protocol.VerifyWebCredentialsRequest.parseFrom(packet.getBody());
log.info( new String( verifyWebCredentialsRequest.getWebCredentials().toByteArray() ) );
Protocol.Header h = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(h, new byte[0]));
h = Protocol.Header.newBuilder()
.setServiceId(10)
.setMethodId(1)
.setToken(4)
.setObjectId(0)
.setSize(2)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(h, Util.hexStringToByteArray("0800")));
h = Protocol.Header.newBuilder()
.setServiceId(10)
.setMethodId(1)
.setToken(5)
.setObjectId(0)
.setSize(2)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(h, Util.hexStringToByteArray("0800")));
// THIRD
//Protocol.LogonResult lr = Protocol.LogonResult.parseFrom(Util.hexStringToByteArray("080012120900000000000000011193710E1A000000001A12094743545702000002116739AB040000000022002801280228032806286230023A0F517569726B794F72632332393638384202534B4A40AA15061771938C7790CDA59BD500BF2AA3205912148098F8B68ADA802F1122B2792D90FA2952A338032A03895322DD02C4E2F3CFE6CD72415466B3798C9ADB015000"));
Protocol.LogonResult logonResult = Protocol.LogonResult.newBuilder()
.setErrorCode(0)
.setAccount(Protocol.EntityId.newBuilder().setHigh(72057594037927936L).setLow(437154195L).build())
.addGameAccount(Protocol.EntityId.newBuilder().setHigh(144115198130930503L).setLow(78330215L).build())
.setEmail("")
.addAvailableRegion(1)
.addAvailableRegion(2)
.addAvailableRegion(3)
.addAvailableRegion(6)
.addAvailableRegion(98)
.setConnectedRegion(2)
.setBattleTag("Asmodeus#66666")
.setGeoipCountry("SK")
.build();
h = Protocol.Header.newBuilder()
.setServiceId(1)
.setMethodId(5)
.setToken(6)
.setObjectId(0)
.setSize(logonResult.getSerializedSize())
.setStatus(0)
.build();
conn.send(new BattleNetPacket(h, logonResult.toByteArray()));
break;
default:
log.error("Can't process weird AuthService method: " + packet.getHeader().getMethodId());
break;
}
}
}

View File

@ -0,0 +1,34 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.utils.BattleNetPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ChannelService extends Service {
private static final Logger log = LoggerFactory.getLogger(ChannelService.class);
public ChannelService(String export_name) {
super(export_name);
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 1:
Protocol.CISubscribeRequest ciSubscribeRequest = Protocol.CISubscribeRequest.parseFrom(packet.getBody());
Protocol.CISubscribeResponse ciSubscribeResponse = Protocol.CISubscribeResponse.getDefaultInstance();
Protocol.Header header = Protocol.Header.newBuilder(packet.getHeader())
.setServiceId(254)
.setSize(ciSubscribeResponse.getSerializedSize())
.build();
conn.send(new BattleNetPacket(header, ciSubscribeResponse.toByteArray()));
break;
default:
log.error("Can't process weird ChannelService method: " + packet.getHeader().getMethodId());
break;
}
}
}

View File

@ -0,0 +1,67 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Set;
public class ConnectionService extends Service {
private static final Logger log = LoggerFactory.getLogger(ConnectionService.class);
public ConnectionService(String export_name) {
super(export_name);
}
/*int GameUtilityService = Compute32.Hash("bnet.protocol.game_utilities.GameUtilities");
int GameMasterService = Compute32.Hash("bnet.protocol.game_master.GameMaster");
int NotificationService = Compute32.Hash("bnet.protocol.notification.NotificationService");
int ChannelOwnerService = Compute32.Hash("bnet.protocol.channel.ChannelOwner");
int ChannelInvitationService = Compute32.Hash("bnet.protocol.channel_invitation.ChannelInvitationService");
int ChallengeService = Compute32.Hash("bnet.protocol.challenge.ChallengeService");
int ResourcesService = Compute32.Hash("bnet.protocol.resources.Resources"); */
private void processConnect( BattleNetPacket packet, Connection conn ) throws Exception {
Protocol.ConnectRequest cr = Protocol.ConnectRequest.parseFrom(packet.getBody());
Protocol.BindResponse.Builder b = Protocol.BindResponse.newBuilder();
List<Integer> hashes = cr.getBindRequest().getImportedServiceHashList();
for( Integer hash : hashes ) {
b.addImportedServiceId(hash);
}
List<Protocol.BoundService> bs = cr.getBindRequest().getExportedServiceList();
for( Protocol.BoundService s : bs ) {
Set<Integer> ks = conn.getServices().keySet();
for( Integer c : ks ) {
Service ss = conn.getServices().get(c);
if( ss != null && ss.getSERVICE_HASH() == s.getHash() ) {
ss.setSERVICE_ID(s.getId());
break;
}
}
}
conn._send(Util.hexStringToByteArray("000c08fe011800200028950130000a0c08f4c9ccf30d10c687bcb805120a0889ff5c1092e5a1b9051800220e0a0c0109080a04030507060211102a2e0a2c0d55450000157a72746d1a206ff4fdd5fa5f6d62a278a04403e075d69d734cd4880732dce8edc6a3f528089230a08a95f4cebdcc02422e0a2c0d55450000157a72746d1a20b4bd0f0096a7648de1d19042fb7a79b96c0df48eea3488f498b08ad3d38fb2cc"));
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 1:
processConnect(packet, conn);
break;
case 5:
// FUCK NODATA
break;
default:
log.error("Can't process weird ConnectionService method: " + packet.getHeader().getMethodId());
break;
}
}
}

View File

@ -0,0 +1,65 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FriendsService extends Service {
private static final Logger log = LoggerFactory.getLogger(FriendsService.class);
public FriendsService(String export_name) {
super(export_name);
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 1:
//Protocol.SubscribeToFriendsRequest subscribeToFriendsRequest = Protocol.SubscribeToFriendsRequest.parseFrom(packet.getBody());
if( packet.getHeader().getToken() == 6 ) {
Protocol.SubscribeToFriendsResponse subscribeToFriendsResponse = Protocol.SubscribeToFriendsResponse.newBuilder()
.setMaxFriends(200)
.setMaxReceivedInvitations(200)
.setMaxSentInvitations(200)
.addRole(Protocol.Role.newBuilder()
.setId(1)
.setName("battle_tag_friend")
.build())
.addRole(Protocol.Role.newBuilder()
.setId(2)
.setName("real_id_friend")
.build())
.build();
Protocol.Header header = Protocol.Header.newBuilder()
.setServiceId(254)
.setStatus(0)
.setToken(packet.getHeader().getToken())
.setSize(subscribeToFriendsResponse.getSerializedSize())
.setObjectId(0)
.build();
conn.send(new BattleNetPacket(header, subscribeToFriendsResponse.toByteArray()));
} else if( packet.getHeader().getToken() == 7 ) {
Protocol.Header header = Protocol.Header.newBuilder()
.setServiceId(254)
.setStatus(0)
.setToken(packet.getHeader().getToken())
.setSize(0)
.setObjectId(0)
.build();
conn.send(new BattleNetPacket(header, new byte[0]));
}
break;
default:
log.error("Can't process weird FriendsService method: " + packet.getHeader().getMethodId());
break;
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,211 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.exampleProtocol;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Util;
import com.google.protobuf.AbstractMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
public class PresenceService extends Service {
private static final Logger log = LoggerFactory.getLogger(PresenceService.class);
public PresenceService(String export_name) {
super(export_name);
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 1:
Protocol.SubscribeRequest subscribeRequest = Protocol.SubscribeRequest.parseFrom(packet.getBody());
Protocol.Header header = Protocol.Header.newBuilder(packet.getHeader())
.setServiceId(254)
.setSize(0)
.setObjectId(0)
.setToken(packet.getHeader().getToken())
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, new byte[0]));
if( subscribeRequest.getObjectId() == 1 ) {
byte[] nickname = "Asmodeus#66666".getBytes(StandardCharsets.US_ASCII);
// byte[] bb = Util.hexStringToByteArray("1A"+Util.intToHex(98+nickname.length)+"AA06"+Util.intToHex(95+nickname.length)+"0A120900000000000000011193710E1A0000000012190A170A0A08CE84011001180620001209189AB1D8B499BCCC02121A0A180A0A08CE8401100118012000120A2A086A6F686E20626F6E12210A1F0A0A08CE840110011804200012102A"+Util.intToHex(nickname.length)+Util.bytesToHex(nickname));
byte[] bb = Util.hexStringToByteArray("1A71AA066E0A120900000000000000011193710E1A0000000012190A170A0A08CE84011001180620001209189AB1D8B499BCCC02121A0A180A0A08CE8401100118012000120A2A086A6F686E20626F6E12210A1F0A0A08CE840110011804200012"+Util.intToHex(nickname.length+2)+"2A"+Util.intToHex(nickname.length)+Util.bytesToHex(nickname));
bb[1] = (byte) (98 + nickname.length);
bb[4] = (byte) (95 + nickname.length);
bb[81] = (byte) (18 + nickname.length);
header = Protocol.Header.newBuilder(packet.getHeader())
.setServiceId(5)
.setMethodId(1)
.setSize(bb.length)
.setObjectId(1)
.setToken(7)
.setStatus(0)
.build();
// FIRST
/*Protocol.AddNotification addNotification = Protocol.AddNotification.parseFrom(Util.hexStringToByteArray("1A71AA066E0A120900000000000000011193710E1A0000000012190A170A0A08CE84011001180620001209189AB1D8B499BCCC02121A0A180A0A08CE8401100118012000120A2A086A6F686E20626F6E12210A1F0A0A08CE840110011804200012112A0F517569726B794F7263233239363838"));
System.out.println(addNotification);*/
System.out.println(Util.bytesToHex(bb));
conn.send(new BattleNetPacket(header, bb));
} else if( subscribeRequest.getObjectId() == 2 ) {
byte[] nickname = "Asmodeus#66666".getBytes(StandardCharsets.US_ASCII);
byte[] bb = Util.hexStringToByteArray("1ADB01AA06D7010A12094743545702000002116739AB040000000012210A1F0A0A08CE840110021805200012"+Util.intToHex(nickname.length+2)+"2A"+Util.intToHex(nickname.length)+Util.bytesToHex(nickname)+"12240A220A0A08CE8401100218072000121452120900000000000000011193710E1A0000000012190A170A0A08CE84011002180420001209189AB1D8B499BCCC0212120A100A0A08CE84011002180C20001202100012120A100A0A08CE84011002180120001202100012160A140A0A08CE84011002180320001206420457544347121D0A1B0A0A08CE8401100218062000120D2A0B3433373135343139352331");
bb[1] = (byte) (204 + nickname.length);
bb[5] = (byte) (200 + nickname.length);
bb[28] = (byte) (18 + nickname.length);
bb[30] = (byte) (16 + nickname.length);
header = Protocol.Header.newBuilder(packet.getHeader())
.setServiceId(5)
.setMethodId(1)
.setSize(bb.length)
.setObjectId(2)
.setToken(8)
.setStatus(0)
.build();
// SECOND
/*Protocol.AddNotification addNotification = Protocol.AddNotification.parseFrom(Util.hexStringToByteArray("1ADB01AA06D7010A12094743545702000002116739AB040000000012210A1F0A0A08CE840110021805200012112A0F517569726B794F726323323936383812240A220A0A08CE8401100218072000121452120900000000000000011193710E1A0000000012190A170A0A08CE84011002180420001209189AB1D8B499BCCC0212120A100A0A08CE84011002180C20001202100012120A100A0A08CE84011002180120001202100012160A140A0A08CE84011002180320001206420457544347121D0A1B0A0A08CE8401100218062000120D2A0B3433373135343139352331"));
System.out.println(addNotification);*/
conn.send(new BattleNetPacket(header, bb));
header = Protocol.Header.newBuilder(packet.getHeader())
.setServiceId(5)
.setMethodId(6)
.setSize(68)
.setObjectId(2)
.setToken(10)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, Util.hexStringToByteArray("1242AA063F0A12094743545702000002116739AB040000000012170A150A0808CE840110021804120918F182EAF5CEBDCC0212100A0E0A0808CE84011002180112021001")));
}
break;
case 3:
if( packet.getHeader().getToken() == 12 ) {
/* Protocol.Header header1 = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, new byte[0]));*/
conn._send(Util.hexStringToByteArray("000c08fe011800200028950130000a0c08f4c9ccf30d10c687bcb805120a0889ff5c1092e5a1b9051800220e0a0c0109080a04030507060211102a2e0a2c0d55450000157a72746d1a206ff4fdd5fa5f6d62a278a04403e075d69d734cd4880732dce8edc6a3f528089230a08a95f4cebdcc02422e0a2c0d55450000157a72746d1a20b4bd0f0096a7648de1d19042fb7a79b96c0df48eea3488f498b08ad3d38fb2cc"));
} else if( packet.getHeader().getToken() == 13 ) {
Protocol.Header header1 = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, new byte[0]));
header1 = Protocol.Header.newBuilder()
.setServiceId(5)
.setMethodId(6)
.setToken(14)
.setObjectId(2)
.setSize(Util.hexStringToByteArray("1233AA06300A12094743545702000002116739AB0400000000121A0A180A0A08C786D1BA0510021813120A2A083833383836303830").length)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, Util.hexStringToByteArray("1233AA06300A12094743545702000002116739AB0400000000121A0A180A0A08C786D1BA0510021813120A2A083833383836303830")));
} else if( packet.getHeader().getToken() == 18 ) {
Protocol.Header header1 = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, new byte[0]));
byte[] b = Util.hexStringToByteArray("122BAA06280A12094743545702000002116739AB040000000012120A100A0A08C786D1BA051002180112021000");
header1 = Protocol.Header.newBuilder()
.setServiceId(5)
.setMethodId(6)
.setToken(17)
.setObjectId(2)
.setSize(b.length)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, b));
b = Util.hexStringToByteArray("0A120900000000000000021100000000000000001212094743545702000002116739AB04000000001A1C575443472E5574696C4E6F74696669636174696F6E4D65737361676522130A0C6D6573736167655F74797065120318CA0222140A0C667261676D656E745F30303012043202080122120A0C6D6573736167655F73697A65120218022A1209000000000000000111000000000000000032120900000000000000011193710E1A000000003A004A0A0889FF5C1092E5A1B90552150A050D93710E1A120C0D6739AB0415474354571802");
header = Protocol.Header.newBuilder()
.setServiceId(4)
.setMethodId(1)
.setToken(18)
.setObjectId(0)
.setSize(b.length)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, b));
} else if( packet.getHeader().getToken() == 26 ) {
Protocol.Header header1 = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, new byte[0]));
byte[] b = Util.hexStringToByteArray("1231AA062E0A12094743545702000002116739AB040000000012180A160A0A08C786D1BA051002181212083206190000190000");
header = Protocol.Header.newBuilder()
.setServiceId(5)
.setMethodId(6)
.setToken(58)
.setObjectId(2)
.setSize(b.length)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, b));
} else if( packet.getHeader().getToken() == 32 ) {
byte[] b = Util.hexStringToByteArray("0D5545000015737368001A20BEC5292231D7686AF00CE64E0C58CC6E360EA950AAFFAC6A114F03A958E275F3");
Protocol.Header header1 = Protocol.Header.newBuilder()
.setServiceId(254)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.setSize(b.length)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header1, b));
b = Util.hexStringToByteArray("1230AA062D0A12094743545702000002116739AB040000000012170A150A0A08C786D1BA0510021811120732050103000000");
header = Protocol.Header.newBuilder()
.setServiceId(5)
.setMethodId(6)
.setToken(63)
.setObjectId(2)
.setSize(b.length)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, b));
}
break;
default:
log.error("Can't process weird PresenceService method: " + packet.getHeader().getMethodId());
break;
}
}
}

View File

@ -0,0 +1,44 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Util;
import com.google.protobuf.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ResourcesService extends Service {
private static final Logger log = LoggerFactory.getLogger(ResourcesService.class);
public ResourcesService(String export_name) {
super(export_name);
}
@Override
public void process(BattleNetPacket packet, Connection conn) throws Exception {
switch (packet.getHeader().getMethodId()) {
case 1:
// Protocol.ContentHandleRequest contentHandleRequest = Protocol.ContentHandleRequest.parseFrom(packet.getBody());
Protocol.ContentHandle contentHandle = Protocol.ContentHandle.newBuilder()
.setRegion(17749)
.setUsage(1885762681)
.setHash(ByteString.copyFrom(Util.hexStringToByteArray("5b2f9b39434a1c4e3f970a76c1e97a8548c95da2ad52a6d37cf9d793dedd887d")))
.build();
Protocol.Header header = Protocol.Header.newBuilder()
.setServiceId(254)
.setSize(contentHandle.getSerializedSize())
.setStatus(0)
.setToken(packet.getHeader().getToken())
.setObjectId(0)
.build();
conn.send(new BattleNetPacket(header, contentHandle.toByteArray()));
break;
default:
log.error("Can't process weird ResourcesService method: " + packet.getHeader().getMethodId());
break;
}
}
}

View File

@ -0,0 +1,29 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.utils.BattleNetPacket;
import com.alterdekim.utils.Compute32;
public abstract class Service {
private final int SERVICE_HASH;
private int SERVICE_ID;
public Service( String export_name ) {
this.SERVICE_HASH = Compute32.Hash(export_name);
}
public int getSERVICEID() {
return this.SERVICE_ID;
}
public void setSERVICE_ID(int SERVICE_ID) {
this.SERVICE_ID = SERVICE_ID;
}
public int getSERVICE_HASH() {
return SERVICE_HASH;
}
public abstract void process(BattleNetPacket packet, Connection conn) throws Exception;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
package com.alterdekim.utils;
import com.alterdekim.Protocol;
import java.io.ByteArrayOutputStream;
public class BattleNetPacket {
private int headerSize = -1;
private int bodySize = -1;
private Protocol.Header header;
private byte[] body;
public Protocol.Header getHeader() {
return header;
}
public byte[] getBody() {
return body;
}
public BattleNetPacket(Protocol.Header header, byte[] body) {
this.header = header;
this.body = body;
}
public BattleNetPacket() {
this.header = null;
this.body = null;
}
public void setHeader(Protocol.Header header) {
this.header = header;
}
public void setBody(byte[] body) {
this.body = body;
}
public int Decode(byte[] bytes, int offset, int available) throws Exception {
int num = 0;
if (this.headerSize < 0) {
if (available < 2) {
return num;
}
this.headerSize = ((int)bytes[offset] << 8) + (int)bytes[offset + 1];
available -= 2;
num += 2;
offset += 2;
}
if (this.header == null) {
if (available < this.headerSize) {
return num;
}
this.header = Protocol.Header.getDefaultInstance();
byte[] s = new byte[this.headerSize];
System.arraycopy(bytes, offset, s, 0, this.headerSize);
this.header = Protocol.Header.parseFrom(s);
this.bodySize = ((!this.header.hasSize()) ? 0 : this.header.getSize()); // something with unsigned integers (debug, if needed)
available -= this.headerSize;
num += this.headerSize;
offset += this.headerSize;
}
if (this.body == null) {
if (available < this.bodySize) {
return num;
}
byte[] destinationArray = new byte[this.bodySize];
System.arraycopy(bytes, offset, destinationArray, 0, this.bodySize);
this.body = destinationArray;
num += this.bodySize;
}
return num;
}
public byte[] Encode() throws Exception {
int serializedSize = this.header.getSerializedSize();
int serializedSize2 = this.body.length;
byte[] array = new byte[2 + serializedSize + serializedSize2];
array[0] = (byte)(serializedSize >> 8 & 255);
array[1] = (byte)(serializedSize & 255);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.header.writeTo(baos);
System.arraycopy(baos.toByteArray(), 0, array, 2, serializedSize);
System.arraycopy(body, 0, array, 2 + serializedSize, serializedSize2);
baos.close();
return array;
}
}

View File

@ -0,0 +1,12 @@
package com.alterdekim.utils;
public class Compute32 {
public static int Hash(String str) {
int num = Integer.parseUnsignedInt("2166136261");
for( char b : str.toCharArray() ) {
num ^= b;
num *= Integer.parseUnsignedInt("16777619");
}
return num;
}
}

View File

@ -0,0 +1,145 @@
package com.alterdekim.utils;
import com.google.protobuf.MessageOrBuilder;
import com.google.protobuf.util.JsonFormat;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import javax.net.ssl.*;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
public class Util {
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static SSLServerSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile,
final String password) {
try {
/**
* Add BouncyCastle as a Security Provider
*/
Security.addProvider(new BouncyCastleProvider());
JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter().setProvider("BC");
/**
* Load Certificate Authority (CA) certificate
*/
PEMParser reader = new PEMParser(new FileReader(caCrtFile));
X509CertificateHolder caCertHolder = (X509CertificateHolder) reader.readObject();
reader.close();
X509Certificate caCert = certificateConverter.getCertificate(caCertHolder);
/**
* Load client certificate
*/
reader = new PEMParser(new FileReader(crtFile));
X509CertificateHolder certHolder = (X509CertificateHolder) reader.readObject();
reader.close();
X509Certificate cert = certificateConverter.getCertificate(certHolder);
/**
* Load client private key
*/
reader = new PEMParser(new FileReader(keyFile));
Object keyObject = reader.readObject();
reader.close();
PEMDecryptorProvider provider = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter().setProvider("BC");
KeyPair key;
if (keyObject instanceof PEMEncryptedKeyPair) {
key = keyConverter.getKeyPair(((PEMEncryptedKeyPair) keyObject).decryptKeyPair(provider));
} else {
key = keyConverter.getKeyPair((PEMKeyPair) keyObject);
}
/**
* CA certificate is used to authenticate server
*/
KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
caKeyStore.load(null, null);
caKeyStore.setCertificateEntry("ca-certificate", caCert);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(caKeyStore);
/**
* Client key and certificates are sent to server so it can authenticate the client
*/
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
clientKeyStore.load(null, null);
clientKeyStore.setCertificateEntry("certificate", cert);
clientKeyStore.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),
new Certificate[]{cert});
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, password.toCharArray());
/**
* Create SSL socket factory
*/
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
/**
* Return the newly created socket factory object
*/
return context.getServerSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public 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;
}
public static String intToHex(int i) {
String s = Integer.toHexString(i).toUpperCase();
return s.length() % 2 == 0 ? s : "0" + s;
}
public static String prototoJson(MessageOrBuilder messageOrBuilder) throws IOException {
return JsonFormat.printer().print(messageOrBuilder);
}
}

View File

@ -0,0 +1,11 @@
syntax = "proto2";
package com.example;
option java_package = "com.alterdekim";
option java_outer_classname = "exampleProtocol";
message Test {
optional int32 a = 1;
optional fixed32 c = 3;
optional string b = 2;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/purecss@3.0.0/build/pure-min.css" integrity="sha384-X38yfunGUhNzHpBaEBsWLO+A0HDYOQi8ufWDkZ0k9e0eXz/tH3II7uKZ9msv++Ls" crossorigin="anonymous">
</head>
<body>
<form class="pure-form pure-form-stacked" method="get" action="localhost:0">
<fieldset>
<legend>Hearthstone (mod) Sign-in:</legend>
<label for="stacked-email">Login</label>
<input type="hidden" value="ABCDEFGHIJKLMNOPQRSTU111111222" name="ST">
<input type="text" id="stacked-email" placeholder="Login" name="login" />
<label for="stacked-password">Password</label>
<input type="password" id="stacked-password" placeholder="Password" name="pwd" />
<label for="stacked-remember" class="pure-checkbox">
<input type="checkbox" id="stacked-remember" /> Remember me
</label>
<button type="submit" name="submit" class="pure-button pure-button-primary">Sign in</button>
</fieldset>
</form>
</body>
</html>

13
test.com.crt Normal file
View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICBjCCAW8CFGXq81zzufsv/8Wkwgy/je2BgVXLMA0GCSqGSIb3DQEBCwUAMEIx
CzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl
ZmF1bHQgQ29tcGFueSBMdGQwHhcNMjMwOTIzMTQwNDU3WhcNMjQwOTIyMTQwNDU3
WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQK
DBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQCrNn3o78dD0H1Trkv6J5e4KD0dkMjC/Pdfjx2TwRN+vGOEwrEjrXLBscJ7pK8D
eCkSmF0WFOCxF4QLfWKOtyZtYh4aPcjU8AdrIPhejwjnW1N15yqFhufZJ3WnYi83
jm4MErcYgBlqWim+Hc80af2LFo+1KR5oj595O49IhAXNEwIDAQABMA0GCSqGSIb3
DQEBCwUAA4GBAGt4DEfFeStgfqL6MdHzANGe3oXIy1JsjyK6L7wCUoGhFsAo62lz
eNUaU6oQr1J94AQ5eVsrwVc8QQ0j0XsBhdWbT9xswedcEMsbDbZGNNEC2eaASg3Z
BLR5Y0VUAZqbxJONjUUqjNkbhMnEG8nOzh/6Vm1iGVC62US3n9hJ4HtK
-----END CERTIFICATE-----

11
test.com.csr Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBgTCB6wIBADBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5
MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQCrNn3o78dD0H1Trkv6J5e4KD0dkMjC/Pdfjx2TwRN+vGOEwrEj
rXLBscJ7pK8DeCkSmF0WFOCxF4QLfWKOtyZtYh4aPcjU8AdrIPhejwjnW1N15yqF
hufZJ3WnYi83jm4MErcYgBlqWim+Hc80af2LFo+1KR5oj595O49IhAXNEwIDAQAB
oAAwDQYJKoZIhvcNAQELBQADgYEApgEuapwv8MeuwfVDF1niUTB3WGe+0TLQxj55
x+niQK7c3n/fgQkSsg4qI0HHkgGIFQvfXWr1vZgTL3cefeKFx1av9lTP32wIgo/Y
GEvV2Z5ZnCpkDK3OZdMl56CkIshZ8CbTP8hjxmc1trpIrV+l304cz1KY5KramaTe
CnTaPUs=
-----END CERTIFICATE REQUEST-----

15
test.com.key Normal file
View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCrNn3o78dD0H1Trkv6J5e4KD0dkMjC/Pdfjx2TwRN+vGOEwrEj
rXLBscJ7pK8DeCkSmF0WFOCxF4QLfWKOtyZtYh4aPcjU8AdrIPhejwjnW1N15yqF
hufZJ3WnYi83jm4MErcYgBlqWim+Hc80af2LFo+1KR5oj595O49IhAXNEwIDAQAB
AoGAUo/FabVuvqnkNZ0gMDI1fG2TAxXVagm4dFE8Lwr1DrFjwBpud0jlxLemlB8W
8jJYhAoLIWHR9DPlzfCZvT5efajcx3jAueqRzvBwCZucTaiLyA5uH4suUf0QR844
2k6o3Q1PvECX9b3VgcbFbv8XNT/fqOiO2lkqOupjLWQNvqkCQQDTqfZL5FycZYt0
HGOh5QFKNNRGe0wDUpAYru22MIsN8Ah3DulP2Ac4dbUCNFlgDGEgdnHqkdh0Aku5
g+5wpdmnAkEAzxNtBfSuinmT5rSDohcAIq+iKy9whaI4ctbrUuZ1CJ6lLdtA3oUK
NMDtNy92C7K9HUHZEcFYtVtR8GN4ii8GtQJAYXp2yYDD/eruDG0+nUKAE5K86DDE
Uwtk/VkidLNqduLCo0IkxPaybJgY4okFWCybVn31/JdqXhLomOlfmFVpJQJAB5B0
GRWZEqHiTzkk3dTtQlccG2u+NoN4gGltazfT6p6w9f3eXsKJXuf1QmDPdRnwYpM3
NLjVXrqZQajAjHuvSQJAZaxQVSuZUtzbrBFMn6cRJp/5e5fEAf/zEa1K6qamr1CZ
gC21NpK8IvyPi+7jTO9sERwGrpoD32dIkyb8Wf21ZQ==
-----END RSA PRIVATE KEY-----

28
test.com.pem Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCrNn3o78dD0H1Trkv6J5e4KD0dkMjC/Pdfjx2TwRN+vGOEwrEj
rXLBscJ7pK8DeCkSmF0WFOCxF4QLfWKOtyZtYh4aPcjU8AdrIPhejwjnW1N15yqF
hufZJ3WnYi83jm4MErcYgBlqWim+Hc80af2LFo+1KR5oj595O49IhAXNEwIDAQAB
AoGAUo/FabVuvqnkNZ0gMDI1fG2TAxXVagm4dFE8Lwr1DrFjwBpud0jlxLemlB8W
8jJYhAoLIWHR9DPlzfCZvT5efajcx3jAueqRzvBwCZucTaiLyA5uH4suUf0QR844
2k6o3Q1PvECX9b3VgcbFbv8XNT/fqOiO2lkqOupjLWQNvqkCQQDTqfZL5FycZYt0
HGOh5QFKNNRGe0wDUpAYru22MIsN8Ah3DulP2Ac4dbUCNFlgDGEgdnHqkdh0Aku5
g+5wpdmnAkEAzxNtBfSuinmT5rSDohcAIq+iKy9whaI4ctbrUuZ1CJ6lLdtA3oUK
NMDtNy92C7K9HUHZEcFYtVtR8GN4ii8GtQJAYXp2yYDD/eruDG0+nUKAE5K86DDE
Uwtk/VkidLNqduLCo0IkxPaybJgY4okFWCybVn31/JdqXhLomOlfmFVpJQJAB5B0
GRWZEqHiTzkk3dTtQlccG2u+NoN4gGltazfT6p6w9f3eXsKJXuf1QmDPdRnwYpM3
NLjVXrqZQajAjHuvSQJAZaxQVSuZUtzbrBFMn6cRJp/5e5fEAf/zEa1K6qamr1CZ
gC21NpK8IvyPi+7jTO9sERwGrpoD32dIkyb8Wf21ZQ==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICBjCCAW8CFGXq81zzufsv/8Wkwgy/je2BgVXLMA0GCSqGSIb3DQEBCwUAMEIx
CzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl
ZmF1bHQgQ29tcGFueSBMdGQwHhcNMjMwOTIzMTQwNDU3WhcNMjQwOTIyMTQwNDU3
WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQK
DBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQCrNn3o78dD0H1Trkv6J5e4KD0dkMjC/Pdfjx2TwRN+vGOEwrEjrXLBscJ7pK8D
eCkSmF0WFOCxF4QLfWKOtyZtYh4aPcjU8AdrIPhejwjnW1N15yqFhufZJ3WnYi83
jm4MErcYgBlqWim+Hc80af2LFo+1KR5oj595O49IhAXNEwIDAQABMA0GCSqGSIb3
DQEBCwUAA4GBAGt4DEfFeStgfqL6MdHzANGe3oXIy1JsjyK6L7wCUoGhFsAo62lz
eNUaU6oQr1J94AQ5eVsrwVc8QQ0j0XsBhdWbT9xswedcEMsbDbZGNNEC2eaASg3Z
BLR5Y0VUAZqbxJONjUUqjNkbhMnEG8nOzh/6Vm1iGVC62US3n9hJ4HtK
-----END CERTIFICATE-----