diff --git a/lib/attach.dll b/lib/attach.dll
new file mode 100644
index 0000000..10421f1
Binary files /dev/null and b/lib/attach.dll differ
diff --git a/lib/tools.jar b/lib/tools.jar
new file mode 100644
index 0000000..884a0d0
Binary files /dev/null and b/lib/tools.jar differ
diff --git a/releases/memEaterBug-1.0.zip b/releases/memEaterBug-1.0.zip
new file mode 100644
index 0000000..fb5f27a
Binary files /dev/null and b/releases/memEaterBug-1.0.zip differ
diff --git a/res/examples/SpaceInvaders.jar b/res/examples/SpaceInvaders.jar
new file mode 100644
index 0000000..644dd86
Binary files /dev/null and b/res/examples/SpaceInvaders.jar differ
diff --git a/res/examples/SpaceInvadersInjection.jar b/res/examples/SpaceInvadersInjection.jar
new file mode 100644
index 0000000..dfdcfd9
Binary files /dev/null and b/res/examples/SpaceInvadersInjection.jar differ
diff --git a/src/de/zabuza/memeaterbug/MemEaterBug.java b/src/de/zabuza/memeaterbug/MemEaterBug.java
index 4f5e379..629b306 100644
--- a/src/de/zabuza/memeaterbug/MemEaterBug.java
+++ b/src/de/zabuza/memeaterbug/MemEaterBug.java
@@ -2,6 +2,8 @@
import com.sun.jna.platform.win32.WinNT.HANDLE;
+import de.zabuza.memeaterbug.exceptions.NotHookedException;
+import de.zabuza.memeaterbug.injection.Injector;
import de.zabuza.memeaterbug.locale.ErrorMessages;
import de.zabuza.memeaterbug.memory.MemManipulator;
import de.zabuza.memeaterbug.util.Masks;
@@ -26,6 +28,10 @@
*/
public final class MemEaterBug {
+ /**
+ * Injector for the current process handle, if hooked, null else.
+ */
+ private Injector mInjector;
/**
* If the current process runs in an 64 bit environment or not. Can only be
* accessed after the the Mem-Eater-Bug was hooked to a process using
@@ -73,6 +79,7 @@ public MemEaterBug(final int processId) {
mIsHooked = false;
mProcessHandle = null;
mMemManipulator = null;
+ mInjector = null;
if (processId == 0) {
throw new IllegalArgumentException(ErrorMessages.PROCESS_NOT_FOUND);
@@ -115,6 +122,21 @@ public MemEaterBug(final String processClassName, final String windowTitle) {
this(User32Util.getWindowThreadProcessIdByClassAndTitle(processClassName, windowTitle).getValue());
}
+ /**
+ * Gets an object for injecting code into the hooked process.
+ *
+ * @return An object for injecting code into the hooked process.
+ * @throws IllegalStateException
+ * If the Mem-Eater-Bug is not hooked to a process
+ */
+ public Injector getInjector() throws IllegalStateException {
+ ensureIsHooked();
+ if (mInjector == null) {
+ mInjector = new Injector(mProcessId, mProcessHandle);
+ }
+ return mInjector;
+ }
+
/**
* Gets an object for memory manipulation of the hooked process.
*
@@ -224,6 +246,7 @@ public void unhookProcess() {
}
mProcessHandle = null;
mMemManipulator = null;
+ mInjector = null;
mIsHooked = false;
}
@@ -236,7 +259,7 @@ public void unhookProcess() {
*/
private void ensureIsHooked() throws IllegalStateException {
if (!mIsHooked) {
- throw new IllegalStateException(ErrorMessages.UNABLE_SINCE_NOT_HOOKED);
+ throw new NotHookedException(ErrorMessages.UNABLE_SINCE_NOT_HOOKED);
}
}
diff --git a/src/de/zabuza/memeaterbug/examples/SoliScorer.java b/src/de/zabuza/memeaterbug/examples/SoliScorer.java
index 0884534..4619fdd 100644
--- a/src/de/zabuza/memeaterbug/examples/SoliScorer.java
+++ b/src/de/zabuza/memeaterbug/examples/SoliScorer.java
@@ -50,4 +50,11 @@ public static void main(final String[] args) {
// Unhook from the game
memEaterBug.unhookProcess();
}
+
+ /**
+ * Utility class. No implementation.
+ */
+ private SoliScorer() {
+
+ }
}
diff --git a/src/de/zabuza/memeaterbug/examples/SpaceInvadersInjection.java b/src/de/zabuza/memeaterbug/examples/SpaceInvadersInjection.java
new file mode 100644
index 0000000..95a8bb7
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/examples/SpaceInvadersInjection.java
@@ -0,0 +1,41 @@
+package de.zabuza.memeaterbug.examples;
+
+import java.lang.instrument.Instrumentation;
+
+/**
+ * Hack for the popular game Space Invaders that displays various information on
+ * the game screen by jar-injection.
+ *
+ * This is the agent as jar that gets injected inside the Space Invaders
+ * jar-file.
+ *
+ * @author Zabuza
+ *
+ */
+public final class SpaceInvadersInjection {
+
+ /**
+ * JVM hook to dynamically load this agent at runtime.
+ *
+ * @param args
+ * Passed arguments, not supported
+ * @param inst
+ * Object used for ByteCode manipulation
+ */
+ public static void agentmain(final String args, final Instrumentation inst) {
+ try {
+ System.out.println("Injected the agent.");
+ } catch (Exception e) {
+ // Catch and print every exception as they would otherwise be
+ // ignored in an agentmain method
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Utility class. No implementation.
+ */
+ private SpaceInvadersInjection() {
+
+ }
+}
diff --git a/src/de/zabuza/memeaterbug/examples/SpaceInvadersInjector.java b/src/de/zabuza/memeaterbug/examples/SpaceInvadersInjector.java
new file mode 100644
index 0000000..458778a
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/examples/SpaceInvadersInjector.java
@@ -0,0 +1,48 @@
+package de.zabuza.memeaterbug.examples;
+
+import de.zabuza.memeaterbug.MemEaterBug;
+import de.zabuza.memeaterbug.injection.Injector;
+
+/**
+ * Hack for the popular game Space Invaders that displays various information on
+ * the game screen by jar-injection.
+ *
+ * @author Zabuza
+ *
+ */
+public final class SpaceInvadersInjector {
+ /**
+ * Demonstrates the usage of the Mem-Eater-Bug for jar-injection by
+ * displaying various information on the game screen of the game Space
+ * Invaders.
+ *
+ * The program was tested on a Windows 10 64-bit system using the provided
+ * SpaceInvaders.jar file.
+ *
+ * @param args
+ * Not supported
+ */
+ public static void main(final String[] args) {
+ // Constants
+ String windowTitle = "Space Invaders 101";
+ String pathToInjectionAgent = "C:\\Users\\Zabuza\\Desktop\\SpaceInvadersInjection.jar";
+
+ // Hook to the game
+ MemEaterBug memEaterBug = new MemEaterBug(null, windowTitle);
+ memEaterBug.hookProcess();
+ Injector injector = memEaterBug.getInjector();
+
+ // Inject the agent jar into the target jar
+ injector.injectJarIntoJar(pathToInjectionAgent);
+
+ // Unhook from the game
+ memEaterBug.unhookProcess();
+ }
+
+ /**
+ * Utility class. No implementation.
+ */
+ private SpaceInvadersInjector() {
+
+ }
+}
diff --git a/src/de/zabuza/memeaterbug/exceptions/NotHookedException.java b/src/de/zabuza/memeaterbug/exceptions/NotHookedException.java
new file mode 100644
index 0000000..512ca29
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/exceptions/NotHookedException.java
@@ -0,0 +1,35 @@
+package de.zabuza.memeaterbug.exceptions;
+
+/**
+ * Thrown when a method could not be executed since the
+ * {@link de.zabuza.memeaterbug.MemEaterBug MemEaterBug} was not hooked to a
+ * process.
+ *
+ * @author Zabuza
+ *
+ */
+public final class NotHookedException extends RuntimeException {
+
+ /**
+ * Serial UID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new exception without a detailed description.
+ */
+ public NotHookedException() {
+ super();
+ }
+
+ /**
+ * Creates a new exception with a given description.
+ *
+ * @param description
+ * Description of the exception
+ */
+ public NotHookedException(final String description) {
+ super(description);
+ }
+
+}
diff --git a/src/de/zabuza/memeaterbug/exceptions/UnableToInjectException.java b/src/de/zabuza/memeaterbug/exceptions/UnableToInjectException.java
new file mode 100644
index 0000000..40683a4
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/exceptions/UnableToInjectException.java
@@ -0,0 +1,34 @@
+package de.zabuza.memeaterbug.exceptions;
+
+/**
+ * Thrown when an {@link de.zabuza.memeaterbug.injection.Injector Injector}
+ * method could not inject code into the given process.
+ *
+ * @author Zabuza
+ *
+ */
+public final class UnableToInjectException extends RuntimeException {
+
+ /**
+ * Serial UID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new exception without a detailed description.
+ */
+ public UnableToInjectException() {
+ super();
+ }
+
+ /**
+ * Creates a new exception with a given description.
+ *
+ * @param description
+ * Description of the exception
+ */
+ public UnableToInjectException(final String description) {
+ super(description);
+ }
+
+}
diff --git a/src/de/zabuza/memeaterbug/exceptions/package-info.java b/src/de/zabuza/memeaterbug/exceptions/package-info.java
new file mode 100644
index 0000000..6afe2b9
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/exceptions/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * This is the core package for exceptions and error handling for Mem-Eater-Bug.
+ */
+package de.zabuza.memeaterbug.exceptions;
\ No newline at end of file
diff --git a/src/de/zabuza/memeaterbug/injection/Injector.java b/src/de/zabuza/memeaterbug/injection/Injector.java
new file mode 100644
index 0000000..2b15649
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/injection/Injector.java
@@ -0,0 +1,115 @@
+package de.zabuza.memeaterbug.injection;
+
+import java.io.IOException;
+
+import com.sun.jna.platform.win32.WinNT.HANDLE;
+import com.sun.tools.attach.AgentInitializationException;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.VirtualMachine;
+
+import de.zabuza.memeaterbug.exceptions.UnableToInjectException;
+import de.zabuza.memeaterbug.locale.ErrorMessages;
+import de.zabuza.memeaterbug.winapi.Process;
+import de.zabuza.memeaterbug.winapi.jna.util.PsapiUtil;
+
+/**
+ * Provides various methods for injecting code into a given process.
+ *
+ * @author Zabuza
+ *
+ */
+public final class Injector {
+
+ /**
+ * Name of the attach library that is used for attaching to a virtual
+ * machine.
+ */
+ private static final String ATTACH_LIBRARY_NAME = "attach";
+
+ /**
+ * The process this object belongs to.
+ */
+ private final Process mProcess;
+
+ /**
+ * Creates a new object that is able to inject code into the given process.
+ *
+ * @param processId
+ * Id of the process to inject into
+ */
+ public Injector(final int processId) {
+ this(processId, null);
+ }
+
+ /**
+ * Creates a new object that is able to inject code into the given process.
+ *
+ * @param processId
+ * Id of the process to inject into
+ * @param processHandle
+ * An optional previously created handle object that must
+ * correspond to the same process that is specified by processId.
+ * Using null results in the creation of a default
+ * handle, that has all access rights.
+ */
+ public Injector(final int processId, final HANDLE processHandle) {
+ mProcess = PsapiUtil.getProcessById(processId);
+ if (processHandle != null) {
+ mProcess.setHandle(processHandle);
+ }
+ loadAttachLibrary();
+ }
+
+ /**
+ * Loads the native attach library into the built path. It is used for
+ * attaching to a virtual machine.
+ */
+ private void loadAttachLibrary() {
+ System.loadLibrary(ATTACH_LIBRARY_NAME);
+ }
+
+ /**
+ * Injects a given agent jar-file into the hooked process. The hooked
+ * process also needs to be a jar-file.
+ *
+ * @param pathToAgentJar
+ * Path to the agent jar-file to inject. The agent jar-file needs
+ * to specify an agentmain-method and must have the Agent-Class
+ * key accordingly.
+ * @throws UnableToInjectException
+ * If the operation was unable to inject the agent jar-file into
+ * the target jar-file
+ */
+ public void injectJarIntoJar(final String pathToAgentJar) throws UnableToInjectException {
+ try {
+ VirtualMachine vm = VirtualMachine.attach("" + mProcess.getPid());
+ vm.loadAgent(pathToAgentJar);
+ vm.detach();
+ } catch (AttachNotSupportedException | AgentLoadException | AgentInitializationException | IOException e) {
+ throw new UnableToInjectException(ErrorMessages.UNABLE_TO_INJECT_JAR_INTO_JAR);
+ }
+ }
+
+ /**
+ * Injects a given agent library into the hooked process. The hooked process
+ * needs to be a jar-file.
+ *
+ * @param pathToAgentLibrary
+ * Path to the agent library to inject. The agent library needs
+ * to specify all needed agent-methods via the native agent
+ * interface.
+ * @throws UnableToInjectException
+ * If the operation was unable to inject the agent library into
+ * the target jar-file
+ */
+ public void injectLibraryIntoJar(final String pathToAgentLibrary) throws UnableToInjectException {
+ try {
+ VirtualMachine vm = VirtualMachine.attach("" + mProcess.getPid());
+ vm.loadAgentLibrary(pathToAgentLibrary);
+ vm.detach();
+ } catch (AttachNotSupportedException | AgentLoadException | AgentInitializationException | IOException e) {
+ throw new UnableToInjectException(ErrorMessages.UNABLE_TO_INJECT_LIBRARY_INTO_JAR);
+ }
+ }
+}
diff --git a/src/de/zabuza/memeaterbug/injection/package-info.java b/src/de/zabuza/memeaterbug/injection/package-info.java
new file mode 100644
index 0000000..67083af
--- /dev/null
+++ b/src/de/zabuza/memeaterbug/injection/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * This is the core package for injecting code into processes.
+ */
+package de.zabuza.memeaterbug.injection;
\ No newline at end of file
diff --git a/src/de/zabuza/memeaterbug/locale/ErrorMessages.java b/src/de/zabuza/memeaterbug/locale/ErrorMessages.java
index cbe629f..95cb8c2 100644
--- a/src/de/zabuza/memeaterbug/locale/ErrorMessages.java
+++ b/src/de/zabuza/memeaterbug/locale/ErrorMessages.java
@@ -40,6 +40,16 @@ public final class ErrorMessages {
* process.
*/
public static final String UNABLE_SINCE_NOT_HOOKED = "Unable to execute since not hooked to a process. First hook, then try again.";
+ /**
+ * Thrown when an {@link de.zabuza.memeaterbug.injection.Injector Injector}
+ * method could not inject an agent jar file into a target jar file.
+ */
+ public static final String UNABLE_TO_INJECT_JAR_INTO_JAR = "Unable to inject the agent jar into the target jar. Ensure the target process is a jar-file and you have all needed permissions. Also make sure the agent jar specifies an agentmain-method and has set the Agent-Class key accordingly.";
+ /**
+ * Thrown when an {@link de.zabuza.memeaterbug.injection.Injector Injector}
+ * method could not inject an agent jar file into a target jar file.
+ */
+ public static final String UNABLE_TO_INJECT_LIBRARY_INTO_JAR = "Unable to inject the agent library into the target jar. Ensure the target process is a jar-file and you have all needed permissions. Also make sure the agent library specifies all needed agent-methods via the native agent interface.";
/**
* Utility class. No implementation.