initial commit

master
Peter "Marenthyu" Fredebold 5 years ago
commit 43405b956d
  1. 3
      src/META-INF/MANIFEST.MF
  2. 50
      src/de/marenthyu/memedit/Main.java
  3. 16
      src/de/marenthyu/memedit/bunny/BunnyConstants.java
  4. 194
      src/de/marenthyu/memedit/bunny/BunnyMemoryManager.java
  5. 38
      src/de/marenthyu/memedit/util/Kernel32.java
  6. 103
      src/de/marenthyu/memedit/util/Shared.java
  7. 196
      src/de/marenthyu/memedit/util/User32.java

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: de.marenthyu.memedit.Main

@ -0,0 +1,50 @@
package de.marenthyu.memedit;
import de.marenthyu.memedit.bunny.BunnyMemoryManager;
import de.marenthyu.twitch.auth.AuthStore;
import de.marenthyu.twitch.auth.oauth.OAuthToken;
import de.marenthyu.twitch.pubsub.PubSubClient;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
public class Main {
private static final String CLIENT_ID = "ckqn7b448jawx00ar8pp5yq8l6a9kc";
public static void main(String[] args) {
AuthStore.init(CLIENT_ID);
while (!AuthStore.isInitialized()) {
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
OAuthToken token = AuthStore.getToken();
PubSubClient pubSub = null;
try {
ArrayList<String> topics = new ArrayList<String>();
topics.add("channel-points-channel-v1." + token.getUserID());
pubSub = new PubSubClient(token, topics);
} catch (URISyntaxException e) {
e.printStackTrace();
}
BunnyMemoryManager.init();
// Okay, we found bunny - time to do some stuff
assert pubSub != null;
BunnyMemoryManager.addSetHPHandler(pubSub);
BunnyMemoryManager.addFullHealHandler(pubSub);
BunnyMemoryManager.addHealHandler(pubSub);
BunnyMemoryManager.addBadgeHandlers(pubSub);
System.out.println("============= SETUP COMPLETE! Leaving this running should work now. Close this window to kill it. =============");
}
}

@ -0,0 +1,16 @@
package de.marenthyu.memedit.bunny;
public class BunnyConstants {
final static String RABI_TITLE = "Rabi-Ribi ver 1.99t";
final static int RABI_SAVBLOCK_OFFSET = 0x01689290;
final static int[] RABI_HEALTH_OFFSETS_IN_SAVBLOCK = {0x4DC};
final static int[] RABI_MAX_HEALTH_OFFSETS_IN_SAVBLOCK = {0x4EC};
final static int[] RABI_MANA_OFFSETS_IN_SAVBLOCK = {0x6BC}; // It's a float!
final static int RABI_BADGE_ARRAY_BASE_POINTER_OFFSET = 0x002ED130; // This still is a pointerpath, with offset 0 as the only one.
final static String[] RABI_BADGES = {"HEALTH_UP", "HEALTH_SURGE", "MANA_UP", "MANA_SURGE", "CRISIS_BOOST",
"ATTACK_GROW", "DEFENSE_GROW", "ATTACK_TRADE", "DEFENSE_TRADE", "ARM_STRENGTH", "CARROT_BOOST", "WEAKEN",
"SELF_DEFENSE", "ARMORED", "LUCKY_SEVEN", "HEX_CANCEL", "PURE_LOVE", "TOXIC_STRIKE",
"FRAME_CANCEL", "HEALTH_WAGER", "MANA_WAGER", "STAMINA_PLUS", "BLESSED", "HITBOX_DOWN", "CASHBACK",
"SURVIVAL", "TOP_FORM", "TOUGH_SKIN", "ERINA_BADGE", "RIBBON_BADGE", "AUTO_TRIGGER", "LILITHS_GIFT"};
}

@ -0,0 +1,194 @@
package de.marenthyu.memedit.bunny;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import de.marenthyu.twitch.pubsub.PubSubClient;
import de.marenthyu.twitch.pubsub.channelpoints.ChannelPointsRedemptionHandler;
import javax.swing.*;
import java.io.IOException;
import static de.marenthyu.memedit.bunny.BunnyConstants.*;
import static de.marenthyu.memedit.util.Shared.*;
public class BunnyMemoryManager {
static int RABI_BASE_SIZE;
public static Pointer bunnyProcess;
public static int bunnyPID;
public static void init() {
bunnyPID = getProcessId(RABI_TITLE);
System.out.println("[BUNNY] Bunny PID: " + bunnyPID);
bunnyProcess = openProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, bunnyPID);
try {
RABI_BASE_SIZE = getBaseAddress("rabiribi.exe");
if (RABI_BASE_SIZE == 0) {
throw new IOException("Invalid Size Returned from Powershell");
}
} catch (NumberFormatException | IOException e) {
// e.printStackTrace();
System.out.println();
System.out.println("[BUNNY] Error getting the Module base address automatically, asking user.");
String userInput = JOptionPane.showInputDialog("Please Enter the base address of rabiribi.exe\n If you dare, please help me automate this. I am at the end of my knowledge. If you don't know how to do this, ask whoever linked you this software.");
try {
RABI_BASE_SIZE = Integer.decode(userInput);
} catch (Exception y) {
try {
RABI_BASE_SIZE = Integer.decode("0x" + userInput);
} catch (Exception ex) {
System.out.println("[BUNNY] You're stupid. I think. something went wrong.");
e.printStackTrace();
ex.printStackTrace();
System.exit(2);
}
}
}
if (bunnyPID == 0) {
System.err.println("[BUNNY] COULD NOT LOCATE PID FOR " + RABI_TITLE + " - PLEASE MAKE SURE THE GAME IS RUNNING AND ON THE SPECIFIED VERSION!");
System.exit(1);
}
}
public static void addSetHPHandler(PubSubClient pubSub) {
pubSub.addChannelPointsRedemptionHandler(new ChannelPointsRedemptionHandler("[BUNNY][HP]") {
@Override
public void matched(String input) {
try {
int newHeahlth = Integer.parseInt(input);
setHP(newHeahlth);
System.out.println("[BUNNY][HP] HP set to " + newHeahlth);
} catch (NumberFormatException e) {
System.err.println("[BUNNY][HP] Invalid Number.");
}
}
});
}
public static void addFullHealHandler(PubSubClient pubSub) {
pubSub.addChannelPointsRedemptionHandler(new ChannelPointsRedemptionHandler("[BUNNY][FULLHEAL]") {
@Override
public void matched(String input) {
fullHeal();
System.out.println("[BUNNY][FULLHEAL] Healed fully!");
}
});
}
public static void addHealHandler(PubSubClient pubSub) {
pubSub.addChannelPointsRedemptionHandler(new ChannelPointsRedemptionHandler("[BUNNY][HEAL]") {
@Override
public void matched(String input) {
try {
int amount = Integer.parseInt(input);
heal(amount);
System.out.println("[BUNNY][HEAL] Healed by " + amount);
} catch (NumberFormatException e) {
System.err.println("[BUNNY][HEAL] Invalid Number.");
}
}
});
}
public static void addBadgeHandlers(PubSubClient pubSub) {
for (int i = 0;i < RABI_BADGES.length;i++) {
for (int j = 0;j<=2;j++) {
String type;
switch (j) {
case 0:
{
type = "DELETE";
break;
}
case 1: {
type = "UNLOCK";
break;
}
case 2: {
type = "EQUIP";
break;
}
default:
throw new IllegalStateException("Unexpected value: " + j);
}
final int finalJ = j;
final int finalI = i;
pubSub.addChannelPointsRedemptionHandler(new ChannelPointsRedemptionHandler("[BUNNY][BADGE][" + type + "][" + RABI_BADGES[finalI] + "]") {
@Override
public void matched(String input) {
switch (finalJ) {
case 0:
{
removeBadge(finalI);
break;
}
case 1: {
unluckAndUnequipBadge(finalI);
break;
}
case 2: {
equipBadge(finalI);
break;
}
default:
throw new IllegalStateException("Unexpected value: " + finalJ);
}
System.out.println("[BUNNY][BADGE][" + type + "][" + RABI_BADGES[finalI] + "] Badges changed!");
}
});
}
}
}
public static void setHP(int newHeahlth) {
System.out.println("[BUNNY] Got request to change HP - setting it to " + newHeahlth);
long dynAddress = findDynAddress(bunnyProcess, RABI_HEALTH_OFFSETS_IN_SAVBLOCK, RABI_BASE_SIZE + RABI_SAVBLOCK_OFFSET);
int curHealth = getCurHP();
System.out.println(String.format("[BUNNY] Old health read from memory was: %d, setting it to %d", curHealth, newHeahlth));
writeMemory(bunnyProcess, dynAddress, intToBytes(newHeahlth));
}
public static int getCurHP() {
long dynAddress = findDynAddress(bunnyProcess, RABI_HEALTH_OFFSETS_IN_SAVBLOCK, RABI_BASE_SIZE + RABI_SAVBLOCK_OFFSET);
Memory healthCurrentMem = readMemory(bunnyProcess, dynAddress, 4);
return healthCurrentMem.getInt(0);
}
public static int getMaxHP() {
long dynAddress = findDynAddress(bunnyProcess, RABI_MAX_HEALTH_OFFSETS_IN_SAVBLOCK, RABI_BASE_SIZE + RABI_SAVBLOCK_OFFSET);
Memory healthCurrentMem = readMemory(bunnyProcess, dynAddress, 4);
return healthCurrentMem.getInt(0);
}
public static void heal(int amount) {
setHP(getCurHP() + amount);
}
public static void fullHeal() {
setHP(getMaxHP());
}
public static void equipBadge(int badgeID) {
long dynAddress = findDynAddress(bunnyProcess, new int[]{badgeID * 4}, RABI_BASE_SIZE + RABI_BADGE_ARRAY_BASE_POINTER_OFFSET);
writeMemory(bunnyProcess, dynAddress, new byte[]{0x02});
}
public static void unluckAndUnequipBadge(int badgeID) {
long dynAddress = findDynAddress(bunnyProcess, new int[]{badgeID * 4}, RABI_BASE_SIZE + RABI_BADGE_ARRAY_BASE_POINTER_OFFSET);
writeMemory(bunnyProcess, dynAddress, new byte[]{0x01});
}
public static void removeBadge(int badgeID) {
long dynAddress = findDynAddress(bunnyProcess, new int[]{badgeID * 4}, RABI_BASE_SIZE + RABI_BADGE_ARRAY_BASE_POINTER_OFFSET);
writeMemory(bunnyProcess, dynAddress, new byte[]{0x00});
}
}

