diff --git a/.classpath b/.classpath index c49f98b..0a0f0b6 100644 --- a/.classpath +++ b/.classpath @@ -13,5 +13,7 @@ + + diff --git a/lib/jna-4.5.0.jar b/lib/jna-4.5.0.jar new file mode 100644 index 0000000..2e4eaeb Binary files /dev/null and b/lib/jna-4.5.0.jar differ diff --git a/lib/jna-platform-4.5.0.jar b/lib/jna-platform-4.5.0.jar new file mode 100644 index 0000000..e1063a6 Binary files /dev/null and b/lib/jna-platform-4.5.0.jar differ diff --git a/projectBuilder.xml b/projectBuilder.xml index 99d06c1..96a4e1b 100644 --- a/projectBuilder.xml +++ b/projectBuilder.xml @@ -23,6 +23,8 @@ + + diff --git a/sigIRCv2.jar b/sigIRCv2.jar index 3ddb610..9c78c07 100644 Binary files a/sigIRCv2.jar and b/sigIRCv2.jar differ diff --git a/src/sig/modules/RabiRibi/MemoryOffset.java b/src/sig/modules/RabiRibi/MemoryOffset.java new file mode 100644 index 0000000..e008bcc --- /dev/null +++ b/src/sig/modules/RabiRibi/MemoryOffset.java @@ -0,0 +1,28 @@ +package sig.modules.RabiRibi; + +public enum MemoryOffset { + MONEY(0xD654CC), + PLAYTIME(0xD642D8), //In frames (Rabi-Ribi runs at 60FPS). + UNKNOWN1(0xD65BDC), //???? Originally assumed to be "Health Ups". + HEALTHUP_START(0xD6342C), + HEALTHUP_END(0xD63528), + ATTACKUP_START(0xD6352C), + ATTACKUP_END(0xD63628), + MANAUP_START(0xD6362C), + MANAUP_END(0xD63728), + REGENUP_START(0xD6372C), + REGENUP_END(0xD63828), + PACKUP_START(0xD6382C), + PACKUP_END(0xD63928), + ; + + long offset; + + MemoryOffset(long offset) { + this.offset=offset; + } + + public long getOffset() { + return offset; + } +} diff --git a/src/sig/modules/RabiRibiModule.java b/src/sig/modules/RabiRibiModule.java new file mode 100644 index 0000000..90c615c --- /dev/null +++ b/src/sig/modules/RabiRibiModule.java @@ -0,0 +1,114 @@ +package sig.modules; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.geom.Rectangle2D; +import java.util.List; + +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinNT.HANDLE; + +import sig.Module; +import sig.sigIRC; +import sig.modules.RabiRibi.MemoryOffset; +import sig.modules.utils.PsapiTools; +import sig.utils.DrawUtils; + +public class RabiRibiModule extends Module{ + final int PROCESS_PERMISSIONS = WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ; + boolean foundRabiRibi = false; + int rabiRibiPID = -1; + long rabiRibiMemOffset = 0; + HANDLE rabiribiProcess = null; + + public RabiRibiModule(Rectangle2D bounds, String moduleName) { + super(bounds, moduleName); + //Initialize(); + Initialize(); + + //System.out.println("Money value is: "+readIntFromMemory(MemoryOffset.MONEY)); + } + + private void Initialize() { + List pids; + try { + pids = PsapiTools.getInstance().enumProcesses(); + for (Integer pid : pids) { + HANDLE process = Kernel32.INSTANCE.OpenProcess(PROCESS_PERMISSIONS, true, pid); + List hModules; + try { + hModules = PsapiTools.getInstance().EnumProcessModules(process); + for(sig.modules.utils.Module m: hModules){ + //System.out.println(m.getFileName()+":"+m.getEntryPoint()); + if (m.getFileName().contains("rabiribi")) { + rabiRibiMemOffset = Pointer.nativeValue(m.getLpBaseOfDll().getPointer()); + System.out.println("Found an instance of Rabi-Ribi at 0x"+Long.toHexString(rabiRibiMemOffset)); + rabiRibiPID=pid; + foundRabiRibi=true; + rabiribiProcess=process; + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + if (foundRabiRibi) { + break; + } + if (process!=null) { + Kernel32.INSTANCE.CloseHandle(process); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void ApplyConfigWindowProperties() { + sigIRC.rabiribimodule_X=(int)position.getX(); + sigIRC.rabiribimodule_Y=(int)position.getY(); + sigIRC.config.setInteger("RABIRIBI_module_X", sigIRC.rabiribimodule_X); + sigIRC.config.setInteger("RABIRIBI_module_Y", sigIRC.rabiribimodule_Y); + } + + public void run() { + super.run(); + } + + public void draw(Graphics g) { + super.draw(g); + int i=32; + DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "Money: "+readIntFromMemory(MemoryOffset.MONEY)); + DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "H-Ups: "+readItemCountFromMemory(MemoryOffset.HEALTHUP_START,MemoryOffset.HEALTHUP_END)); + DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "A-Ups: "+readItemCountFromMemory(MemoryOffset.ATTACKUP_START,MemoryOffset.ATTACKUP_END)); + DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "M-Ups: "+readItemCountFromMemory(MemoryOffset.MANAUP_START,MemoryOffset.MANAUP_END)); + DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "R-Ups: "+readItemCountFromMemory(MemoryOffset.REGENUP_START,MemoryOffset.REGENUP_END)); + DrawUtils.drawOutlineText(g, sigIRC.panel.programFont, position.getX(), position.getY()+(i+=24), 3, Color.BLACK, Color.WHITE, "P-Ups: "+readItemCountFromMemory(MemoryOffset.PACKUP_START,MemoryOffset.PACKUP_END)); + } + + int readIntFromMemory(long offset) { + Memory mem = new Memory(4); + Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+offset), mem, 4, null); + return mem.getInt(0); + } + + int readIntFromMemory(MemoryOffset val) { + Memory mem = new Memory(4); + Kernel32.INSTANCE.ReadProcessMemory(rabiribiProcess, new Pointer(rabiRibiMemOffset+val.getOffset()), mem, 4, null); + return mem.getInt(0); + } + + int readItemCountFromMemory(MemoryOffset start_range, + MemoryOffset end_range) { + int count=0; + for (long i=start_range.getOffset();i<=end_range.getOffset();i++) { + if (readIntFromMemory(i)==1) { + count++; + } + } + return count; + } +} diff --git a/src/sig/modules/utils/Module.java b/src/sig/modules/utils/Module.java new file mode 100644 index 0000000..87c545d --- /dev/null +++ b/src/sig/modules/utils/Module.java @@ -0,0 +1,64 @@ +package sig.modules.utils; + +import sig.modules.utils.Psapi.LPMODULEINFO; +import com.sun.jna.platform.win32.WinDef.HMODULE; +import com.sun.jna.platform.win32.WinNT.HANDLE; + +public class Module { + private HANDLE hProcess; + private HMODULE hModule; + private HANDLE lpBaseOfDll = null; + private int SizeOfImage = 0; + private HANDLE EntryPoint = null; + + private PsapiTools psapi = PsapiTools.getInstance(); + + protected Module() { + } + + public Module(HANDLE hProcess, HMODULE hModule) { + this.hProcess = hProcess; + this.hModule = hModule; + } + + public HMODULE getPointer() { + return hModule; + } + + public String getFileName() { + return psapi.GetModuleFileNameExA(hProcess, hModule); + } + + public String getBaseName() { + return psapi.GetModuleBaseNameA(hProcess, hModule); + } + + private void GetModuleInformation() { + if (lpBaseOfDll == null) { + try { + LPMODULEINFO x = psapi.GetModuleInformation(hProcess, hModule); + lpBaseOfDll = x.lpBaseOfDll; + SizeOfImage = x.SizeOfImage; + EntryPoint = x.EntryPoint; + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public HANDLE getLpBaseOfDll() { + GetModuleInformation(); + return lpBaseOfDll; + } + + public int getSizeOfImage() { + GetModuleInformation(); + return SizeOfImage; + } + + public HANDLE getEntryPoint() { + GetModuleInformation(); + return EntryPoint; + } + +} diff --git a/src/sig/modules/utils/MyKernel32.java b/src/sig/modules/utils/MyKernel32.java new file mode 100644 index 0000000..5dcf32e --- /dev/null +++ b/src/sig/modules/utils/MyKernel32.java @@ -0,0 +1,81 @@ +package sig.modules.utils; + +import com.sun.jna.Memory; +import com.sun.jna.Native; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.ptr.IntByReference; + +public interface MyKernel32 extends Kernel32 { + final Kernel32 INSTANCE = (Kernel32) Native.loadLibrary ("kernel32", Kernel32.class); + +// BOOL WINAPI WriteProcessMemory( +// __in HANDLE hProcess, +// __in LPVOID lpBaseAddress, +// __in LPCVOID lpBuffer, +// __in SIZE_T nSize, +// __out SIZE_T *lpNumberOfBytesWritten +// ); + boolean WriteProcessMemory(HANDLE p, int address, HANDLE 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(HANDLE hProcess, int inBaseAddress, Memory outputBuffer, int nSize, IntByReference outNumberOfBytesRead); + + +// HANDLE WINAPI OpenProcess( +// __in DWORD dwDesiredAccess, +// __in BOOL bInheritHandle, +// __in DWORD dwProcessId +// ); + HANDLE OpenProcess(int desired, boolean inherit, int pid); + + +// BOOL WINAPI EnumProcessModules( +// _In_ HANDLE hProcess, +// _Out_ HMODULE *lphModule, +// _In_ DWORD cb, +// _Out_ LPDWORD lpcbNeeded +// ); + boolean EnumProcessModules(HANDLE hProcess, HMODULE lphModule, int cb, int lpcbNeeded); + + +// DWORD WINAPI GetModuleFileName( +// _In_opt_ HMODULE hModule, +// _Out_ LPTSTR lpFilename, +// _In_ DWORD nSize +// ); + + int GetModuleFileName(HMODULE hModule, String lpFilename, int size); + +// DWORD WINAPI GetModuleFileNameEx( +// _In_ HANDLE hProcess, +// _In_opt_ HMODULE hModule, +// _Out_ LPTSTR lpFilename, +// _In_ DWORD nSize +// ); + + +// BOOL WINAPI GetModuleHandleEx( +// _In_ DWORD dwFlags, +// _In_opt_ LPCTSTR lpModuleName, +// _Out_ HMODULE *phModule +// ); + + int GetModuleHandleExA(int permissions, String lpFilename, HMODULE module); + +// BOOL WINAPI EnumProcesses( +// _Out_ DWORD *pProcessIds, +// _In_ DWORD cb, +// _Out_ DWORD *pBytesReturned +// ); + + boolean EnumProcesses(int[] processIds, int cb, int bytesReturned); + + int GetLastError(); +} \ No newline at end of file diff --git a/src/sig/modules/utils/MyUser32.java b/src/sig/modules/utils/MyUser32.java new file mode 100644 index 0000000..68c3e68 --- /dev/null +++ b/src/sig/modules/utils/MyUser32.java @@ -0,0 +1,12 @@ +package sig.modules.utils; + +import com.sun.jna.Native; +import com.sun.jna.platform.win32.User32; + +public interface MyUser32 extends User32 { + final User32 INSTANCE = (User32) Native.loadLibrary ("user32", User32.class); + boolean ShowWindow(HWND hWnd, int nCmdShow); + boolean SetForegroundWindow(HWND hWnd); + HWND FindWindowA(String lpClassName, String lpWindowName); + +} diff --git a/src/sig/modules/utils/Psapi.java b/src/sig/modules/utils/Psapi.java new file mode 100644 index 0000000..712db65 --- /dev/null +++ b/src/sig/modules/utils/Psapi.java @@ -0,0 +1,57 @@ +package sig.modules.utils; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Native; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinDef.HMODULE; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.win32.StdCallLibrary; + +public interface Psapi extends StdCallLibrary{ + Psapi INSTANCE = (Psapi) Native.loadLibrary("Psapi", Psapi.class); + + /* + * http://msdn.microsoft.com/en-us/library/ms682629(VS.85).aspx + */ + boolean EnumProcesses(int[] pProcessIds, int cb, IntByReference pBytesReturned); + + + /* + * http://msdn.microsoft.com/en-us/library/ms682631(VS.85).aspx + */ + boolean EnumProcessModules(HANDLE hProcess, HMODULE[] lphModule, int cb, IntByReference lpcbNeededs); + + boolean EnumProcessModulesEx(HANDLE hProcess, HMODULE[] lphModule, int cb, IntByReference lpcbNeededs, int flags); + + + /* + * http://msdn.microsoft.com/en-us/library/ms683198(VS.85).aspx + */ + int GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, byte[] lpImageFileName, int nSize); + + int GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule, byte[] lpImageFileName, int nSize); + + + /* + * http://msdn.microsoft.com/en-us/library/ms684229(VS.85).aspx + */ + public static class LPMODULEINFO extends Structure { + public HANDLE lpBaseOfDll; + public int SizeOfImage; + public HANDLE EntryPoint; + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "lpBaseOfDll", "SizeOfImage", "EntryPoint"}); + } +} + + /* + * http://msdn.microsoft.com/en-us/library/ms683201(VS.85).aspx + */ + boolean GetModuleInformation(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, int cb); + + +} diff --git a/src/sig/modules/utils/PsapiTools.java b/src/sig/modules/utils/PsapiTools.java new file mode 100644 index 0000000..581a199 --- /dev/null +++ b/src/sig/modules/utils/PsapiTools.java @@ -0,0 +1,104 @@ +package sig.modules.utils; + +import java.util.LinkedList; +import java.util.List; + +import sig.modules.utils.Psapi.LPMODULEINFO; +import com.sun.jna.Native; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinDef.HMODULE; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.ptr.IntByReference; + +public class PsapiTools { + private static PsapiTools INSTANCE=null; + private static Psapi psapi = Psapi.INSTANCE; + private static Kernel32 k32 = MyKernel32.INSTANCE; + + private PsapiTools(){} + + public static PsapiTools getInstance(){ + if (INSTANCE==null) + INSTANCE=new PsapiTools(); + return INSTANCE; + } + + + public List enumProcesses() throws Exception{ + List list = new LinkedList(); + + int[] pProcessIds = new int[1024]; + IntByReference pBytesReturned = new IntByReference(); + boolean success = psapi.EnumProcesses(pProcessIds, pProcessIds.length*Integer.SIZE/8, pBytesReturned); + if (!success){ + int err=k32.GetLastError(); + throw new Exception("EnumProcesses failed. Error: "+err); + } + + int size = (pBytesReturned.getValue()/(Integer.SIZE/8)); + for (int i=0;i EnumProcessModules(HANDLE hProcess) throws Exception{ + List list = new LinkedList(); + + HMODULE[] lphModule = new HMODULE[1024]; + IntByReference lpcbNeededs= new IntByReference(); + boolean success = psapi.EnumProcessModules(hProcess, lphModule, lphModule.length, lpcbNeededs); + if (!success){ + int err=k32.GetLastError(); + if (err!=6) { + throw new Exception("EnumProcessModules failed. Error: "+err); + } + } + for (int i = 0; i < lpcbNeededs.getValue()/4; i++) { + list.add(new Module(hProcess, lphModule[i])); + } + + return list; + } + + public List EnumProcessModulesEx(HANDLE hProcess, int flags) throws Exception{ + List list = new LinkedList(); + + HMODULE[] lphModule = new HMODULE[1024]; + IntByReference lpcbNeededs= new IntByReference(); + boolean success = psapi.EnumProcessModulesEx(hProcess, lphModule, lphModule.length, lpcbNeededs, flags); + if (!success){ + int err=k32.GetLastError(); + throw new Exception("EnumProcessModules failed. Error: "+err); + } + for (int i = 0; i < lpcbNeededs.getValue()/4; i++) { + list.add(new Module(hProcess, lphModule[i])); + } + + return list; +} + + public String GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule){ + byte[] lpImageFileName= new byte[256]; + psapi.GetModuleFileNameExA(hProcess, hModule, lpImageFileName, 256); + return Native.toString(lpImageFileName); + } + + public String GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule){ + byte[] lpImageFileName= new byte[256]; + psapi.GetModuleBaseNameA(hProcess, hModule, lpImageFileName, 256); + return Native.toString(lpImageFileName); +} + + public LPMODULEINFO GetModuleInformation(HANDLE hProcess, HMODULE hModule) throws Exception{ + LPMODULEINFO lpmodinfo = new LPMODULEINFO(); + + boolean success = psapi.GetModuleInformation(hProcess, hModule, lpmodinfo, lpmodinfo.size()); + if (!success){ + int err=k32.GetLastError(); + throw new Exception("GetModuleInformation failed. Error: "+err); + } + return lpmodinfo; + } + +} diff --git a/src/sig/sigIRC.java b/src/sig/sigIRC.java index fcda6bd..1a5dbcd 100644 --- a/src/sig/sigIRC.java +++ b/src/sig/sigIRC.java @@ -12,15 +12,28 @@ import com.mb3364.twitch.api.handlers.ChannelResponseHandler; import com.mb3364.twitch.api.handlers.StreamResponseHandler; import com.mb3364.twitch.api.models.Channel; import com.mb3364.twitch.api.models.Stream; +import com.sun.jna.Memory; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Advapi32; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.platform.win32.WinNT.HANDLEByReference; import sig.modules.ChatLogModule; import sig.modules.ControllerModule; +import sig.modules.RabiRibiModule; import sig.modules.TouhouMotherModule; import sig.modules.TwitchModule; import sig.modules.ChatLog.ChatLogMessage; import sig.modules.ChatLog.ChatLogTwitchEmote; +import sig.modules.utils.MyKernel32; +import sig.modules.utils.PsapiTools; import sig.utils.FileUtils; import sig.utils.GithubUtils; +import sig.utils.MemoryUtils; import sig.utils.TextUtils; import java.awt.Color; @@ -116,6 +129,11 @@ public class sigIRC{ public static int chatlogmodule_height=312; public static int chatlogmodule_X=0; public static int chatlogmodule_Y=312; + public static int rabiribimodule_width=320; + public static int rabiribimodule_height=312; + public static int rabiribimodule_X=0; + public static int rabiribimodule_Y=312; + public static boolean rabiribimodule_enabled=true; public static int chatlogMessageHistory=50; public static boolean controllermodule_enabled=true; public static int controllermodule_width=320; @@ -186,6 +204,11 @@ public class sigIRC{ touhoumothermodule_Y = config.getInteger("TOUHOUMOTHER_module_Y",312); touhoumothermodule_width = config.getInteger("TOUHOUMOTHER_module_width",320); touhoumothermodule_height = config.getInteger("TOUHOUMOTHER_module_height",312); + rabiribimodule_X = config.getInteger("RABIRIBI_module_X",0); + rabiribimodule_Y = config.getInteger("RABIRIBI_module_Y",312); + rabiribimodule_width = config.getInteger("RABIRIBI_module_width",320); + rabiribimodule_height = config.getInteger("RABIRIBI_module_height",312); + rabiribimodule_enabled = config.getBoolean("Module_rabiribi_Enabled", false); chatlogmodule_X = config.getInteger("CHATLOG_module_X",0); chatlogmodule_Y = config.getInteger("CHATLOG_module_Y",312); chatlogmodule_width = config.getInteger("CHATLOG_module_width",320); @@ -332,6 +355,13 @@ public class sigIRC{ "Controller" )); } + + if (rabiribimodule_enabled) { + modules.add(new RabiRibiModule( + new Rectangle(rabiribimodule_X,rabiribimodule_Y,rabiribimodule_width,rabiribimodule_height), + "Rabi-Ribi" + )); + } } private static void InitializeCustomSounds() { diff --git a/src/sig/utils/MemoryUtils.java b/src/sig/utils/MemoryUtils.java new file mode 100644 index 0000000..7138235 --- /dev/null +++ b/src/sig/utils/MemoryUtils.java @@ -0,0 +1,37 @@ +package sig.utils; + +import com.sun.jna.Native; +import com.sun.jna.platform.win32.Advapi32; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinNT.HANDLEByReference; + +public class MemoryUtils { + /** + * Enables debug privileges for this process, required for OpenProcess() to + * get processes other than the current user + */ + public static void enableDebugPrivilege() { + HANDLEByReference hToken = new HANDLEByReference(); + boolean success = Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), + WinNT.TOKEN_QUERY | WinNT.TOKEN_ADJUST_PRIVILEGES, hToken); + if (!success) { + System.out.println("OpenProcessToken failed. Error: {}" + Native.getLastError()); + return; + } + WinNT.LUID luid = new WinNT.LUID(); + success = Advapi32.INSTANCE.LookupPrivilegeValue(null, WinNT.SE_DEBUG_NAME, luid); + if (!success) { + System.out.println("LookupprivilegeValue failed. Error: {}" + Native.getLastError()); + return; + } + WinNT.TOKEN_PRIVILEGES tkp = new WinNT.TOKEN_PRIVILEGES(1); + tkp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED)); + success = Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tkp, 0, null, null); + if (!success) { + System.out.println("AdjustTokenPrivileges failed. Error: {}" + Native.getLastError()); + } + Kernel32.INSTANCE.CloseHandle(hToken.getValue()); + } +}