Alterar Memoria , Como CheatEngine, Em java?

13 respostas
S

Povo, ola!!!

Bom, eu estou precisando fazer um programa em java que altera um valor da memoria de um processo.
Por enquanto só queria fazer algo bem simples pra entender como que funciona, mas parece que tem pouca informação sobre isso.
Fui Procurando e consegui juntar umas classes.Porém acho que elas nao funcionam, talvez porque foram feitas para win32!?

Bom, eu tive que usar JNA 3.4.0 + as classes desse tópico :

http://www.gamedeception.net/threads/20318-Java-Memory-Hack-using-JNA-for-the-Win-API
http://pastebin.com/Vq8wfy39

Vou tentar fuçar mais um pouco no código antes de realmente postar minha dúvida, mas queria saber o que acham sobre isso…
E nao, nao tem como eu aprender C++ agora porque estou me aprofundando em java :smiley:

13 Respostas

V

Tá querendo escrever um bot para jogar por voce?

Para usar DMA, acho que o melhor seria usar C/C++ mesmo. Java roda em uma maquina virtual e é mais restrito quanto a segurança.

Boa sorte.

S

vitu:
Tá querendo escrever um bot para jogar por voce?

Para usar DMA, acho que o melhor seria usar C/C++ mesmo. Java roda em uma maquina virtual e é mais restrito quanto a segurança.

Boa sorte.

Na verdade nao.
Estou precisando de um programa que altera o valor da memoria de um certo endereço de um jogo singleplayer para ele parar de dar bug…
Eu poderia fazer um script cheat engine, mas acho que fazer em java seria mais interessante …

Vou postar os códigos que estou usando… Nao ta dando muito certo

V

O jogo é em java? Pode tentar usar um decompilador.
Também pode usar um disassembler ou editor hexadecimal.

Voce deve encontrar poucas informações sobre isso na internet, pois as mesmas tecnicas podem ser utilizadas para escrever spywares, keyloggers ou outro tipo de software malicioso.

S
vitu:
O jogo é em java? Pode tentar usar um decompilador. Também pode usar um disassembler ou editor hexadecimal.

Voce deve encontrar poucas informações sobre isso na internet, pois as mesmas tecnicas podem ser utilizadas para escrever spywares, keyloggers ou outro tipo de software malicioso.

Na verdade o jogo é um emulador ( PCSX2 ),

Aqui estão os códigos que estou usando, meu objetivo é alterar algum valor da memoria qualquer do campo minado... Nao importa se travar ele ou se der crash :

Usando a JNA 4.0 e JNA Master_algumaCoisa

[url]http://pastebin.com/Vq8wfy39[/url]

Só que nao ta dando muito certo.... O que acha?

package MainStart;

import com.br.HM.User32;
import com.br.kernel.Kernel32;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;


public class Cheater {

    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);

    public static void main(String[] args) {
        int pid = getProcessId("MineSweeper"); // get our process ID
        Pointer readprocess = openProcess(0x0010, pid); // open the process ID with read priviledges.

        int size = 4; // we want to read 4 bytes
        Memory read = readMemory(readprocess, 0x40096E,4); // read 4 bytes of memory starting at the address 0x00AB0C62.

        System.out.println(read.getInt(0)); // print out the value!

    }

    public static int writeMemory(Pointer process, int address, short[] data) {
        IntByReference written = new IntByReference(0);

        Memory toWrite = new Memory(data.length);

        for (long i = 0; i < data.length; i++) {
            toWrite.setShort(0, data[new Integer(Long.toString(i))]);
        }

        boolean b = kernel32.WriteProcessMemory(process, address, toWrite, data.length, written);
        return written.getValue();
    }

    public static Pointer openProcess(int permissions, int pid) {
        Pointer process = kernel32.OpenProcess(permissions, true, pid);
        return process;
    }

    public static int getProcessId(String window) {
        IntByReference pid = new IntByReference(0);
        user32.GetWindowThreadProcessId(user32.FindWindowA(null, window), pid);

        return pid.getValue();
    }

    public static Memory readMemory(Pointer process, int address, int bytesToRead) {
        IntByReference read = new IntByReference(0);
        Memory output = new Memory(bytesToRead);

        kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
        return output;
    }
}
package com.br.HM;

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.StdCallLibrary.StdCallCallback;
import com.sun.jna.win32.W32APIOptions;

/**
 * Provides access to the w32 user32 library. Incomplete implementation to
 * support demos.
 *
 * @author Todd Fast, [email removido]
 * @author [email removido]
 */
public interface User32 extends W32APIOptions {

    User32 INSTANCE = (User32) Native.loadLibrary("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);
}
package com.br.kernel;

import com.sun.jna.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.ptr.IntByReference;
 
// by deject3d
 
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, int 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, int 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();
}
V

Esta rodando em Windows correto?
Até onde rodou?
O PID não devia ser um valor númerico? Voce pode pegar esse valor pelo comando tasklist do DOS.
Esses endereços de memoria fixos estão corretos?

S
vitu:
Esta rodando em Windows correto? Até onde rodou? O PID não devia ser um valor númerico? Voce pode pegar esse valor pelo comando tasklist do DOS. Esses endereços de memoria fixos estão corretos?

VITU!!!!
Quando coloquei o pid manualmente, deu certo! Bateu Exatamente como no Cheat Engine.