@ -0,0 +1,38 @@
package de.marenthyu.memedit.util;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
public interface Kernel32 extends StdCallLibrary {
// description from msdn
//BOOL WINAPI WriteProcessMemory(
//__in HANDLE hProcess,
//__in LPVOID lpBaseAddress,
//__in LPCVOID lpBuffer,
//__in SIZE_T nSize,
//__out SIZE_T *lpNumberOfBytesWritten
//);
boolean WriteProcessMemory(Pointer p, long address, Pointer buffer, int size, IntByReference written);
//BOOL WINAPI ReadProcessMemory(
// __in HANDLE hProcess,
// __in LPCVOID lpBaseAddress,
// __out LPVOID lpBuffer,
// __in SIZE_T nSize,
// __out SIZE_T *lpNumberOfBytesRead
// );
boolean ReadProcessMemory(Pointer hProcess, long inBaseAddress, Pointer outputBuffer, int nSize, IntByReference outNumberOfBytesRead);
//HANDLE WINAPI OpenProcess(
// __in DWORD dwDesiredAccess,
// __in BOOL bInheritHandle,
// __in DWORD dwProcessId
//);
Pointer OpenProcess(int desired, boolean inherit, int pid);
/* derp */
int GetLastError();
}

@ -0,0 +1,103 @@
package de.marenthyu.memedit.util;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Shared {
static Kernel32 kernel32 = Native.load("kernel32", Kernel32.class);
static User32 user32 = Native.load("user32", User32.class);
public static int PROCESS_VM_READ = 0x0010;
public static int PROCESS_VM_WRITE = 0x0020;
public static int PROCESS_VM_OPERATION = 0x0008;
public static int getProcessId(String window) {
IntByReference pid = new IntByReference(0);
user32.GetWindowThreadProcessId(user32.FindWindowA(null, window), pid);
return pid.getValue();
}
public static Pointer openProcess(int permissions, int pid) {
Pointer process = kernel32.OpenProcess(permissions, true, pid);
return process;
}
public static long findDynAddress(Pointer process, int[] offsets, long baseAddress) {
long pointer = baseAddress;
int size = 4;
Memory pTemp = new Memory(size);
long pointerAddress = 0;
// System.out.println("initial pointerAddress: " + String.format("0x%X", pointer));
for (int i = 0; i < offsets.length; i++) {
if (i == 0) {
kernel32.ReadProcessMemory(process, pointer, pTemp, size, null);
}
pointerAddress = ((pTemp.getInt(0) + offsets[i]));
// System.out.println("Current pointerAddress: " + String.format("0x%X", pointerAddress));
if (i != offsets.length - 1)
kernel32.ReadProcessMemory(process, pointerAddress, pTemp, size, null);
}
return pointerAddress;
}
public static Memory readMemory(Pointer process, long address, int bytesToRead) {
IntByReference read = new IntByReference(0);
Memory output = new Memory(bytesToRead);
kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
return output;
}
public static void writeMemory(Pointer process, long address, byte[] data) {
int size = data.length;
Memory toWrite = new Memory(size);
for (int i = 0; i < size; i++) {
toWrite.setByte(i, data[i]);
}
boolean b = kernel32.WriteProcessMemory(process, address, toWrite, size, null);
}
public static byte[] intToBytes(final int data) {
return new byte[]{
(byte) ((data >> 0) & 0xff),
(byte) ((data >> 8) & 0xff),
(byte) ((data >> 16) & 0xff),
(byte) ((data >> 24) & 0xff)
};
}
public static int getBaseAddress(String executableName) throws IOException {
String command = "powershell.exe \"$modules = Get-Process " + executableName.split("\\.")[0] + " -Module; $modules[0].BaseAddress;\"";
// Executing the command
Process powerShellProcess = Runtime.getRuntime().exec(command);
// Getting the results
powerShellProcess.getOutputStream().close();
String line;
BufferedReader stdout = new BufferedReader(new InputStreamReader(
powerShellProcess.getInputStream()));
StringBuilder output = new StringBuilder();
while ((line = stdout.readLine()) != null) {
output.append(line);
}
stdout.close();
return Integer.parseInt(output.toString());
}
}

