diff --git a/.idea/artifacts/G_Earth2.xml b/.idea/artifacts/G_Earth2.xml
new file mode 100644
index 0000000..9d4fe51
--- /dev/null
+++ b/.idea/artifacts/G_Earth2.xml
@@ -0,0 +1,20 @@
+
+
+ $PROJECT_DIR$/out/artifacts/G_Earth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..0548357
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..1ebdf36
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..712c2b5
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,1248 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Memor
+ 256
+ memory maps
+ print
+ send
+ sendtostream
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project
+
+
+ true
+
+
+
+ DIRECTORY
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1522695209780
+
+
+ 1522695209780
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/src/main/protocol/memory/Rc4Obtainer.java
+ 28
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ G-Earth2
+
+
+
+
+
+
+
+
+
+
+
+ No facets are configured
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
+
+
+
+
+
+
+
+
+
+
+ G-Earth2
+
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/G-Earth2.iml b/G-Earth2.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/G-Earth2.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/out/artifacts/G_Earth/G_Earth.html b/out/artifacts/G_Earth/G_Earth.html
new file mode 100644
index 0000000..83d886b
--- /dev/null
+++ b/out/artifacts/G_Earth/G_Earth.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+Test page for G-Earth2
+ Webstart: click to launch this app as webstart
+
+
+
+
diff --git a/out/artifacts/G_Earth/G_Earth.jar b/out/artifacts/G_Earth/G_Earth.jar
new file mode 100644
index 0000000..7416dac
Binary files /dev/null and b/out/artifacts/G_Earth/G_Earth.jar differ
diff --git a/out/artifacts/G_Earth/G_Earth.jnlp b/out/artifacts/G_Earth/G_Earth.jnlp
new file mode 100644
index 0000000..92bd616
--- /dev/null
+++ b/out/artifacts/G_Earth/G_Earth.jnlp
@@ -0,0 +1,15 @@
+
+
+
+ G-Earth
+ Unknown
+ G-Earth2
+
+
+
+
+
+
+
+
+
diff --git a/out/production/G-Earth2/main/Main.class b/out/production/G-Earth2/main/Main.class
new file mode 100644
index 0000000..5aaa3d0
Binary files /dev/null and b/out/production/G-Earth2/main/Main.class differ
diff --git a/out/production/G-Earth2/main/OSValidator.class b/out/production/G-Earth2/main/OSValidator.class
new file mode 100644
index 0000000..8975ffe
Binary files /dev/null and b/out/production/G-Earth2/main/OSValidator.class differ
diff --git a/out/production/G-Earth2/main/irrelevant/Timer.class b/out/production/G-Earth2/main/irrelevant/Timer.class
new file mode 100644
index 0000000..7864cd1
Binary files /dev/null and b/out/production/G-Earth2/main/irrelevant/Timer.class differ
diff --git a/out/production/G-Earth2/main/protocol/HConnection$State.class b/out/production/G-Earth2/main/protocol/HConnection$State.class
new file mode 100644
index 0000000..552be5b
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/HConnection$State.class differ
diff --git a/out/production/G-Earth2/main/protocol/HConnection.class b/out/production/G-Earth2/main/protocol/HConnection.class
new file mode 100644
index 0000000..cf1b3ff
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/HConnection.class differ
diff --git a/out/production/G-Earth2/main/protocol/HMessage$Side.class b/out/production/G-Earth2/main/protocol/HMessage$Side.class
new file mode 100644
index 0000000..a449dcc
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/HMessage$Side.class differ
diff --git a/out/production/G-Earth2/main/protocol/HMessage.class b/out/production/G-Earth2/main/protocol/HMessage.class
new file mode 100644
index 0000000..1048185
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/HMessage.class differ
diff --git a/out/production/G-Earth2/main/protocol/HPacket.class b/out/production/G-Earth2/main/protocol/HPacket.class
new file mode 100644
index 0000000..8b6fa9f
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/HPacket.class differ
diff --git a/out/production/G-Earth2/main/protocol/StateChangeListener.class b/out/production/G-Earth2/main/protocol/StateChangeListener.class
new file mode 100644
index 0000000..fbb7e8d
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/StateChangeListener.class differ
diff --git a/out/production/G-Earth2/main/protocol/TrafficListener.class b/out/production/G-Earth2/main/protocol/TrafficListener.class
new file mode 100644
index 0000000..efcc262
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/TrafficListener.class differ
diff --git a/out/production/G-Earth2/main/protocol/crypto/RC4.class b/out/production/G-Earth2/main/protocol/crypto/RC4.class
new file mode 100644
index 0000000..f9e4168
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/crypto/RC4.class differ
diff --git a/out/production/G-Earth2/main/protocol/memory/FlashClient.class b/out/production/G-Earth2/main/protocol/memory/FlashClient.class
new file mode 100644
index 0000000..00d3474
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/memory/FlashClient.class differ
diff --git a/out/production/G-Earth2/main/protocol/memory/MemorySnippet.class b/out/production/G-Earth2/main/protocol/memory/MemorySnippet.class
new file mode 100644
index 0000000..46d3eaf
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/memory/MemorySnippet.class differ
diff --git a/out/production/G-Earth2/main/protocol/memory/MemoryUtils.class b/out/production/G-Earth2/main/protocol/memory/MemoryUtils.class
new file mode 100644
index 0000000..fe37b46
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/memory/MemoryUtils.class differ
diff --git a/out/production/G-Earth2/main/protocol/memory/Rc4Obtainer.class b/out/production/G-Earth2/main/protocol/memory/Rc4Obtainer.class
new file mode 100644
index 0000000..12b2f39
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/memory/Rc4Obtainer.class differ
diff --git a/out/production/G-Earth2/main/protocol/packethandler/BufferListener.class b/out/production/G-Earth2/main/protocol/packethandler/BufferListener.class
new file mode 100644
index 0000000..9a3d35d
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/packethandler/BufferListener.class differ
diff --git a/out/production/G-Earth2/main/protocol/packethandler/Handler.class b/out/production/G-Earth2/main/protocol/packethandler/Handler.class
new file mode 100644
index 0000000..d162727
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/packethandler/Handler.class differ
diff --git a/out/production/G-Earth2/main/protocol/packethandler/IncomingHandler.class b/out/production/G-Earth2/main/protocol/packethandler/IncomingHandler.class
new file mode 100644
index 0000000..f7407a7
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/packethandler/IncomingHandler.class differ
diff --git a/out/production/G-Earth2/main/protocol/packethandler/OutgoingHandler.class b/out/production/G-Earth2/main/protocol/packethandler/OutgoingHandler.class
new file mode 100644
index 0000000..444e331
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/packethandler/OutgoingHandler.class differ
diff --git a/out/production/G-Earth2/main/protocol/packethandler/PayloadBuffer.class b/out/production/G-Earth2/main/protocol/packethandler/PayloadBuffer.class
new file mode 100644
index 0000000..a564b77
Binary files /dev/null and b/out/production/G-Earth2/main/protocol/packethandler/PayloadBuffer.class differ
diff --git a/out/production/G-Earth2/main/ui/G-Earth.fxml b/out/production/G-Earth2/main/ui/G-Earth.fxml
new file mode 100644
index 0000000..2dea4ee
--- /dev/null
+++ b/out/production/G-Earth2/main/ui/G-Earth.fxml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/out/production/G-Earth2/main/ui/GEarthController.class b/out/production/G-Earth2/main/ui/GEarthController.class
new file mode 100644
index 0000000..a22f2d0
Binary files /dev/null and b/out/production/G-Earth2/main/ui/GEarthController.class differ
diff --git a/out/production/G-Earth2/main/ui/SubForm.class b/out/production/G-Earth2/main/ui/SubForm.class
new file mode 100644
index 0000000..ec75b78
Binary files /dev/null and b/out/production/G-Earth2/main/ui/SubForm.class differ
diff --git a/out/production/G-Earth2/main/ui/bootstrap3.css b/out/production/G-Earth2/main/ui/bootstrap3.css
new file mode 100644
index 0000000..a79da42
--- /dev/null
+++ b/out/production/G-Earth2/main/ui/bootstrap3.css
@@ -0,0 +1,893 @@
+.root {
+ -fx-body-color : #F5F5F5;
+ -fx-outer-border : #cecece;
+}
+.button,.menu-button,.toggle-button,.split-menu-button {
+ -fx-font-size: 14;
+ -fx-background-radius: 4;
+ -fx-border-radius: 4;
+ -fx-pref-height: 30;
+ -fx-min-width: 30;
+}
+.button,.menu-button,.split-menu-button,.toggle-button,.number-button {
+ -fx-background-insets: 0, 0, -1, 0;
+}
+
+.split-menu-button > .label {
+ -fx-border-radius: 4 0 0 4;
+ -fx-background-radius: 3 0 0 3;
+}
+
+.split-menu-button > .arrow-button {
+ -fx-border-radius: 0 4 4 0;
+ -fx-background-radius: 0 3 3 0;
+}
+
+.lg {
+ -fx-min-height: 46;
+ -fx-max-height: 46;
+ -fx-font-size: 18;
+}
+
+.sm {
+ -fx-min-height: 30;
+ -fx-max-height: 30;
+}
+
+.xs {
+ -fx-min-height: 22;
+ -fx-max-height: 22;
+ -fx-font-size: 10;
+}
+
+.primary .arrow,
+.success .arrow,
+.info .arrow,
+.warning .arrow,
+.danger .arrow {
+ -fx-background-color: transparent, white;
+}
+
+.primary > .label,
+.success > .label,
+.info > .label,
+.warning > .label,
+.danger > .label {
+ -fx-text-fill: white;
+}
+
+.action-btn {
+ -fx-min-width: 80;
+}
+
+/*positions*/
+/*first*/
+.button.first, .menu-button.first, .toggle-button.first, .text-field.first, .text-area.first {
+ -fx-border-radius: 4 0 0 4;
+ -fx-background-radius: 4 0 0 4;
+}
+
+.split-menu-button.first > .arrow-button, .split-menu-button.middle > .arrow-button {
+ -fx-border-radius: 0;
+ -fx-background-radius: 0;
+}
+
+VBox > .button.first,
+VBox > .menu-button.first,
+VBox > .toggle-button.first,
+VBox > .split-menu-button.first,
+VBox > .text-field.first,
+VBox > .text-area.first {
+ -fx-border-radius: 4 4 0 0;
+ -fx-background-radius: 4 4 0 0;
+}
+
+VBox > .split-menu-button.first > .label {
+ -fx-border-radius: 4 0 0 0;
+ -fx-background-radius: 3 0 0 0;
+}
+VBox > .split-menu-button.first > .arrow-button {
+ -fx-border-radius: 0 4 0 0;
+ -fx-background-radius: 0 3 0 0;
+}
+/*middle*/
+.middle {
+ -fx-border-radius: 0;
+ -fx-background-radius: 0;
+}
+
+/*last*/
+.split-menu-button.middle > .label, .split-menu-button.last > .label {
+ -fx-border-radius: 0;
+ -fx-background-radius: 0;
+}
+
+.split-menu-button.last {
+ -fx-border-radius: 0 4 4 0;
+ -fx-background-radius: 0 4 4 0;
+}
+
+.button.middle, .text-field.middle, .text-area.middle, .split-menu-button.middle, .toggle-button.middle {
+ -fx-border-radius: 0;
+ -fx-background-radius: 0;
+}
+
+.button.last, .text-field.last, .text-area.last, .split-menu-button.last, .toggle-button.last, .menu-button.last {
+ -fx-border-radius: 0 4 4 0;
+ -fx-background-radius: 0 4 4 0;
+}
+VBox > .button.last,
+VBox > .menu-button.last,
+VBox > .toggle-button.last,
+VBox > .split-menu-button.last,
+VBox > .text-field.last,
+VBox > .text-area.last {
+ -fx-border-radius: 0 0 4 4;
+ -fx-background-radius: 0 0 4 4;
+}
+
+VBox > .split-menu-button.last > .label {
+ -fx-border-radius: 0 0 0 4;
+ -fx-background-radius: 0 0 0 3;
+}
+VBox > .split-menu-button.last > .arrow-button {
+ -fx-border-radius: 0 0 4 0;
+ -fx-background-radius: 0 0 3 0;
+}
+
+/*button styles*/
+
+/*default button settings*/
+
+/*bgcolor setting*/
+.color-picker,.date-picker > .arrow-button,
+.number-button,.left-arrow-button,.right-arrow-button,
+.button,.split-menu-button,.toggle-button,.menu-button,
+.font-menu-button, .split-menu-button > .label, .split-menu-button > .arrow-button {
+ -fx-background-color: white;
+}
+
+.color-picker,.date-picker > .arrow-button,
+.button,.menu-button,.toggle-button,.number-button,.left-arrow-button,.right-arrow-button,
+.font-menu-button,
+.split-menu-button > .label,.split-menu-button > .arrow-button {
+ -fx-border-color: #cccccc;
+ -fx-text-fill: #333333;
+}
+/*just for the special split menu button*/
+.split-menu-button > .label {
+ -fx-border-width: 1 0 1 1;
+}
+/*for date picker arrow button*/
+.date-picker > .arrow-button {
+ -fx-border-radius: 0 4 4 0;
+}
+.combo-box > .arrow-button, .choice-box > .arrow-button {
+ -fx-border-width: 0;
+}
+/*hover state*/
+.color-picker:hover,
+.date-picker:hover > .arrow-button,
+.combo-box:hover,.choice-box:hover,
+.number-button:hover,.left-arrow-button:hover,.right-arrow-button:hover,
+.button:hover,.menu-button:hover,.toggle-button:hover,
+.font-menu-button:hover,
+.split-menu-button > .label:hover, .split-menu-button > .arrow-button:hover {
+ -fx-background-color: #e6e6e6;
+ -fx-border-color: #acacac;
+}
+/*pressed selected*/
+.color-picker:pressed,.color-picker:selected,
+.number-button:pressed,.number-button:selected,
+.date-picker:pressed > .arrow-button,
+.combo-box:pressed > .arrow-button,.combo-box:selected > .arrow-button,
+.choice-box:pressed > .arrow-button,.choice-box:selected > .arrow-button,
+.font-menu-button:pressed,.font-menu-button:selected,
+.left-arrow-button:pressed,.left-arrow-button:selected,
+.right-arrow-button:pressed,.right-arrow-button:selected,
+.button:pressed, .button:selected,.menu-button:pressed,.menu-button:selected
+,.toggle-button:pressed,.toggle-button:selected,
+.split-menu-button:pressed > .label, .split-menu-button > .arrow-button:pressed {
+ -fx-background-color: #e6e6e6;
+ -fx-border-color: #acacac;
+ -fx-effect: innershadow(gaussian, #adadad, 10, 0, 0, 3);
+}
+
+/*primary*/
+
+.button.primary,.split-menu-button.primary,.toggle-button.primary,.menu-button.primary,
+.split-menu-button.primary > .label, .split-menu-button.primary > .arrow-button {
+ -fx-background-color: #337ab7;
+}
+
+.button.primary,.menu-button.primary,.toggle-button.primary,
+.split-menu-button.primary > .label,.split-menu-button.primary > .arrow-button {
+ -fx-border-color: #2e6da4;
+ -fx-text-fill: white;
+}
+/*hover state*/
+.button.primary:hover,.menu-button.primary:hover,.toggle-button.primary:hover,
+.split-menu-button.primary > .label:hover, .split-menu-button.primary > .arrow-button:hover {
+ -fx-border-color: #204d74;
+ -fx-background-color: #286090;
+}
+/*pressed selected*/
+.button.primary:pressed, .button.primary:selected,
+.menu-button.primary:pressed,.menu-button.primary:selected
+,.toggle-button.primary:pressed,.toggle-button.primary:selected,
+.split-menu-button.primary:pressed > .label, .split-menu-button.primary > .arrow-button:pressed {
+ -fx-background-color: #286090;
+ -fx-border-color: #204d74;
+ -fx-effect: innershadow(gaussian, #204d74, 10, 0, 0, 3);
+}
+
+/*success*/
+
+.button.success,.split-menu-button.success,.toggle-button.success,.menu-button.success,
+.split-menu-button.success > .label, .split-menu-button.success > .arrow-button {
+ -fx-background-color: #5cb85c;
+}
+
+.button.success,.menu-button.success,.toggle-button.success,
+.split-menu-button.success > .label,.split-menu-button.success > .arrow-button {
+ -fx-border-color: #4cae4c;
+ -fx-text-fill: white;
+}
+/*hover state*/
+.button.success:hover,.menu-button.success:hover,.toggle-button.success:hover,
+.split-menu-button.success > .label:hover, .split-menu-button.success > .arrow-button:hover {
+ -fx-border-color: #398439;
+ -fx-background-color: #449d44;
+}
+/*pressed selected*/
+.button.success:pressed, .button.success:selected,
+.menu-button.success:pressed,.menu-button.success:selected
+,.toggle-button.success:pressed,.toggle-button.success:selected,
+.split-menu-button.success:pressed > .label, .split-menu-button.success > .arrow-button:pressed {
+ -fx-background-color: #449d44;
+ -fx-border-color: #398439;
+ -fx-effect: innershadow(gaussian, #398439, 10, 0, 0, 3);
+}
+
+/*info*/
+
+.button.info,.split-menu-button.info,.toggle-button.info,.menu-button.info,
+.split-menu-button.info > .label, .split-menu-button.info > .arrow-button {
+ -fx-background-color: #5bc0de;
+}
+
+.button.info,.menu-button.info,.toggle-button.info,
+.split-menu-button.info > .label,.split-menu-button.info > .arrow-button {
+ -fx-border-color: #46b8da;
+ -fx-text-fill: white;
+}
+/*hover state*/
+.button.info:hover,.menu-button.info:hover,.toggle-button.info:hover,
+.split-menu-button.info > .label:hover, .split-menu-button.info > .arrow-button:hover {
+ -fx-border-color: #269abc;
+ -fx-background-color: #31b0d5;
+}
+/*pressed selected*/
+.button.info:pressed, .button.info:selected,
+.menu-button.info:pressed,.menu-button.info:selected
+,.toggle-button.info:pressed,.toggle-button.info:selected,
+.split-menu-button.info:pressed > .label, .split-menu-button.info > .arrow-button:pressed {
+ -fx-background-color: #31b0d5;
+ -fx-border-color: #269abc;
+ -fx-effect: innershadow(gaussian, #269abc, 10, 0, 0, 3);
+}
+
+/*warning*/
+
+.button.warning,.split-menu-button.warning,.toggle-button.warning,.menu-button.warning,
+.split-menu-button.warning > .label, .split-menu-button.warning > .arrow-button {
+ -fx-background-color: #f0ad4e;
+}
+
+.button.warning,.menu-button.warning,.toggle-button.warning,
+.split-menu-button.warning > .label,.split-menu-button.warning > .arrow-button {
+ -fx-border-color: #eea236;
+ -fx-text-fill: white;
+}
+/*hover state*/
+.button.warning:hover,.menu-button.warning:hover,.toggle-button.warning:hover,
+.split-menu-button.warning > .label:hover, .split-menu-button.warning > .arrow-button:hover {
+ -fx-border-color: #d58512;
+ -fx-background-color: #ec971f;
+}
+/*pressed selected*/
+.button.warning:pressed, .button.warning:selected,
+.menu-button.warning:pressed,.menu-button.warning:selected
+,.toggle-button.warning:pressed,.toggle-button.warning:selected,
+.split-menu-button.warning:pressed > .label, .split-menu-button.warning > .arrow-button:pressed {
+ -fx-background-color: #ec971f;
+ -fx-border-color: #d58512;
+ -fx-effect: innershadow(gaussian, #d58512, 10, 0, 0, 3);
+}
+
+/*danger*/
+
+.button.danger,.split-menu-button.danger,.toggle-button.danger,.menu-button.danger,
+.split-menu-button.danger > .label, .split-menu-button.danger > .arrow-button {
+ -fx-background-color: #d9534f;
+}
+
+.button.danger,.menu-button.danger,.toggle-button.danger,
+.split-menu-button.danger > .label,.split-menu-button.danger > .arrow-button {
+ -fx-border-color: #d43f3a;
+ -fx-text-fill: white;
+}
+/*hover state*/
+.button.danger:hover,.menu-button.danger:hover,.toggle-button.danger:hover,
+.split-menu-button.danger > .label:hover, .split-menu-button.danger > .arrow-button:hover {
+ -fx-border-color: #ac2925;
+ -fx-background-color: #c9302c;
+}
+/*pressed selected*/
+.button.danger:pressed, .button.danger:selected,
+.menu-button.danger:pressed,.menu-button.danger:selected
+,.toggle-button.danger:pressed,.toggle-button.danger:selected,
+.split-menu-button.danger:pressed > .label, .split-menu-button.danger > .arrow-button:pressed {
+ -fx-border-color: #ac2925;
+ -fx-background-color: #c9302c;
+ -fx-effect: innershadow(gaussian, #ac2925, 10, 0, 0, 3);
+}
+
+.menu-item {
+ -fx-min-width: 200;
+}
+
+.menu-item:focused {
+ -fx-background-color: #f5f5f5;
+}
+
+.menu-item:focused > * {
+ -fx-text-fill: #262626;
+}
+.menu-item:focused .arrow {
+ -fx-background-color: #333333;
+}
+
+.check-menu-item:checked:hover > .left-container > .check,
+.check-menu-item:checked:focused > .left-container > .check,
+.radio-menu-item:checked:hover > .left-container > .radio,
+.radio-menu-item:checked:focused > .left-container > .radio {
+ -fx-background-color: #333333;
+}
+
+.context-menu {
+ -fx-border-radius: 4;
+ -fx-background-radius: 4;
+ -fx-border-color: #bebec0;
+}
+
+.context-menu > * {
+ -fx-padding: 5 0 5 0;
+}
+
+.separator {
+ -fx-padding: 5 0 5 0;
+}
+
+.text-field {
+ -fx-pref-height: 30;
+}
+
+.combo-box, .choice-box {
+ -fx-background-insets: 0;
+ -fx-border-color: #cecece;
+ -fx-padding: -1;
+ -fx-border-width: 1;
+}
+.combo-box, .choice-box, .color-picker, .date-picker {
+ -fx-border-radius: 4;
+ -fx-background-radius: 4;
+ -fx-pref-height: 30;
+}
+
+.combo-box:editable > .arrow-button {
+ -fx-background-color: white;
+}
+
+.combo-box:editable > .arrow-button:hover {
+ -fx-background-color: #e6e6e6;
+}
+
+.combo-box:editable > .arrow-button:pressed {
+ -fx-effect: innershadow(gaussian, #adadad, 10, 0, 0, 3);
+}
+
+.combo-box > .text-input, .date-picker > .text-input {
+ -fx-background-radius: 4 0 0 4;
+ -fx-border-width: 0;
+}
+
+.text-field, .text-area {
+ -fx-border-color: #cccccc;
+ -fx-background-color: white;
+ -fx-border-radius: 4;
+ -fx-background-radius: 4;
+ -fx-effect: innershadow(gaussian, transparent, 0, 0, 0, 0);
+}
+
+.text-field:focused, .text-area:focused {
+ -fx-border-color: #66afe9;
+ -fx-effect: dropshadow(gaussian, #66afe9, 10, 0, 0, 0);
+}
+
+.text-area .scroll-pane, .text-area .scroll-pane .content {
+ -fx-background-color: white;
+ -fx-background-radius: 4;
+}
+
+.tab-pane .tab-header-background {
+ -fx-background-color: #f4f4f4;
+}
+.tab-pane.plain .tab-header-background {
+ -fx-background-color: transparent;
+}
+
+.tab-pane .tab-header-area .tab {
+ -fx-border-radius: 4 4 0 0;
+ -fx-background-radius: 5 5 0 0;
+ -fx-background-color: transparent;
+ -fx-border-color: transparent;
+ -fx-padding: 3 10 5 10;
+ -fx-background-insets: 0;
+}
+
+.tab-pane .tab-header-area .tab .tab-label {
+ -fx-text-fill: #337ab7;
+}
+
+.tab-pane .tab-header-area .tab:hover {
+ -fx-background-color: #eeeeee;
+}
+
+.tab-pane .tab-header-area .tab:selected {
+ -fx-focus-color: transparent;
+ -fx-border-color: #dddddd #dddddd white #dddddd;
+ -fx-background-color: white;
+}
+.tab-pane .tab-header-area .tab:selected .tab-label {
+ -fx-text-fill: #333333;
+}
+.tab-pane > .tab-content-area {
+ -fx-background-color: white;
+}
+
+.tab-pane .tab-header-area .tab .tab-label {
+ -fx-focus-color: transparent;
+}
+
+.tab-pane:focused > .tab-header-area > .headers-region > .tab:selected .focus-indicator {
+ -fx-border-color: transparent;
+}
+
+.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button {
+ -fx-background-color: #337ab7;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:selected > .tab-container > .tab-close-button {
+ -fx-background-color: #333333;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button:hover {
+ -fx-background-color: red;
+ -fx-cursor: hand;
+}
+
+.scroll-bar {
+ -fx-background-color: transparent;
+ -fx-background-radius: 0;
+ -fx-block-increment: 50;
+}
+
+.corner {
+ -fx-background-color: transparent;
+}
+
+.scroll-bar .decrement-button, .scroll-bar .decrement-arrow {
+ visibility: hidden;
+ -fx-pref-height: 1;
+ -fx-pref-width: 1;
+}
+
+.scroll-bar .increment-button, .scroll-bar .increment-arrow {
+ visibility: hidden;
+ -fx-pref-height: 1;
+ -fx-pref-width: 1;
+}
+
+.scroll-bar:vertical {
+ -fx-pref-width: 10;
+}
+
+.scroll-bar:horizontal {
+ -fx-pref-height: 10;
+}
+
+.scroll-bar:horizontal .track,
+.scroll-bar:vertical .track {
+ -fx-background-color: transparent;
+ -fx-border-color: transparent;
+ -fx-background-radius: 5;
+}
+
+.scroll-bar:vertical .track-background,
+.scroll-bar:horizontal .track-background {
+ -fx-background-color: transparent;
+ -fx-background-insets: 0;
+ -fx-background-radius: 5;
+}
+
+.scroll-bar:horizontal .thumb {
+ -fx-background-color: #c9c9c9;
+ -fx-background-insets: 2 0 2 0;
+ -fx-background-radius: 5;
+}
+
+.scroll-bar:vertical .thumb {
+ -fx-background-color: #c9c9c9;
+ -fx-background-insets: 0 2 0 2;
+ -fx-background-radius: 5;
+}
+
+.scroll-bar:horizontal .thumb:hover,
+.scroll-bar:vertical .thumb:hover {
+ -fx-background-color: #b5b5b5;
+}
+
+.scroll-bar:horizontal .thumb:pressed,
+.scroll-bar:vertical .thumb:pressed {
+ -fx-background-color: #a0a0a0;
+}
+
+.scroll-bar:vertical .increment-button, .scroll-bar:vertical .decrement-button {
+ -fx-background-color: transparent;
+ -fx-background-radius: 5;
+ -fx-padding: 5;
+}
+
+.scroll-bar:horizontal .increment-button, .scroll-bar:horizontal .decrement-button {
+ -fx-background-color: transparent;
+ -fx-background-radius: 5;
+ -fx-padding: 5;
+}
+
+.scroll-bar:vertical:focused,
+.scroll-bar:horizontal:focused {
+ -fx-background-color: transparent, rgb(96, 96, 96), rgb(96, 96, 96);
+}
+
+.menu-bar {
+ -fx-background-color: white;
+}
+.menu-bar > .container > .menu-button {
+ -fx-background-radius: 0;
+ -fx-background-insets: 0;
+ -fx-border-width: 0;
+ -fx-border-radius: 0;
+}
+.menu-bar > .container > .menu-button:hover,
+.menu-bar > .container > .menu-button:showing {
+ -fx-background-color: #56c0e0;
+}
+
+.color-palette {
+ -fx-background-color: white;
+}
+
+.pagination > .pagination-control > .control-box {
+ -fx-spacing: -1;
+}
+.pagination > .pagination-control > .control-box > .left-arrow-button {
+ -fx-border-radius: 3 0 0 3;
+ -fx-border-insets: 0 0 0 7;
+ -fx-background-insets: 0 0 0 7, 0 0 0 5, 1 1 1 6, 2 2 2 7;
+}
+.pagination > .pagination-control > .control-box > .right-arrow-button {
+ -fx-border-radius: 0 3 3 0;
+ -fx-border-insets: 0 7 0 0;
+ -fx-background-insets: 0 7 -1 0, 0 5 0 0, 1 6 1 1, 2 7 2 2;
+}
+.pagination > .pagination-control > .control-box > .number-button {
+ -fx-background-radius: 0;
+ -fx-border-radius: 0;
+}
+
+.progress-bar > .track {
+ -fx-pref-height: 10;
+ -fx-background-radius: 3;
+ -fx-effect: innershadow(gaussian, #e4e4e4, 4, 0, 0, 1);
+ -fx-background-color: #f5f5f5;
+}
+
+.progress-bar > .bar {
+ -fx-background-insets: 0;
+ -fx-background-color: #337ab7;
+}
+
+.progress-bar.success > .bar {
+ -fx-background-insets: 0;
+ -fx-background-color: #5cb85c;
+}
+
+.progress-bar.info > .bar {
+ -fx-background-insets: 0;
+ -fx-background-color: #5bc0de;
+}
+
+.progress-bar.warning > .bar {
+ -fx-background-insets: 0;
+ -fx-background-color: #f0ad4e
+}
+
+.progress-bar.danger > .bar {
+ -fx-background-insets: 0;
+ -fx-background-color: #d9534f;
+}
+
+.tooltip {
+ -fx-background: white;
+ -fx-text-fill: #333333;
+ -fx-background-color: white;
+ -fx-background-radius: 4px;
+ -fx-border-radius: 4px;
+ -fx-border-color: #C0C0C0;
+ -fx-background-insets: 0;
+ -fx-padding: 0.667em 0.75em 0.667em 0.75em; /* 10px */
+ -fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.5), 10, 0.0, 0, 3);
+ -fx-font-size: 0.85em;
+}
+
+.tooltip.success {
+ -fx-background: #dff0d8;
+ -fx-background-color: #dff0d8;
+ -fx-text-fill: #99bb96;
+ -fx-border-color: #d6e9c6;
+}
+
+.tooltip.info {
+ -fx-background: #d8ecf6;
+ -fx-background-color: #d8ecf6;
+ -fx-text-fill: #31708f;
+ -fx-border-color: #bce8f1;
+}
+
+.tooltip.warning {
+ -fx-background: #fcf8e3;
+ -fx-background-color: #fcf8e3;
+ -fx-text-fill: #8a6e3c;
+ -fx-border-color: #faebcc;
+}
+
+.tooltip.danger {
+ -fx-background: #f2dede;
+ -fx-background-color: #f2dede;
+ -fx-text-fill: #a94442;
+ -fx-border-color: #ebccd1;
+}
+
+.titled-pane > .title {
+ -fx-background-color: #f5f5f5;
+ -fx-border-color: #dddddd;
+ /*-fx-background-insets: 5, 1, 5;*/
+ -fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0;
+ -fx-border-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0;
+ -fx-padding: 11
+}
+
+.titled-pane > .content {
+ -fx-background-color: white;
+ -fx-background-radius: 0 0 4 4;
+ -fx-border-radius: 0 0 4 4;
+ -fx-border-color: #dddddd;
+ /*-fx-padding: -11;*/
+}
+
+.titled-pane.primary {
+ -fx-text-fill: white;
+}
+
+.titled-pane.primary > .title {
+ -fx-background-color: #337ab7;
+ -fx-border-color: #337ab7;
+}
+
+.titled-pane.primary > .content {
+ -fx-border-color: #337ab7;
+}
+
+.titled-pane.success .arrow,
+.titled-pane.info .arrow,
+.titled-pane.warning .arrow,
+.titled-pane.danger .arrow {
+ -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+}
+
+.titled-pane.success {
+ -fx-text-fill: #3c763d;
+}
+
+.titled-pane.success > .title {
+ -fx-background-color: #dff0d8;
+ -fx-border-color: #d6e9c6;
+}
+
+.titled-pane.success > .content {
+ -fx-border-color: #d6e9c6;
+}
+
+.titled-pane.info {
+ -fx-text-fill: #31708f;
+}
+
+.titled-pane.info > .title {
+ -fx-background-color: #d9edf7;
+ -fx-border-color: #bce8f1;
+}
+
+.titled-pane.info > .content {
+ -fx-border-color: #bce8f1;
+}
+
+.titled-pane.warning {
+ -fx-text-fill: #8a6d3b;
+}
+
+.titled-pane.warning > .title {
+ -fx-background-color: #fcf8e3;
+ -fx-border-color: #faebcc;
+}
+
+.titled-pane.warning > .content {
+ -fx-border-color: #faebcc;
+}
+
+.titled-pane.danger {
+ -fx-text-fill: #a94442;
+}
+
+.titled-pane.danger > .title {
+ -fx-background-color: #f2dede;
+ -fx-border-color: #eacbd0;
+}
+
+.titled-pane.danger > .content {
+ -fx-border-color: #eacbd0;
+}
+
+.accordion > .titled-pane > .title,
+.accordion > .titled-pane > .content {
+ -fx-background-radius: 0;
+ -fx-border-radius: 0;
+}
+
+.tool-bar:vertical { /* left */
+ -fx-border-color: transparent #dddddd transparent transparent;
+}
+
+.tool-bar { /* top */
+ -fx-background-color: white;
+ -fx-border-color: transparent transparent #dddddd transparent;
+}
+
+.tool-bar:vertical {
+ -fx-background-insets: 0, 0 1 0 0;
+}
+
+/*table view columns*/
+.filler,.column-header,.show-hide-columns-button {
+ -fx-background-color: #dddddd, white, white;
+}
+.show-hide-columns-button {
+ -fx-border-width: 0;
+ -fx-background-insets: 0 0 1 1;
+}
+.column-header:hover,.show-hide-columns-button:hover {
+ -fx-background-color: #dddddd, white, #f8f8f8;
+}
+.column-header-background > .filler {
+ -fx-border-color: transparent #dddddd transparent transparent;
+ -fx-border-insets: 0 1 0 0;
+}
+.column-drag-header {
+ -fx-background-color: #2fb254;
+}
+
+/*split pane*/
+.split-pane > .split-pane-divider {
+ -fx-background-color: white;
+ -fx-border-color: #eeeeee;
+ -fx-pref-width: 8;
+}
+.split-pane:horizontal > .split-pane-divider {
+ -fx-background-insets: 0, 0 1 0 1;
+ -fx-border-width: 0 1 0 1;
+}
+/* vertical the two nodes are placed on top of each other. */
+.split-pane:vertical > .split-pane-divider {
+ -fx-background-insets: 0, 1 0 1 0;
+ -fx-border-width: 1 0 1 0;
+}
+.split-pane > .split-pane-divider:hover {
+ -fx-background-color: #E0E0E0;
+}
+
+/*******************************************************************************
+ * *
+ * CheckBox *
+ * *
+ ******************************************************************************/
+.check-box > .box {
+ -fx-background-radius: 3;
+ /*-fx-padding: 0.166667em 0.166667em 0.25em 0.25em; !* 2 2 3 3 *!*/
+ -fx-padding:0;
+ -fx-border-color: #56c0e0;
+ -fx-border-radius: 3;
+ -fx-background-color: white;
+}
+.check-box > .box > .mark {
+ -fx-background-color: null;
+ -fx-padding: 0.416667em 0.416667em 0.5em 0.5em; /* 5 5 6 6 */
+ -fx-shape: "M927.936 272.992l-68.288-68.288c-12.608-12.576-32.96-12.576-45.536 0l-409.44 409.44-194.752-196.16c-12.576-12.576-32.928-12.576-45.536 0l-68.288 68.288c-12.576 12.608-12.576 32.96 0 45.536l285.568 287.488c12.576 12.576 32.96 12.576 45.536 0l500.736-500.768c12.576-12.544 12.576-32.96 0-45.536z";
+ -fx-background-insets: -3 -3 1 0;
+}
+.check-box {
+ -fx-label-padding: 0.2em 0.0em 0.3em 0.416667em; /* 0 0 0 5 */
+ -fx-text-fill: -fx-text-background-color;
+ -fx-padding: 0 0 2 0;
+}
+.check-box:indeterminate > .box {
+ -fx-padding: 0;
+}
+.check-box:selected > .box > .mark {
+ -fx-background-color: linear-gradient(to bottom, #56c0e0, #40b8dc);
+}
+
+/*******************************************************************************
+ * *
+ * RadioButton *
+ * *
+ ******************************************************************************/
+
+.radio-button {
+ -fx-label-padding: 0.0em 0.0em 0.1em 0.416667em; /* 0 0 0 5 */
+ -fx-text-fill: -fx-text-background-color;
+ -fx-padding: 0 0 .5 0;
+}
+.radio-button > .radio,
+.radio-button:focused > .radio {
+ -fx-border-color: #56c0e0;
+ -fx-border-radius: 1em;
+ -fx-background-radius: 1.0em; /* large value to make sure this remains circular */
+ -fx-padding: 1 2 3 2;
+ -fx-background-color: white;
+}
+.radio-button > .radio > .dot {
+ -fx-background-color: transparent;
+ -fx-background-radius: 1.0em; /* large value to make sure this remains circular */
+ -fx-padding: 0.333333em; /* 4 -- radius of the inner black dot when selected */
+ -fx-background-insets: 3 2 1 2;
+}
+.radio-button:selected > .radio,.radio-button:hover > .radio {
+ -fx-fill-color: #56c0e0;
+}
+.radio-button:pressed > .radio {
+ -fx-background-color: #50c0e2;
+}
+.radio-button:selected > .radio > .dot {
+ -fx-background-color: #56c0e0;
+}
+
+/*common things*/
+.check-box:hover > .box,
+.check-box:selected > .box,
+.radio-button:hover > .radio,
+.radio-button:selected > .radio {
+ -fx-background-color: linear-gradient(to bottom, white, #efefef);
+}
+
+.check-box:pressed > .box,
+.radio-button:pressed > .radio {
+ -fx-background-color: #50c0e2;
+}
\ No newline at end of file
diff --git a/out/production/G-Earth2/main/ui/connection/Connection.fxml b/out/production/G-Earth2/main/ui/connection/Connection.fxml
new file mode 100644
index 0000000..d4590b8
--- /dev/null
+++ b/out/production/G-Earth2/main/ui/connection/Connection.fxml
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/out/production/G-Earth2/main/ui/connection/ConnectionForm.class b/out/production/G-Earth2/main/ui/connection/ConnectionForm.class
new file mode 100644
index 0000000..588bd51
Binary files /dev/null and b/out/production/G-Earth2/main/ui/connection/ConnectionForm.class differ
diff --git a/out/production/G-Earth2/main/ui/injection/Injection.fxml b/out/production/G-Earth2/main/ui/injection/Injection.fxml
new file mode 100644
index 0000000..fda9bd9
--- /dev/null
+++ b/out/production/G-Earth2/main/ui/injection/Injection.fxml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/out/production/G-Earth2/main/ui/injection/InjectionForm.class b/out/production/G-Earth2/main/ui/injection/InjectionForm.class
new file mode 100644
index 0000000..5279aef
Binary files /dev/null and b/out/production/G-Earth2/main/ui/injection/InjectionForm.class differ
diff --git a/out/production/G-Earth2/main/ui/logger/Logger.fxml b/out/production/G-Earth2/main/ui/logger/Logger.fxml
new file mode 100644
index 0000000..d96cbcc
--- /dev/null
+++ b/out/production/G-Earth2/main/ui/logger/Logger.fxml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/out/production/G-Earth2/main/ui/logger/LoggerForm.class b/out/production/G-Earth2/main/ui/logger/LoggerForm.class
new file mode 100644
index 0000000..d13b757
Binary files /dev/null and b/out/production/G-Earth2/main/ui/logger/LoggerForm.class differ
diff --git a/out/production/G-Earth2/main/ui/tools/Tools.fxml b/out/production/G-Earth2/main/ui/tools/Tools.fxml
new file mode 100644
index 0000000..362b480
--- /dev/null
+++ b/out/production/G-Earth2/main/ui/tools/Tools.fxml
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/out/production/G-Earth2/main/ui/tools/ToolsForm.class b/out/production/G-Earth2/main/ui/tools/ToolsForm.class
new file mode 100644
index 0000000..c2c80ed
Binary files /dev/null and b/out/production/G-Earth2/main/ui/tools/ToolsForm.class differ
diff --git a/src/main/protocol/HConnection.java b/src/main/protocol/HConnection.java
index a5b3319..6ce083c 100644
--- a/src/main/protocol/HConnection.java
+++ b/src/main/protocol/HConnection.java
@@ -1,6 +1,7 @@
package main.protocol;
import main.OSValidator;
+import main.protocol.memory.Rc4Obtainer;
import main.protocol.packethandler.Handler;
import main.protocol.packethandler.IncomingHandler;
import main.protocol.packethandler.OutgoingHandler;
@@ -126,10 +127,13 @@ public class HConnection {
final boolean[] aborted = new boolean[1];
+ Rc4Obtainer rc4Obtainer = new Rc4Obtainer();
+
// wachten op data van client
new Thread(() -> {
try {
OutgoingHandler handler = new OutgoingHandler(habbo_server_out);
+ rc4Obtainer.setOutgoingHandler(handler);
while (!client.isClosed() && (state == State.WAITING_FOR_CLIENT || state == State.CONNECTED)) {
byte[] buffer;
@@ -179,6 +183,7 @@ public class HConnection {
new Thread(() -> {
try {
IncomingHandler handler = new IncomingHandler(client_out);
+ rc4Obtainer.setIncomingHandler(handler);
while (!habbo_server.isClosed() && (state == State.CONNECTED || state == State.WAITING_FOR_CLIENT)) {
byte[] buffer;
diff --git a/src/main/protocol/HPacket.java b/src/main/protocol/HPacket.java
index a47dcdd..ade4ca2 100644
--- a/src/main/protocol/HPacket.java
+++ b/src/main/protocol/HPacket.java
@@ -21,12 +21,14 @@ public class HPacket {
packetInBytes = fromStringToBytes(fromExpressionToString(packet));
}
public HPacket(int header) {
- packetInBytes = new byte[]{0,0,0,4,0,0};
+ packetInBytes = new byte[]{0,0,0,2,0,0};
replaceUShort(4, header);
+ isEdited = false;
}
public HPacket(int header, byte[] bytes) {
- packetInBytes = new byte[4];
+ this(header);
appendBytes(bytes);
+ isEdited = false;
}
public String toString() {
diff --git a/src/main/protocol/crypto/RC4.java b/src/main/protocol/crypto/RC4.java
index 1c67547..e062291 100644
--- a/src/main/protocol/crypto/RC4.java
+++ b/src/main/protocol/crypto/RC4.java
@@ -35,6 +35,10 @@ package main.protocol.crypto;
import main.protocol.HPacket;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
/**
* This is a simple implementation of the RC4 (tm) encryption algorithm. The
* author implemented this class for some simple applications
@@ -111,6 +115,17 @@ public class RC4 {
}
+ public RC4(byte[] state, int x, int y) {
+ this.x = x;
+ this.y = y;
+ this.state = state;
+ }
+
+ //copyconstructor
+ public RC4 deepCopy() {
+ return new RC4(Arrays.copyOf(state, 256), x, y);
+ }
+
/**
* RC4 encryption/decryption.
*
@@ -169,36 +184,100 @@ public class RC4 {
return result;
}
+ public void undoRc4(byte[] buf) {
+
+ byte tmp;
+
+ for (int i = buf.length - 1; i >= 0; i--) {
+
+ tmp = state[x];
+ state[x] = state[y];
+ state[y] = tmp;
+
+ y = (y - (state[x] & 0xff)) & 0xff;
+ x = (x - 1) & 0xff;
+ }
+
+ }
+
public void printKey() {
System.out.println(new HPacket(state).toString());
}
+
+ private static void printState(byte[] booleans) {
+ StringBuilder builder = new StringBuilder("state: ");
+ for (byte bool : booleans) {
+ builder.append(bool);
+ builder.append(",");
+ }
+ System.out.println(builder);
+ }
+
public static void main(String[] args) {
+
byte[] sharedKey = new byte[27];
-
+ List allbytesEncrypted = new ArrayList<>();
RC4 p1 = new RC4(sharedKey);
- RC4 p2 = new RC4(sharedKey);
- p1.printKey();
- p2.printKey();
- byte[] enc = p1.rc4("hallo".getBytes());
- System.out.println(new String(p2.rc4(enc)));
+ System.out.println("original:");
+ printState(p1.state);
+ System.out.println("x: " + p1.x + ", y: " + p1.y);
- p1.printKey();
- p2.printKey();
+ byte[] enc1 = p1.rc4("hallo dit istoch wel redelijk veel tekst ofzo denk k".getBytes());
+ for (int i = 0; i < enc1.length; i++) {
+ allbytesEncrypted.add(enc1[i]);
+ }
- enc = p1.rc4("hallo".getBytes());
- System.out.println(new String(p2.rc4(enc)));
+ byte[] enc2 = p1.rc4("dit is ook redelijk wa tekst maar mag nog veel meer zijn eigelijk in principe hoor".getBytes());
+ for (int i = 0; i < enc2.length; i++) {
+ allbytesEncrypted.add(enc2[i]);
+ }
- p1.printKey();
- p2.printKey();
+ System.out.println("-----------");
+ System.out.println("after being sent:");
+ printState(p1.state);
+ System.out.println("x: " + p1.x + ", y: " + p1.y);
- enc = p1.rc4("meneeeer dit zijn echt veel meer dan 27 characters dus latne we dit even proberen".getBytes());
- System.out.println(new String(p2.rc4(enc)));
- p1.printKey();
- p2.printKey();
+ byte[] allencrypted = new byte[allbytesEncrypted.size()];
+ for (int i = 0; i < allbytesEncrypted.size(); i++) {
+ allencrypted[i] = allbytesEncrypted.get(i);
+ }
+
+ p1.undoRc4(allencrypted);
+
+ System.out.println("-----------");
+ System.out.println("after undo:");
+ printState(p1.state);
+ System.out.println("x: " + p1.x + ", y: " + p1.y);
+
+
+// byte[] sharedKey = new byte[27];
+//
+// RC4 p1 = new RC4(sharedKey);
+// RC4 p2 = new RC4(sharedKey);
+//
+// p1.printKey();
+// p2.printKey();
+// byte[] enc = p1.rc4("hallo".getBytes());
+// System.out.println(new String(p2.rc4(enc)));
+//
+// p1.printKey();
+// p2.printKey();
+//
+// enc = p1.rc4("hallo".getBytes());
+// System.out.println(new String(p2.rc4(enc)));
+//
+// p1.printKey();
+// p2.printKey();
+//
+// enc = p1.rc4("meneeeer dit zijn echt veel meer dan 27 characters dus latne we dit even proberen".getBytes());
+// System.out.println(new String(p2.rc4(enc)));
+//
+// p1.printKey();
+// p2.printKey();
}
// public static void main(String[] args) {
diff --git a/src/main/protocol/memory/FlashClient.java b/src/main/protocol/memory/FlashClient.java
index fb06315..0276472 100644
--- a/src/main/protocol/memory/FlashClient.java
+++ b/src/main/protocol/memory/FlashClient.java
@@ -4,34 +4,15 @@ import main.irrelevant.Timer;
import java.io.*;
import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
public class FlashClient {
-
- public class MemorySnippet {
- long offset;
- byte[] data;
-
- public MemorySnippet(long offset, byte[] data) {
- this.offset = offset;
- this.data = data;
- }
-
- public byte[] getData() {
- return data;
- }
-
- public long getOffset() {
- return offset;
- }
- }
-
private int PID;
private List maps;
+ private static final boolean DEBUG = false;
+
public static FlashClient create() {
File folder = new File("/proc");
FlashClient client = null;
@@ -52,7 +33,7 @@ public class FlashClient {
} while (client == null);
- System.out.println("* Found flashclient process: " + client.PID);
+ if (DEBUG) System.out.println("* Found flashclient process: " + client.PID);
return client;
}
public void refreshMemoryMaps() {
@@ -85,7 +66,7 @@ public class FlashClient {
e.printStackTrace();
}
- System.out.println("* Found memory maps (amount: " + maps.size() + ")");
+ if (DEBUG) System.out.println("* Found memory maps (amount: " + maps.size() + ")");
}
public List createMemorySnippetList () {
@@ -102,254 +83,74 @@ public class FlashClient {
return result;
}
public void fetchMemory(List snippets) {
- String memoryPath = "/proc/" + PID + "/mem";
for (MemorySnippet snippet : snippets) {
- long begin = snippet.offset;
- try {
- RandomAccessFile raf = new RandomAccessFile(memoryPath, "r");
- raf.seek(begin);
- raf.read(snippet.getData());
- raf.close();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
+ fetchMemory(snippet);
}
}
-
- /**
- * can remove & add & edit maps of memorysnipperlist
- */
- public void updateMapLocationsSnippetList(List snippets) {
- refreshMemoryMaps();
-
- List list2 = new ArrayList<>();
- List not_added = new ArrayList<>();
-
- // readd all maps that stayed the same
- for (long[] map : maps) {
- //if was in snippetlist:
- boolean found = false;
- for (MemorySnippet snippet : snippets) {
- if (snippet.offset == map[0] && snippet.offset + snippet.getData().length == map[1]) {
- list2.add(snippet);
- snippets.remove(snippet);
- found = true;
- break;
- }
- }
- if (!found) {
- not_added.add(map);
- }
-
+ public void fetchMemory(MemorySnippet snippet) {
+ String memoryPath = "/proc/" + PID + "/mem";
+ long begin = snippet.offset;
+ try {
+ RandomAccessFile raf = new RandomAccessFile(memoryPath, "r");
+ raf.seek(begin);
+ raf.read(snippet.getData());
+ raf.close();
}
-
- for (int i = 0; i < not_added.size(); i++) {
- long[] map = not_added.get(i);
- //find potential overlap snippet
- MemorySnippet snippet = new MemorySnippet(map[0], new byte[(int)(map[1] - map[0])]);
- byte[] data = snippet.getData();
-
- for (MemorySnippet potential : snippets) {
- //if there is overlap
- if ((potential.offset >= map[0] && potential.offset < map[1]) ||
- (potential.offset + potential.getData().length >= map[0] && potential.offset + potential.getData().length< map[1]) ||
- (potential.offset < map[0] && potential.offset + potential.getData().length >= map[1]) ) {
-
- int start = Math.max((int)(potential.offset - map[0]), 0);
- int offset2 = -(int)(potential.offset - map[0]);
-
- for (int j = start; j < Math.min(map[1] - map[0], potential.getData().length - offset2); j++) {
- data[j] = potential.getData()[j+offset2];
- }
- }
- }
- list2.add(snippet);
+ catch (Exception e) {
+ e.printStackTrace();
}
-
- snippets.clear();
- for (MemorySnippet snippet : list2) {
- snippets.add(snippet);
- }
-
}
- /**
- * creates a new memorysnippet list of data that changed (or not) from the original list with a given left&right buffer
- */
- public List differentiate(List original, boolean isChanged, int leftRightbytebuffer) {
- //fill a new memorysnippet list with live data
+ public List differentiate2(List original, int minChangedBytes, int maxChangedBytes, int range) {
List upToDate = new ArrayList<>();
for (MemorySnippet memorySnippet : original) {
upToDate.add(new MemorySnippet(memorySnippet.getOffset(), new byte[memorySnippet.getData().length]));
}
fetchMemory(upToDate);
-
List result = new ArrayList<>();
-
- long totalBytes = 0;
-
+ Queue wachter = new LinkedList<>();
for (int i = 0; i < original.size(); i++) {
- long offset = original.get(i).getOffset();
- byte[] old = original.get(i).getData();
- byte[] curr = upToDate.get(i).getData();
+ wachter.clear();
+ int wachtersize = 0;
- if (!isChanged) {
- // find all non-changed stuff and put in result
- long pre = offset;
- for (int j = 0; j < old.length; j++) {
- if (old[j] != curr[j]) {
- //calculate previous block length
- int len = j - ((int)(pre - offset));
- if (len >= leftRightbytebuffer && len > 0) {
- result.add(new MemorySnippet(pre, new byte[len]));
- totalBytes += len;
- }
- pre = offset + j + 1;
- }
+ MemorySnippet org = original.get(i);
+ byte[] orgdata = org.getData();
+ MemorySnippet upd = upToDate.get(i);
+ byte[] upddata = upd.getData();
+
+ int curstartoffset = -1;
+ int lastendbuffer = -1;
+
+ for (int p = 0; p < org.getData().length; p++) {
+ if (wachtersize > 0 && p == wachter.peek()) {
+ wachter.poll();
+ wachtersize--;
}
- int len = old.length - ((int)(pre - offset));
- if (len >= leftRightbytebuffer && len > 0) {
- result.add(new MemorySnippet(pre, new byte[len]));
- totalBytes += len;
+ if (orgdata[p] != upddata[p]) {
+ wachter.add(p + range);
+ wachtersize++;
+ }
+
+ if (p >= range - 1 && wachtersize >= minChangedBytes && wachtersize <= maxChangedBytes) {
+ if (curstartoffset == -1) {
+ curstartoffset = p - range + 1;
+ }
+ else if (lastendbuffer < p - range) {
+ MemorySnippet snippet = new MemorySnippet(curstartoffset + org.getOffset(), new byte[lastendbuffer - curstartoffset + 1]);
+ result.add(snippet);
+ curstartoffset = p - range + 1;
+ }
+ lastendbuffer = p;
}
}
- else {
- //find all changed stuff and put result
- long pre = offset;
- int downCount = -1; //if downCount reaches zero, buffer should be written out
- for (int j = 0; j < old.length; j++) {
- if (old[j] != curr[j]) {
- if (downCount <= 0) {
- pre = Math.max(offset, offset + j - leftRightbytebuffer);
- }
- downCount = leftRightbytebuffer;
- }
- else { downCount -= 1; }
- if (downCount == 0) {
- int len = j - ((int)(pre - offset));
- result.add(new MemorySnippet(pre, new byte[len]));
- totalBytes += len;
- }
- }
- int len = old.length - ((int)(pre - offset));
- if (downCount > 0 && len >= leftRightbytebuffer) {
- result.add(new MemorySnippet(pre, new byte[len]));
- totalBytes += len;
- }
+ if (curstartoffset != -1) {
+ MemorySnippet snippet = new MemorySnippet(curstartoffset + org.getOffset(), new byte[lastendbuffer - curstartoffset + 1]);
+ result.add(snippet);
}
}
fetchMemory(result);
-
- System.out.println("totalbytes after diff: " + totalBytes);
-
return result;
}
- //currently not being used functions:
- List searchOffsetForByteArray(byte[] toFind) {
- if (toFind.length == 0) return null;
-
- System.out.println("*** Start searching for: " + new String(toFind));
- String memoryPath = "/proc/" + PID + "/mem";
- List results = new ArrayList<>();
-
- Timer t = new Timer();
- t.start();
-
- for (long[] map : maps) {
- long begin = map[0];
- long end = map[1];
- try {
- RandomAccessFile raf = new RandomAccessFile(memoryPath, "r");
- byte[] wholeBuffer = new byte[(int)(end - begin)];
- raf.seek(begin);
- raf.read(wholeBuffer);
- raf.close();
-
- for (int i = 0; i < wholeBuffer.length; i++) {
-
- int subIndex = 0;
- while (subIndex < toFind.length && wholeBuffer[i + subIndex] == toFind[subIndex]) subIndex++;
-
- if (subIndex == toFind.length) {
- long result = (long)i + begin;
- results.add(result);
- System.out.println("* Found match for " + new String(toFind) + " at address: " + result);
- }
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- System.out.println("*** End searching for: " + new String(toFind) + " in " + t.delta() + "ms");
- return results;
- }
- List searchOffsetForString(String keyString) {
- return searchOffsetForByteArray(keyString.getBytes());
- }
-
- public List findSharedKey (List snippets){
-
- byte[] bounds = "09afAF".getBytes();
-
- List results = new ArrayList<>();
-
- int size = 54;
-
- for (MemorySnippet snippet : snippets) {
- int count = 0;
- byte[] data = snippet.getData();
- if (data.length >= size) {
- for (int i = 0; i < data.length; i++) {
- byte b = data[i];
- if ((b >= bounds[0] && b <= bounds[1]) ||
- (b >= bounds[2] && b <= bounds[3]) ||
- (b >= bounds[4] && b <= bounds[5])) {
- count++;
- }
- else {
- count = 0;
- }
- if (count == size && (i + 1 == data.length || !((data[i+1] >= bounds[0] && data[i+1] <= bounds[1]) ||
- (data[i+1] >= bounds[2] && data[i+1] <= bounds[3]) ||
- (data[i+1] >= bounds[4] && data[i+1] <= bounds[5]))) ) {
- results.add(new String(Arrays.copyOfRange(data, i - size + 1, i + 1)) + " on location: " + (snippet.getOffset() + i));
- }
- }
- }
-
- }
- return results;
- }
-
- public List findSharedKey2() {
- List memorySnippets = new ArrayList<>();
-
- int buff = 15000000;
-
- long verystart = maps.get(0)[0];
- long veryend = maps.get(0)[1];
-
- for (int i = 1; i < maps.size(); i++) {
- long[] map = maps.get(i);
- if (map[1] - veryend <= buff) {
- veryend = map[1];
- }
- else {
- memorySnippets.add(new MemorySnippet(verystart, new byte[(int)(veryend - verystart + buff)]));
- verystart = maps.get(i)[0];
- veryend = maps.get(i)[1];
- }
- }
- memorySnippets.add(new MemorySnippet(verystart, new byte[(int)(veryend - verystart + buff)]));
-
- fetchMemory(memorySnippets);
- return findSharedKey(memorySnippets);
- }
-
-
@SuppressWarnings("Duplicates")
public void pauseProcess() {
String[] args = new String[] {"kill", "-STOP", PID+""};
@@ -401,10 +202,8 @@ public class FlashClient {
// client.updateMapLocationsSnippetList(l);
- List res = client.findSharedKey2();
- System.out.println(res);
- System.out.println("test");
}
+
}
diff --git a/src/main/protocol/memory/MemorySnippet.java b/src/main/protocol/memory/MemorySnippet.java
new file mode 100644
index 0000000..aca539a
--- /dev/null
+++ b/src/main/protocol/memory/MemorySnippet.java
@@ -0,0 +1,19 @@
+package main.protocol.memory;
+
+public class MemorySnippet {
+ long offset;
+ byte[] data;
+
+ public MemorySnippet(long offset, byte[] data) {
+ this.offset = offset;
+ this.data = data;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public long getOffset() {
+ return offset;
+ }
+}
diff --git a/src/main/protocol/memory/Rc4Obtainer.java b/src/main/protocol/memory/Rc4Obtainer.java
index 6e734e3..5358119 100644
--- a/src/main/protocol/memory/Rc4Obtainer.java
+++ b/src/main/protocol/memory/Rc4Obtainer.java
@@ -2,33 +2,34 @@ package main.protocol.memory;
import javafx.application.Platform;
import main.protocol.HPacket;
+import main.protocol.crypto.RC4;
import main.protocol.packethandler.BufferListener;
import main.protocol.packethandler.IncomingHandler;
import main.protocol.packethandler.OutgoingHandler;
import main.protocol.memory.FlashClient;
+import java.util.Arrays;
import java.util.List;
+import java.util.Random;
public class Rc4Obtainer {
- public static Rc4Obtainer rc4Obtainer = null;
- public static void initialize() {
- rc4Obtainer = new Rc4Obtainer();
- rc4Obtainer.client = FlashClient.create();
- }
+ public static final boolean DEBUG = false;
FlashClient client = null;
OutgoingHandler outgoingHandler = null;
IncomingHandler incomingHandler = null;
- private Rc4Obtainer() {
-
+ public Rc4Obtainer() {
+ client = FlashClient.create();
}
+
+ private boolean hashappened1 = false;
public void setOutgoingHandler(OutgoingHandler handler) {
outgoingHandler = handler;
- handler.addBufferListener(() -> {
- if (handler.getCurrentIndex() >= 3) hasChangedFromLastCheck = true;
+ handler.addBufferListener((int addedbytes) -> {
+ if (handler.getCurrentIndex() >= 3) this.addedBytes += addedbytes;
if (!hashappened1 && handler.getCurrentIndex() == 3) {
hashappened1 = true;
onSendFirstEncryptedMessage();
@@ -38,91 +39,182 @@ public class Rc4Obtainer {
public void setIncomingHandler(IncomingHandler handler) {
incomingHandler = handler;
- handler.addBufferListener(() -> {
- if (!hashappened2 && handler.getCurrentIndex() == 1) {
- hashappened2 = true;
- onReceivePubKey();
- }
- });
}
- private List fullmemorybeforekey = null;
- private boolean hasChangedFromLastCheck = false;
-
- private boolean hashappened2 = false;
- private void onReceivePubKey() {
- incomingHandler.block();
- new Thread(() -> {
-
- System.out.println("[+] receive pubkey");
- client.pauseProcess();
-
- fullmemorybeforekey = client.createMemorySnippetList();
- client.fetchMemory(fullmemorybeforekey);
-
- System.out.println("[-] receive pubkey");
-
- client.resumeProcess();
- incomingHandler.unblock();
- }).start();
- }
-
-
- private boolean hashappened1 = false;
+ private volatile int addedBytes = 0;
private void onSendFirstEncryptedMessage() {
incomingHandler.block();
outgoingHandler.block();
new Thread(() -> {
- System.out.println("[+] send encrypted");
- client.pauseProcess();
- client.updateMapLocationsSnippetList(fullmemorybeforekey);
- client.resumeProcess();
+ if (DEBUG) System.out.println("[+] send encrypted");
+ sleep(20);
- List diff = searchForPossibleRC4Tables(fullmemorybeforekey);
- System.out.println("size: " + getTotalBytesLengthOfDiff(diff));
- for (int i = 0; i < 20; i++) {
-// if (i % 2 == 1) {
-// incomingHandler.sendToStream(new HPacket(3631).toBytes());
-// }
- sleep(200);
- boolean rem = hasChangedFromLastCheck;
- diff = searchForPossibleRC4Tables(diff);
- System.out.println("size: " + getTotalBytesLengthOfDiff(diff) + " and was changed: " + rem);
+ List diff = null;
+
+
+ // STEP ONE: filtering to obtain one area containing the rc4 data field
+ int foundbuffersize = 0;
+ while (foundbuffersize == 0) {
+ client.pauseProcess();
+ diff = client.createMemorySnippetList();
+ client.fetchMemory(diff);
+ client.resumeProcess();
+ this.addedBytes = 0;
+
+ Random rand = new Random();
+
+ if (DEBUG) System.out.println("size: " + getTotalBytesLengthOfDiff(diff));
+ int i = 0;
+ while (getTotalBytesLengthOfDiff(diff) > 2000) {
+ int am = 0;
+ if (i % 2 == 1) {
+ am = rand.nextInt(30) + 1;
+ for (int j = 0; j < am; j++) {
+ incomingHandler.sendToStream(new HPacket(3794).toBytes());
+ outgoingHandler.fakePongAlert();
+ sleep(20);
+ }
+ }
+ sleep(50);
+ int rem = addedBytes;
+ diff = searchForPossibleRC4Tables(diff);
+ if (DEBUG) System.out.println("size: " + getTotalBytesLengthOfDiff(diff) + " with changed bytes: " + rem + " should be: " + am * 6);
+ i++;
+ }
+
+ foundbuffersize = (int)getTotalBytesLengthOfDiff(diff);
}
- System.out.println("[-] send encrypted");
+
+
+
+ //diff should only have one element now
+ // STEP TWO: obtain the exactly the 256 needed bytes
+ //research shows that this equals the first occurence of a number followed by 3 zeros is the start
+ //if that number accidentally is zero it won't work so fuck that - cry -
+ MemorySnippet snippet = diff.get(0);
+ byte[] wannabeRC4data = snippet.getData();
+ int result_start_index = -1;
+ for (int i = 0; i < snippet.getData().length - 3; i++) {
+ if (wannabeRC4data[i] != 0 && wannabeRC4data[i+1] == 0 && wannabeRC4data[i+2] == 0 && wannabeRC4data[i+3] == 0) {
+ result_start_index = i;
+ if (DEBUG) System.out.println(result_start_index);
+ break;
+ }
+ }
+
+ byte[] data = new byte[256]; // dis is the friggin key
+ for (int i = 0; i < 256; i++) data[i] = wannabeRC4data[i*4 + result_start_index];
+
+ if (DEBUG) printByteArray(data);
+
+
+
+
+
+ // STEP 3: find the i & j values (in our RC4 class called x & y)
+ // this goes together with the verification of this actually being the right RC4 table
+
+ MemorySnippet snippet1 = new MemorySnippet(snippet.getOffset(), new byte[snippet.getData().length]);
+ client.fetchMemory(snippet1);
+ incomingHandler.sendToStream(new HPacket(3794).toBytes());
+ outgoingHandler.fakePongAlert();
+ sleep(70);
+
+ byte[] data1 = new byte[256];
+ for (int i = 0; i < 256; i++) data1[i] = snippet1.getData()[i*4 + result_start_index];
+
+ byte[] lastPongPacket = new byte[6];
+ List encodedbytelistraw = outgoingHandler.getEncryptedBuffer();
+ for (int i = 0; i < 6; i++) {
+ lastPongPacket[i] = encodedbytelistraw.get(encodedbytelistraw.size() - 6 + i);
+ }
+
+ RC4 result = null;
+
+ //dont panic this runs extremely fast xo
+ outerloop:
+ for (int x = 0; x < 256; x++) {
+ for (int y = 0; y < 256; y++) {
+ byte[] copy = new byte[256];
+ for (int i = 0; i < 256; i++) {
+ copy[i] = data1[i];
+ }
+ RC4 rc4Tryout = new RC4(copy, x, y);
+
+ HPacket tryout = new HPacket(rc4Tryout.rc4(lastPongPacket));
+ if (!tryout.isCorrupted()) {
+ result = rc4Tryout;
+ break outerloop;
+ }
+ }
+ }
+
+
+
+ // STEP FOUR: undo all sent packets in the rc4 stream
+ List enbuf = outgoingHandler.getEncryptedBuffer();
+ byte[] encrbuffer = new byte[enbuf.size()];
+ for (int i = 0; i < enbuf.size(); i++) {
+ encrbuffer[i] = enbuf.get(i);
+ }
+
+ result.undoRc4(encrbuffer);
+
+
+ // STEP FIVE: set the rc4 stream
+
+ if (result != null) {
+ outgoingHandler.setRc4(result);
+ }
+ else {
+ System.err.println("Did not find RC4 stream");
+ }
+
+ if (DEBUG) System.out.println("[-] send encrypted");
outgoingHandler.unblock();
incomingHandler.unblock();
}).start();
-
-
}
- private List searchForPossibleRC4Tables(List snippets) {
- List result;
+
+
+
+
+ private List searchForPossibleRC4Tables(List snippets) {
+ List result;
client.pauseProcess();
- if (hasChangedFromLastCheck) {
- result = client.differentiate(snippets, true, 255);
- hasChangedFromLastCheck = false;
- }
- else {
- result = client.differentiate(snippets, false, 4);
- }
+ result = client.differentiate2(snippets, ((addedBytes * 2) / 3), addedBytes * 2, 1028);
+ addedBytes = 0;
client.resumeProcess();
return result;
}
- private long getTotalBytesLengthOfDiff(List snippets) {
+ private void printBooleanArray(boolean[] booleans) {
+ StringBuilder builder = new StringBuilder();
+ for (boolean bool : booleans) {
+ builder.append(bool ? "1" : "0");
+ }
+ System.out.println(builder);
+ }
+ private void printByteArray(byte[] booleans) {
+ StringBuilder builder = new StringBuilder();
+ for (byte bool : booleans) {
+ builder.append(bool);
+ builder.append(",");
+ }
+ System.out.println(builder);
+ }
+ private long getTotalBytesLengthOfDiff(List snippets) {
long tot = 0;
- for (FlashClient.MemorySnippet snippet : snippets) {
+ for (MemorySnippet snippet : snippets) {
tot += (snippet.getData().length);
}
return tot;
}
-
private void sleep(int ms) {
try {
Thread.sleep(ms);
diff --git a/src/main/protocol/packethandler/BufferListener.java b/src/main/protocol/packethandler/BufferListener.java
index 1a459fb..8e346f6 100644
--- a/src/main/protocol/packethandler/BufferListener.java
+++ b/src/main/protocol/packethandler/BufferListener.java
@@ -3,6 +3,6 @@ package main.protocol.packethandler;
public interface BufferListener {
- void act();
+ void act(int addedbytes);
}
diff --git a/src/main/protocol/packethandler/Handler.java b/src/main/protocol/packethandler/Handler.java
index 054368e..638eb21 100644
--- a/src/main/protocol/packethandler/Handler.java
+++ b/src/main/protocol/packethandler/Handler.java
@@ -12,8 +12,8 @@ public abstract class Handler {
volatile PayloadBuffer payloadBuffer = new PayloadBuffer();
volatile OutputStream out;
- private volatile Object[] listeners = null; //get notified on packet send
- private volatile boolean isTempBlocked = false;
+ volatile Object[] listeners = null; //get notified on packet send
+ volatile boolean isTempBlocked = false;
volatile boolean isDataStream = false;
volatile int currentIndex = 0;
@@ -32,16 +32,11 @@ public abstract class Handler {
if (isDataStream) {
payloadBuffer.push(buffer);
- notifyBufferListeners();
+ notifyBufferListeners(buffer.length);
if (!isTempBlocked) {
flush();
}
- else {
- if (this instanceof OutgoingHandler) {
- System.out.println("blocked outgoing bytes with size: "+ buffer.length);
- }
- }
}
else {
out.write(buffer);
@@ -88,9 +83,9 @@ public abstract class Handler {
public void removeBufferListener(BufferListener listener) {
bufferListeners.remove(listener);
}
- private void notifyBufferListeners() {
+ void notifyBufferListeners(int addedbytes) {
for (int i = bufferListeners.size() - 1; i >= 0; i -= 1) {
- bufferListeners.get(i).act();
+ bufferListeners.get(i).act(addedbytes);
}
}
diff --git a/src/main/protocol/packethandler/IncomingHandler.java b/src/main/protocol/packethandler/IncomingHandler.java
index b830469..ae17a1c 100644
--- a/src/main/protocol/packethandler/IncomingHandler.java
+++ b/src/main/protocol/packethandler/IncomingHandler.java
@@ -13,34 +13,35 @@ public class IncomingHandler extends Handler {
super(outputStream);
}
- @Override
- public void setAsDataStream() {
- super.setAsDataStream();
- Rc4Obtainer.rc4Obtainer.setIncomingHandler(this);
- }
+ private final Object lock = new Object();
@Override
public void sendToStream(byte[] buffer) {
- try {
- out.write(buffer);
- out.flush();
- } catch (IOException e) {
- e.printStackTrace();
+ synchronized (lock) {
+ try {
+ out.write(buffer);
+ out.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
@Override
public void flush() throws IOException {
- HPacket[] hpackets = payloadBuffer.receive();
+ synchronized (lock) {
+ HPacket[] hpackets = payloadBuffer.receive();
- for (HPacket hpacket : hpackets){
- HMessage hMessage = new HMessage(hpacket, HMessage.Side.TOCLIENT, currentIndex);
- notifyListeners(hMessage);
+ for (HPacket hpacket : hpackets){
+ HMessage hMessage = new HMessage(hpacket, HMessage.Side.TOCLIENT, currentIndex);
+ notifyListeners(hMessage);
- if (!hMessage.isBlocked()) {
- out.write(hMessage.getPacket().toBytes());
+ if (!hMessage.isBlocked()) {
+ out.write(hMessage.getPacket().toBytes());
+ }
+ currentIndex++;
}
- currentIndex++;
}
+
}
}
diff --git a/src/main/protocol/packethandler/OutgoingHandler.java b/src/main/protocol/packethandler/OutgoingHandler.java
index ba83af8..a5938d0 100644
--- a/src/main/protocol/packethandler/OutgoingHandler.java
+++ b/src/main/protocol/packethandler/OutgoingHandler.java
@@ -2,14 +2,23 @@ package main.protocol.packethandler;
import main.protocol.HMessage;
import main.protocol.HPacket;
+import main.protocol.crypto.RC4;
import main.protocol.memory.Rc4Obtainer;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
public class OutgoingHandler extends Handler {
+ private final Object lock = new Object();
+
+
private final static int encryptOffset = 3; //all packets with index < 3 aren't encrypted
+ private RC4 clientcipher = null;
+ private RC4 servercipher = null;
+ private List tempEncryptedBuffer = new ArrayList<>();
public OutgoingHandler(OutputStream outputStream) {
super(outputStream);
@@ -19,49 +28,101 @@ public class OutgoingHandler extends Handler {
if (!isDataStream) {
HPacket hpacket = new HPacket(buffer);
isDataStream = (hpacket.getBytesLength() > 6 && hpacket.headerId() == 4000 && hpacket.headerId() == 4000);
- if (isDataStream) {
- Rc4Obtainer.initialize();
- Rc4Obtainer.rc4Obtainer.setOutgoingHandler(this);
- }
}
}
@Override
public void act(byte[] buffer, Object[] listeners) throws IOException {
dataStreamCheck(buffer);
- super.act(buffer, listeners);
+ this.listeners = listeners;
+
+ if (isDataStream) {
+
+ if (currentIndex < encryptOffset) {
+ payloadBuffer.push(buffer);
+ }
+ else if (clientcipher == null) {
+ for (int i = 0; i < buffer.length; i++) {
+ tempEncryptedBuffer.add(buffer[i]);
+ }
+ }
+ else {
+ payloadBuffer.push(clientcipher.rc4(buffer));
+ }
+
+ notifyBufferListeners(buffer.length);
+
+ if (!isTempBlocked) {
+ flush();
+ }
+ }
+ else {
+ out.write(buffer);
+ }
}
@Override
public void sendToStream(byte[] buffer) {
+ synchronized (lock) {
+ try {
+ out.write(servercipher.rc4(buffer));
+ out.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
+ public void setRc4(RC4 rc4) {
+ this.clientcipher = rc4;
+ this.servercipher = rc4.deepCopy();
+
+ byte[] encrbuffer = new byte[tempEncryptedBuffer.size()];
+ for (int i = 0; i < tempEncryptedBuffer.size(); i++) {
+ encrbuffer[i] = tempEncryptedBuffer.get(i);
+ }
+
+ try {
+ act(encrbuffer, this.listeners);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ tempEncryptedBuffer = null;
+ }
+ public List getEncryptedBuffer() {
+ return tempEncryptedBuffer;
+ }
+
+
+ //as pings & pongs are used in order to find the RC4 table, we really don't want it to be displayed
+ //or even be sent to the server, we can fix that by calling this method everytime we fakesend a ping
+ private int skipPongAmount = 0;
+ public void fakePongAlert() {
+ skipPongAmount ++;
+ }
+
@Override
public void flush() throws IOException {
-
- if (currentIndex < encryptOffset) {
+ synchronized (lock) {
HPacket[] hpackets = payloadBuffer.receive();
for (HPacket hpacket : hpackets){
+ if (skipPongAmount > 0 && hpacket.length() == 2) {
+ skipPongAmount --;
+ continue;
+ }
+
HMessage hMessage = new HMessage(hpacket, HMessage.Side.TOSERVER, currentIndex);
notifyListeners(hMessage);
if (!hMessage.isBlocked()) {
- out.write(hMessage.getPacket().toBytes());
+ out.write(
+ currentIndex < encryptOffset ? hMessage.getPacket().toBytes() :
+ servercipher.rc4(hMessage.getPacket().toBytes())
+ );
}
currentIndex ++;
}
}
- if (currentIndex >= encryptOffset) {
- if (payloadBuffer.peak().length > 0) {
- HPacket packet = new HPacket(payloadBuffer.forceClear());
- HMessage hMessage = new HMessage(packet, HMessage.Side.TOSERVER, currentIndex);
-
- notifyListeners(hMessage);
- out.write(packet.toBytes());
- currentIndex++;
- }
-
- }
}
}