Mas ele nao acha o pid automaticamente.... Deve ter algo errado no método, o que será que é? Meu windows é 64 bit!
public static void main(String[] args) {
        int pid = getProcessId("MineSweeper.exe"); // get our process ID
        System.out.println("Pid = " + getProcessId("MineSweeper.exe")); // Sempre da 0
        //pid = 4772;
        Pointer readprocess = openProcess(0x0010,pid); // open the process ID with read priviledges.
       
        int size = 4; // we want to read 4 bytes
        Memory read = readMemory(readprocess,0x00401743,size); // read 4 bytes of memory starting at the address 0x00AB0C62.
 
        System.out.println(read.getInt(0)); // print out the value!

    }
V

Esse método espera o título da janela como parâmetro.

S
vitu:
Esse método espera o título da janela como parâmetro.

Ah, é verdade!!
Agora deu certo...

Sem querer abusar.. rsrs, mas só preciso de mais uma ajudinha :D

Mas nao consigo dar um write no mesmo endereço.
Ele nao da erro, mas retorna o mesmo valor.

public static void main(String[] args) {
        //Read Memory
        int pid = getProcessId("Campo Minado"); // get our process ID
        System.out.println("Pid = " + pid);

        
        Pointer readprocess = openProcess(readRight, pid); // open the process ID with read priviledges.
        Pointer writeprocess = openProcess(writeRight, pid);

        int size = 4; // we want to read 4 bytes
        int address = 0x00401743;

        //Read Memory
        Memory read = readMemory(readprocess, address, size); // read 4 bytes of memory starting at the address 0x00AB0C62.
        System.out.println(read.getInt(0)); // print out the value!
        
        
        //Write Memory
        writeMemory(writeprocess, address, new short[123]);
        Memory readM = readMemory(readprocess, address, size); 
        System.out.println(readM.getInt(0)); 
        

    }

To usando isso aqui como referencia pra abrir o processo :
http://msdn.microsoft.com/en-us/library/ms684880(v=VS.85).aspx

V

Parece estar abrindo o processo somente como leitura.
Tentou trocar o 0x0010 por 0x0020?

S
vitu:
Parece estar abrindo o processo somente como leitura. Tentou trocar o 0x0010 por 0x0020?

//Write Memory
writeMemory(writeprocess, address, new short[123]);
Memory readM = readMemory(readprocess, address, size);
System.out.println(readM.getInt(0));

Mas e isso aqui ?

public class Cheater {

    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
    static int readRight = 0x0010;
    static int writeRight = 0x0020;
    //static int PROCESS_VM_OPERATION = 0x0008;

    public static void main(String[] args) {
        //Read Memory
        int pid = getProcessId("Campo Minado"); // get our process ID
        System.out.println("Pid = " + pid);

        Pointer readprocess = openProcess(readRight, pid); // open the process ID with read priviledges.
        Pointer writeprocess = openProcess(writeRight, pid);

        int size = 4; // we want to read 4 bytes
        int address = 0x00401743;

        //Read Memory
        Memory read = readMemory(readprocess, address, size); // read 4 bytes of memory starting at the address 0x00AB0C62.
        System.out.println(read.getInt(0)); // print out the value!       

        //Write Memory
        writeMemory(writeprocess, address, new short[123]);
        Memory readM = readMemory(readprocess, address, size);
        System.out.println(readM.getInt(0));
    }
V

Tenta depurar o retorno do WriteProcessMemory.

Ele pode estar sobrescreendo esse valor com o antigo logo em seguida.

O CheatEngine parece manter uma thread que sempre reescreve o valor.

S
vitu:
Tenta depurar o retorno do WriteProcessMemory.

Ele pode estar sobrescreendo esse valor com o antigo logo em seguida.

O CheatEngine parece manter uma thread que sempre reescreve o valor.

Esse boolean aqui retorna false...

Mas eu acho que nem sempre rpecisa de uma thread pra ficar reescrevendo. Porque no simcity 4 , por exemplo eu usei pra ficar com 999 999 999 de dinheiro , depois eu fechei e ainda ficou.
public static int writeMemory(Pointer process, int address, short[] data) {
        IntByReference written = new IntByReference(0);

        Memory toWrite = new Memory(data.length);

        for (long i = 0; i < data.length; i++) {
            toWrite.setShort(0, data[new Integer(Long.toString(i))]);
        }

        boolean b = kernel32.WriteProcessMemory(process, address, toWrite, data.length, written);
        System.out.println("kernel32.WriteProcessMemory : " + b); // Retorna false
        return written.getValue();
    }
S

Ainda nao consegui descobrir... Mas ta ai o que aparece...O que sera que devo fazer?

run: Pid = 508 191852368 kernel32.WriteProcessMemory : false WriteMemory :0 191852368 CONSTRUÍDO COM SUCESSO (tempo total: 0 segundos)
public class Cheater {

    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
    static int readRight = 0x0010;
    static int writeRight = 0x0020;
    //static int PROCESS_VM_OPERATION = 0x0008;

    public static void main(String[] args) {
        //Read Memory
        int pid = getProcessId("Campo Minado"); // get our process ID
        System.out.println("Pid = " + pid);

        Pointer readprocess = openProcess(readRight, pid); // open the process ID with read priviledges.
        Pointer writeprocess = openProcess(writeRight, pid);

        int size = 4; // we want to read 4 bytes
        int address = 0x00401743;

        //Read Memory
        Memory read = readMemory(readprocess, address, size); // read 4 bytes of memory starting at the address 0x00AB0C62.
        System.out.println(read.getInt(0)); // print out the value!       
        //Write Memory
        int writeMemory = writeMemory(writeprocess, address, new short[123]);
        System.out.println("WriteMemory :" + writeMemory);
        Memory readM = readMemory(readprocess, address, size);
        System.out.println(readM.getInt(0));
    }
Criado 14 de julho de 2013
Ultima resposta 15 de jul. de 2013
Respostas 13
Participantes 2