@ -0,0 +1,196 @@
package de.marenthyu.memedit.util;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APIOptions;
public interface User32 extends W32APIOptions {
User32 INSTANCE = Native.load("user32", User32.class, DEFAULT_OPTIONS);
Pointer GetDC(Pointer hWnd);
int ReleaseDC(Pointer hWnd, Pointer hDC);
int FLASHW_STOP = 0;
int FLASHW_CAPTION = 1;
int FLASHW_TRAY = 2;
int FLASHW_ALL = (FLASHW_CAPTION | FLASHW_TRAY);
int FLASHW_TIMER = 4;
int FLASHW_TIMERNOFG = 12;
public static class FLASHWINFO extends Structure {
public int cbSize;
public Pointer hWnd;
public int dwFlags;
public int uCount;
public int dwTimeout;
}
int IMAGE_BITMAP = 0;
int IMAGE_ICON = 1;
int IMAGE_CURSOR = 2;
int IMAGE_ENHMETAFILE = 3;
int LR_DEFAULTCOLOR = 0x0000;
int LR_MONOCHROME = 0x0001;
int LR_COLOR = 0x0002;
int LR_COPYRETURNORG = 0x0004;
int LR_COPYDELETEORG = 0x0008;
int LR_LOADFROMFILE = 0x0010;
int LR_LOADTRANSPARENT = 0x0020;
int LR_DEFAULTSIZE = 0x0040;
int LR_VGACOLOR = 0x0080;
int LR_LOADMAP3DCOLORS = 0x1000;
int LR_CREATEDIBSECTION = 0x2000;
int LR_COPYFROMRESOURCE = 0x4000;
int LR_SHARED = 0x8000;
Pointer FindWindowA(String winClass, String title);
int GetClassName(Pointer hWnd, byte[] lpClassName, int nMaxCount);
public static class GUITHREADINFO extends Structure {
public int cbSize = size();
public int flags;
Pointer hwndActive;
Pointer hwndFocus;
Pointer hwndCapture;
Pointer hwndMenuOwner;
Pointer hwndMoveSize;
Pointer hwndCaret;
RECT rcCaret;
}
boolean GetGUIThreadInfo(int idThread, GUITHREADINFO lpgui);
public static class WINDOWINFO extends Structure {
public int cbSize = size();
public RECT rcWindow;
public RECT rcClient;
public int dwStyle;
public int dwExStyle;
public int dwWindowStatus;
public int cxWindowBorders;
public int cyWindowBorders;
public short atomWindowType;
public short wCreatorVersion;
}
boolean GetWindowInfo(Pointer hWnd, WINDOWINFO pwi);
boolean GetWindowRect(Pointer hWnd, RECT rect);
int GetWindowText(Pointer hWnd, byte[] lpString, int nMaxCount);
int GetWindowTextLength(Pointer hWnd);
int GetWindowModuleFileName(Pointer hWnd, byte[] lpszFileName, int cchFileNameMax);
int GetWindowThreadProcessId(Pointer hWnd, IntByReference lpdwProcessId);
interface WNDENUMPROC extends StdCallCallback {
/**
* Return whether to continue enumeration.
*/
boolean callback(Pointer hWnd, Pointer data);
}
boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer data);
boolean EnumThreadWindows(int dwThreadId, WNDENUMPROC lpEnumFunc, Pointer data);
boolean FlashWindowEx(FLASHWINFO info);
Pointer LoadIcon(Pointer hInstance, String iconName);
Pointer LoadImage(Pointer hinst, // handle to instance
String name, // image to load
int type, // image type
int xDesired, // desired width
int yDesired, // desired height
int load // load options
);
boolean DestroyIcon(Pointer hicon);
int GWL_EXSTYLE = -20;
int GWL_STYLE = -16;
int GWL_WNDPROC = -4;
int GWL_HINSTANCE = -6;
int GWL_ID = -12;
int GWL_USERDATA = -21;
int DWL_DLGPROC = 4;
int DWL_MSGRESULT = 0;
int DWL_USER = 8;
int WS_EX_COMPOSITED = 0x20000000;
int WS_EX_LAYERED = 0x80000;
int WS_EX_TRANSPARENT = 32;
int GetWindowLong(Pointer hWnd, int nIndex);
int SetWindowLong(Pointer hWnd, int nIndex, int dwNewLong);
int LWA_COLORKEY = 1;
int LWA_ALPHA = 2;
int ULW_COLORKEY = 1;
int ULW_ALPHA = 2;
int ULW_OPAQUE = 4;
boolean SetLayeredWindowAttributes(Pointer hwnd, int crKey,
byte bAlpha, int dwFlags);
boolean GetLayeredWindowAttributes(Pointer hwnd,
IntByReference pcrKey,
ByteByReference pbAlpha,
IntByReference pdwFlags);
/**
* Defines the x- and y-coordinates of a point.
*/
public static class POINT extends Structure {
public int x, y;
}
/**
* Specifies the width and height of a rectangle.
*/
public static class SIZE extends Structure {
public int cx, cy;
}
int AC_SRC_OVER = 0x00;
int AC_SRC_ALPHA = 0x01;
int AC_SRC_NO_PREMULT_ALPHA = 0x01;
int AC_SRC_NO_ALPHA = 0x02;
public static class BLENDFUNCTION extends Structure {
public byte BlendOp = AC_SRC_OVER; // only valid value
public byte BlendFlags = 0; // only valid value
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
boolean UpdateLayeredWindow(Pointer hwnd, Pointer hdcDst,
POINT pptDst, SIZE psize,
Pointer hdcSrc, POINT pptSrc, int crKey,
BLENDFUNCTION pblend, int dwFlags);
int SetWindowRgn(Pointer hWnd, Pointer hRgn, boolean bRedraw);
int VK_SHIFT = 16;
int VK_LSHIFT = 0xA0;
int VK_RSHIFT = 0xA1;
int VK_CONTROL = 17;
int VK_LCONTROL = 0xA2;
int VK_RCONTROL = 0xA3;
int VK_MENU = 18;
int VK_LMENU = 0xA4;
int VK_RMENU = 0xA5;
boolean GetKeyboardState(byte[] state);
short GetAsyncKeyState(int vKey);
}
Loading…
Cancel
Save