Thread: ReadProcessMemory?

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    55

    ReadProcessMemory?

    Hey all, I'm new to the forum here. Nice to see all the wonderful people helping others with programming! Anyways..

    About:

    I am writing a program for a game, Halo Trial, which I play quite frequently. I host servers everyday for my 'clan' to play on. However, we get lots of 'noobs' who ruin the server by betraying other members and such. We hate these kinds of people. Recently, I got into editing hex values inside the game. I found values of players that I could change so they would freeze and couldn't move. I did this to these 'noob' players who annoyed me. This was just a temporary fix. Every time I would have to freeze a player, I would have to go inside of memory, search for that player, and edit his values...by that time, he was causing mass chaos.

    My Program:

    I can make simple programs to 'Poke' an address to freeze the player. But, I have to figure out which player I have to freeze, by going in memory and figuring out which player goes with which offset. This is a hassle. My new program, which I am working on, needs to read the player names into a listbox, so I can choose which player to edit. This will save time and hassle for kicking a player off my server.

    The problem:

    I can't get the strings of player names to read into my listbox. Here is the code and I will explain more at bottom:

    Code:
    #include <windows.h>
    #include "resource.h"
    
    #pragma comment(linker,"/FILEALIGN:512 /MERGE:.rdata=.text /MERGE:.data=.text /SECTION:.text,EWR /IGNORE:4078")
    
    char *gameWindow = "Halo"; // Edit the game caption here
    DWORD pid; HWND hwndWindow; DWORD bytes; HANDLE hand = NULL;
    /** Start of Declarations here **/
    
    DWORD Player1 = 0x4BD7AFD0, NextPlayer = 0x4BD7B1D0; // Player 1's name address at first byte then player2's name at first byte
    BYTE HoldName[22]; // Max player name legth is 22 bytes
    // Get it by subing Player 1's name address from player 2's.
    int OffsetBetweenPlayerNames = 0x200; // 200 bytes between players or should it be C8h?
    char Out[26];
    int MaxNumberOfPlayers = 16;
    int i = 0;
    
    void CreatePlayerList(HWND hwnd) // notice the new param 
    {
       // Clear the list.
        SendDlgItemMessage(hwnd, IDC_PLAYERLIST,  LB_RESETCONTENT, 0, 0);
        for(i = 0; i < MaxNumberOfPlayers; i++)
        {
             ReadProcessMemory(hand, (VOID*)NextPlayer, HoldName, 22, NULL);
             wsprintf(Out, "%s", HoldName); // Ex text: 1. Silentkarma
             // Set Listbox Text with name and offset
             SendDlgItemMessage(hwnd, IDC_PLAYERLIST, LB_ADDSTRING, (WPARAM) i, (LPARAM) (LPCTSTR) Out);
             NextPlayer = Player1 + (i * OffsetBetweenPlayerNames);
        }
    }
    
    // Below is the about text that is shown when "About" button is clicked
    char *about   =
    "HTMP Trainer v2\n\n"
    "Limbo :: Nor Heaven, Nor Hell.\n"
    "You live eternally in nowhere.\n\n"
    "SilentK/Scoopa";
    
    /** End of Declarations here **/
    
    void aboutButton(HWND hwnd)
    {
    	MessageBox(hwnd,about,"About",MB_ICONINFORMATION);
    }
    
    void Initialize(HWND hwnd,WPARAM wParam, LPARAM lParam) {
    	hwndWindow = FindWindow(NULL,gameWindow);
    
    	if(hwndWindow) {
    		GetWindowThreadProcessId(hwndWindow, &pid);
    		hand = OpenProcess(PROCESS_ALL_ACCESS,0,pid);
    		SetTimer(hwnd, 1, 100, NULL);	//Timer speed is 100ms, you can change it here
    	} else {
    		MessageBox(NULL, "Cannot find Halo Trial! It MUST be open for this trainer to work!", "Error", MB_OK + MB_ICONWARNING);
    	}
    }
    
    void timerCall(HWND hwnd) // Added Param for function
    {
    	/** All your Pokes should go in here **/
        if(GetAsyncKeyState(VK_F6))
             CreatePlayerList(hwnd);
    	/** End **/
    }
    
    BOOL CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    
    
        switch (message)
    	{
    		case WM_INITDIALOG:
    			Initialize(hwnd,wParam,lParam);
    			return TRUE;
    
    		case WM_COMMAND:
    			switch (LOWORD(wParam))
    			{
    				case IDC_ABOUT:
    					aboutButton(hwnd);
    					return TRUE;
    
    				case IDC_EXIT:
    					EndDialog (hwnd, 0);
    					return TRUE;
    			}
    		return TRUE;
    
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			return TRUE;
    
    		case WM_CLOSE:
    			PostQuitMessage(0);
    			return TRUE;
    		case WM_TIMER:
    			timerCall(hwnd); /* Changed to match new func */
    			return TRUE;
        }
        return FALSE;
    }
    
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
    {
    	DialogBox(hInstance,MAKEINTRESOURCE(IDD_MAINDLG), NULL,DialogProc);
    	return 0;
    }
    Why is it not reading strings into my listbox? Anyone know?
    [Using VC++ - IDC_PLAYERLIST is the listbox ID]
    Last edited by silentkarma; 09-09-2006 at 11:05 PM.

  2. #2
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    check and make sure that Out is a valid string. debug through it, do a Run to Cursor on the wsprintf() line then hit f10 - check and see what Out is.
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    I don't think you're going to get many answers here. Screwing with process memory is highly malicious and while you intentions seem to be legitimate... most people who can help you might not be willing to distribute that information. As you can expect, this forum has it's fair share of visitors and some of them have bad intentions when it comes to programming. Explaining how to edit memory of another process can be very bad in the wrong hands.

    I can't be certain that you won't get an answer, I'm just telling you not to get your hopes up.
    Sent from my iPadŽ

  4. #4
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    Quote Originally Posted by SlyMaelstrom
    I don't think you're going to get many answers here. Screwing with process memory is highly malicious and while you intentions seem to be legitimate... most people who can help you might not be willing to distribute that information. As you can expect, this forum has it's fair share of visitors and some of them have bad intentions when it comes to programming. Explaining how to edit memory of another process can be very bad in the wrong hands.

    I can't be certain that you won't get an answer, I'm just telling you not to get your hopes up.

    Agreed, however, from the way I read his post, it sounded more like a general windows listbox question, not a process memory question.
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    55
    Well, I'm not discussing how to edit hex values at all...

    I want to read the memory into a listbox. Is that so much to ask? What's the harm in that? It's not malacious in my way of doing things. I just want to host my game server with ease. My intent is not malacious. I don't think reading memory on MY OWN computer is bad to me.

    So. Can someone help me?

    Edit: My code has nothing in it that gives away how to edit memory. I took them out before I posted. My question is just a general listbox question like neandrake stated.
    Last edited by silentkarma; 09-10-2006 at 12:00 AM.

  6. #6
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Code:
             SendDlgItemMessage(hwnd, IDC_PLAYERLIST, LB_ADDSTRING, (WPARAM) i, (LPARAM) (LPCTSTR) Out);
    About that WPARAM of LB_ADDSTRING: not used; must be zero.
    Code:
    int OffsetBetweenPlayerNames = 0x200; // 200 bytes between players or should it be C8h?
    0x200 is hex represention of 512, if you mean 200 bytes as a decimal, just cut off the "0x".

    Instead of:
    Code:
             ReadProcessMemory(hand, (VOID*)Player1, HoldName, 22, NULL);
             wsprintf(Out, "%s", HoldName); // Ex text: 1. Silentkarma
             // Set Listbox Text with name and offset
             SendDlgItemMessage(hwnd, IDC_PLAYERLIST, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) Out);
    cant you just use:
    Code:
             ReadProcessMemory(hand, (VOID*)Player1, HoldName, 22, NULL);
             SendDlgItemMessage(hwnd, IDC_PLAYERLIST, LB_ADDSTRING, 0, (LPARAM)HoldName);
    Now, a little changed version:
    Code:
    void CreatePlayerList(HWND hwnd){
        SendDlgItemMessage(hwnd, IDC_PLAYERLIST,  LB_RESETCONTENT, 0, 0);
        for(i = 0; i < MaxNumberOfPlayers; i++){
             ReadProcessMemory(hand, (VOID*)Player1, HoldName, 22, NULL);
             SendDlgItemMessage(hwnd, IDC_PLAYERLIST, LB_ADDSTRING, 0, (LPARAM)HoldName);
             Player1+=OffsetBetweenPlayerNames;
        }
    }
    I didn't have the time to test these things, so there might be some typos.

    Now you can delete some unnecessary variables, like NextPlayer and Out.
    Last edited by maxorator; 09-10-2006 at 02:13 AM.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    55
    I still cannot get this to work. I know the program reads the handle because it doesn't pop up an error when I run it. I just can't get anything to show up in the listbox...at all. It's like it's not even reading the memory. Maybe it's a refresh problem? Not sure. Could you write me a simple code that works as far as reading memory into a listbox. Nothing to fancy. I just want something that works that I can learn from, then build from that to what I am doing. Thanks for your cooperation and help!

  8. #8
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    I'll try to do something tomorrow.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    55
    Thanks alot man! I appreciate your help!

  10. #10
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I know the program reads the handle because it doesn't pop up an error when I run it.
    This ain't necessarily true. You should verify that all handles are valid and check the return code from OpenProcess and ReadProcessMemory. Please note the "remote" app will display the hex address of the data in the window. This is the address to be used in your "utility".

    Your utility to access the remote app:
    Code:
    // util.rc
    #include <windows.h>
    #define IDD_LISTBOX 100
    #define IDC_PLAYERLIST 101
    
    IDD_LISTBOX DIALOGEX 0, 0, 497, 171
    STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
        WS_SYSMENU
    CAPTION "Just a test list box"
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
        DEFPUSHBUTTON   "OK",IDOK,137,138,50,14
        PUSHBUTTON      "Cancel",IDCANCEL,220,140,50,14
        LISTBOX         IDC_PLAYERLIST,79,22,279,91,LBS_SORT | LBS_NOINTEGRALHEIGHT | 
                        WS_VSCROLL | WS_TABSTOP
    END

    Code:
    // util.cpp
    #include <windows.h>    
    #include <commctrl.h>
    #include <stdio.h>
    #include <string.h>
    
    #define IDD_LISTBOX 100
    #define IDC_PLAYERLIST 101
    
    BOOL CALLBACK DoListboxProcess(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HWND hwnd;           
        DWORD pid;
        HANDLE process;
        int x;
        // Hex address from "remote" app
        DWORD iAddress = 0x408088;
        DWORD dummy = 0;
        char value[33], outvalue[22];
    
        switch (message) {
            case WM_INITDIALOG:
                hwnd=FindWindow(NULL, "The Hello Program");
                SendDlgItemMessage(hDlg, IDC_PLAYERLIST,  LB_RESETCONTENT, 0, 0);
                GetWindowThreadProcessId(hwnd, &pid);
                process = OpenProcess(PROCESS_VM_READ
                    |PROCESS_VM_WRITE|     
                    PROCESS_VM_OPERATION    
                    |PROCESS_QUERY_INFORMATION, 
                    FALSE, pid);
                for(x = 0; x < 3;x++)
                {
                    ReadProcessMemory(process    // handle to the process
                        ,(void*) iAddress,     // address to start reading
                        (void*) &value,        // address of buffer to place read data
                        sizeof(value)          // number of bytes to read
                        ,&dummy);              // number of bytes read
                    strncpy(outvalue, value,22);
                    outvalue[21] = '\0';
    				 SendDlgItemMessage(hDlg, IDC_PLAYERLIST, LB_ADDSTRING, 0, (LPARAM)outvalue);
                        iAddress += sizeof value;
                }       
                return (TRUE);
            case WM_COMMAND:
    
                if (LOWORD(wParam) == IDOK ||LOWORD(wParam)== IDCANCEL  ) {
                    EndDialog(hDlg, TRUE);
                    return (TRUE);
                }
                break;
        }
        return FALSE;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance,
           HINSTANCE hPrevInstance,
           LPSTR lpszArgs,
           int nWinMode)
    {
        InitCommonControls();
        DialogBox(hInstance ,MAKEINTRESOURCE(IDD_LISTBOX) , 0, DoListboxProcess);
        return 0;
    }
    The "remote" app:
    Code:
    // remote.cpp
    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         static TCHAR szAppName[] = TEXT ("HelloWin") ;
         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;
    
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = 0 ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;
    
         if (!RegisterClass (&wndclass))
         {
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                          szAppName, MB_ICONERROR) ;
              return 0 ;
         }
         
         hwnd = CreateWindow (szAppName,                  // window class name
                              TEXT ("The Hello Program"), // window caption
                              WS_OVERLAPPEDWINDOW,        // window style
                              CW_USEDEFAULT,              // initial x position
                              CW_USEDEFAULT,              // initial y position
                              CW_USEDEFAULT,              // initial x size
                              CW_USEDEFAULT,              // initial y size
                              NULL,                       // parent window handle
                              NULL,                       // window menu handle
                              hInstance,                  // program instance handle
                              NULL) ;                     // creation parameters
         
         ShowWindow (hwnd, iCmdShow) ;
         UpdateWindow (hwnd) ;
         
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
         return msg.wParam ;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	// This is the array we are reading remotely
    	 static char array[3][33]= {"Ted                   GoodPlayer","Bobby                 BadPlayer " , "Joey                  OKPlayer  "}; 
         HDC         hdc ;
         PAINTSTRUCT ps ;
         RECT        rect ;
    	 char szMessage[128] = {0};
         
         switch (message)
         {
         case WM_CREATE:
                  return 0 ;
         case WM_PAINT:
              hdc = BeginPaint (hwnd, &ps) ;
              GetClientRect (hwnd, &rect) ;
    		  sprintf(szMessage,"Address of array is HEX %02x", array);
              DrawText (hdc, TEXT (szMessage), -1, &rect,
                        DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
              EndPaint (hwnd, &ps) ;
              return 0 ;
         case WM_DESTROY:
              PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    Last edited by BobS0327; 09-11-2006 at 08:50 AM.

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    55
    I'm not sure how to set that up into VC++. I'm still in the learning process, but I can understand what your code does. Could you point me a little more thanks

  12. #12
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I'm not sure how to set that up into VC++.
    Let's keep things simple and do it from the command line...

    Please note that I have edited the code samples and added names to each section such as util.rc, util.cpp and remote.cpp.

    First compile the remote app as follows:

    CL.EXE remote.cpp user32.lib gdi32.lib

    Execute the remote.exe and get the hex address displayed in the window. Put this hex address in the appropriate location in the util.cpp source code

    Now compile the resource file as follows:

    RC.EXE util.rc
    which produces a util.res if compiled succesfully.

    Next compile the util as follows:

    CL.EXE util.cpp util.res user32.lib comctl32.lib

    Execute the util.exe

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    55
    Had no trouble at with the CL.EXE. Now when I tried to complile the util.rc, it gave me this error:

    --------------------Configuration: CL - Win32 Debug--------------------
    Compiling resources...
    C:\Documents and Settings\Stephen Ratliff\CL\util.rc (10): error RC2135 : file not found: DoListboxProcess

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    55
    Found the problem. Compiled the wrong code lol. let me try this now.
    Last edited by silentkarma; 09-11-2006 at 11:46 AM.

  15. #15
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    C:\Documents and Settings\Stephen Ratliff\CL\util.rc (10): error RC2135 : file not found: DoListboxProcess
    You're compiling the util.cpp code as rc code. Thus, generating the above error. In other words, your file with the rc extension contains the main driver function code etc.

    Please create the util.rc file from the first code tag segment with the commented name of util.rc at the top of the segment. Then compile this as RC.EXE util.rc.

    The code from the second code tag segment should be put in a file named util.cpp

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with ReadProcessMemory function
    By MattZimmerer in forum C Programming
    Replies: 16
    Last Post: 10-30-2008, 09:21 PM
  2. ReadProcessMemory Error
    By Scarvenger in forum Windows Programming
    Replies: 10
    Last Post: 05-28-2008, 04:47 PM
  3. ReadProcessMemory() help
    By Anddos in forum C++ Programming
    Replies: 7
    Last Post: 08-08-2006, 10:55 AM
  4. ReadProcessMemory();
    By kennny2004 in forum C++ Programming
    Replies: 12
    Last Post: 07-10-2006, 10:09 PM
  5. ReadProcessMemory()
    By Josh Kasten in forum Windows Programming
    Replies: 2
    Last Post: 06-19-2003, 12:45 AM