Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[C++] Help reading string from memory process
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Sun Feb 26, 2012 4:01 pm    Post subject: [C++] Help reading string from memory process Reply with quote

Hello everybody, I must say I am a bit new programming on c++. I usually develop my applications in vb6 or c#.
Now I'm in the middle of a trouble trying to make a Win32 COM DLL in C++ to find in a process memory a certain string, for example "CheatEn". (7 len)

To do this, and also test & debug it with my vb6 application, i programmed this function:

Code:
int _stdcall ReadString(char *window, int Point, int Len)
{
   char* value;

        HWND hWnd = FindWindow(NULL, window);
   DWORD proc_id;
   GetWindowThreadProcessId(hWnd, &proc_id);

   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, proc_id);
   
   ReadProcessMemory(hProcess, (LPVOID)Point, &value, 7, 0);
   
   //if (value == 'CheatEn')
        //{
        //       return 10;
        //}


   //CloseHandle(hProcess); Is actually necessary this?
   return 0;
}


For example, i would like to read the string in a certain address i would especify like 0x00F15130. In that address there's a string: "CheatEn" (7 len). I would like to compare it and verify if actually it is "CheatEn" or is another string like "asdagjkf" or whatever.
I tried many things but the part of the IF sentence still not working.
When i debug my dll and "add watches" y can see that &value has a value of 0xADDRESSHERE and then "CheatEn" the string i'm looking for.

Than you so much for reading my post.
I hope you can understand me without problems because my english is not the best.

Shalvaid
Back to top
View user's profile Send private message
SpaceUrkel
How do I cheat?
Reputation: 0

Joined: 25 Feb 2012
Posts: 8

PostPosted: Sun Feb 26, 2012 9:38 pm    Post subject: Reply with quote

In c++ you can only compare two variables of the same >type< in an if statement.
This makes sure that both variables have the same size. For example numbers: a LONG is 4 bytes long (int) for example.

strings don't have that, they are not even a type in c++. The only means
to tell the length of a string is by attaching a NULL at the end.

0x01 'H'
0x02 'e'
0x03 'l'
0x04 'l'
0x05 'o'
0x06 '\0' (zero)

You could either write your own routine that compares the strings CHAR by CHAR (or preferably DWORD by
DWORD) or use one of the many functions that the C runtime and windows provide (strings.h gives you strcmp for
example). i.e.: if( strcmp( string, string ) == NULL )
[/code]

_________________
et illus fugit
Back to top
View user's profile Send private message
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Sun Feb 26, 2012 10:13 pm    Post subject: Reply with quote

SpaceUrkel wrote:
In c++ you can only compare two variables of the same >type< in an if statement.
This makes sure that both variables have the same size. For example numbers: a LONG is 4 bytes long (int) for example.

strings don't have that, they are not even a type in c++. The only means
to tell the length of a string is by attaching a NULL at the end.

0x01 'H'
0x02 'e'
0x03 'l'
0x04 'l'
0x05 'o'
0x06 '\0' (zero)

You could either write your own routine that compares the strings CHAR by CHAR (or preferably DWORD by
DWORD) or use one of the many functions that the C runtime and windows provide (strings.h gives you strcmp for
example). i.e.: if( strcmp( string, string ) == NULL )
[/code]



Thank you so much for your help. Using strcmp I receive an error: Unhandled exception in MyDll.exe (MYDLL.DLL): 0x0000005: Access Violation, and then crash (running directly from my MyDLL.exe application. And debugging it through vc++ 6.0 y receive the same error but asking me to "Enter the path of STRCMP.ASM.

I've received this error in the past, trying to do something like this, but I dont know how to fix it.

Thanks a lot.


My VB 6.0 Code:

Code:
Private Declare Function ReadString Lib "MyDLL.dll" (ByVal Window As String, ByVal Pointer As Long, ByVal xLen As Long) As Long

Private Sub Command1_Click()
MsgBox ReadString("WindowToRead", CLng("&H" & "00F15130"), 7)
End Sub


żDo you think it would be better to create my own function to compare the strings? Is the only solution i think i can get.
Back to top
View user's profile Send private message
SpaceUrkel
How do I cheat?
Reputation: 0

Joined: 25 Feb 2012
Posts: 8

PostPosted: Sun Feb 26, 2012 10:59 pm    Post subject: Reply with quote

Well, the access violation can happen when you try reading from protected
areas. You can't just read out the process from address 0x00000000
to 0xFFFFFFFF.

Ofcourse, writing a routine that compares strings is quite easy. But there
are some tricks to it to make it faster. For example, rather than comparing
byte by byte, as I said earlier, its faster to compare dwords or (if you
run on a 64bit system) qwords.

Code:


//return zero when both strings are equal, otherwise return address of the first difference
unsigned char*
compare( char* _cpsource, char* _cpdestination, unsigned long _ullength )
{
unsigned long dw_count = _ullength/sizeof(unsigned long); //we devide by 4. lets say our _ullength is 15 so: 3
unsigned short byte_count = _ullenght%sizeof(unsigned long);//now we need the ammount of the remaining bytes: also 3

//so in theory we can compare 3 DWORDs (4byte) and 3 CHARs (1byte), assuming you want to compare 15 bytes with each other

while( dw_count ) //reading in DWORDs
{
   if(*_cpsource != *_cpdestination) //the star is the operator to access the memory that our variables point to
      break;
   (char*)_cpsource+=sizeof(unsigned long); //here we are here we know that the if statement was false and that
   (char*)_cpdestination+=sizeof(unsigned long); //the two DWORDs were identical, so we advance to the next set
   dw_cout--;                       //of DWORDs by increasing the address that our pointer carries by the size of one DWORD.
}

while( byte_count ) //reading in CHARs (1 byte)//once we are here we can assume that we either ran out of DWORDs to
{                           //compare or that there was a difference found and now we need to find the exact location of it.
  if(*(char*)_cpsource != *(char*)_cpdestination)) //we cast our pointer into the CHAR type so our compiler knows we
    goto NOT_EQUAL                                            //only compare 1 byte values now.
  (char*)_cpsource+=sizeof(char);
  (char*)_cpdestination+=sizeof(char);
  byte_count--;
}

return 0; //if we reach this point every single DWORD and BYTE are
              //identical.

NOT_EQUAL:
return _cpsource;
}


Hope this helps you get into the language some more. C++ is really worth getting into. Smile

_________________
et illus fugit
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8585
Location: 127.0.0.1

PostPosted: Mon Feb 27, 2012 2:04 am    Post subject: Reply with quote

You are getting problems because you don't initialize your pointer.

char* value;

This isn't a valid data type to write into yet because it isn't initialized and since it is a pointer, it points to nothing. If you know the size is always going to be 7, use a char array instead.

If not, use new/malloc and allocate space and initialize value before you use it. (Be sure to free the memory when you are done too.)

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Mon Feb 27, 2012 11:55 am    Post subject: Reply with quote

Thanks all of you, As Wiccaan and most of you said, i didn't initialize my pointer, so now I' ve done and this is my code working:

Code:

char* _stdcall ReadString(char *window, int Point, int Len)
{
   //char *value = (char*)malloc(Len+1) = {0};
   char value[8] = {0};

    HWND hWnd = FindWindow(NULL, window);
   DWORD proc_id;
   GetWindowThreadProcessId(hWnd, &proc_id);

   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, proc_id);
   
   BOOL bReturn = ReadProcessMemory(hProcess, (LPVOID)Point, &value, 7, 0);
   if ( bReturn == 0 )
   {
      DWORD lastError = GetLastError();
     // error
   }
   else
   {
      // success
      return value;
   }
}


Thank you SpaceUrkel for the idea of making a new routine and your code. But I decided to use strcmp to compare both values because it was the way i had tried 3 days ago, but it was not working because de readprocessmemory was wrong... Now it is reading the correct value, and I'm trying to make a routine to find a text value from visual basic. This is what i've done:


Code:
int _stdcall SearchString(char *window, char *Text)
{
   long int x;
   
    for(x = 0; x < 80000000; x++) // This is a fucking disaster
   {
          if (strcmp(ReadString(window, x, sizeof(Text)), Text) == 0)
          {
                return x;                     
          }
   }

   return 0;

}


That routine, i will call through vb6, with the window name and the text to search. I don't know why but it still not working properly. And I know there's a way to get the base address of a process to start searching since it like 0x40000000 but it changes on Windows 7 or Windows Vista, so i guess mi app will crash and not work properly.

I've tried this [C++] Get base Address (sorry, i can't paste here the url, but it's a thread of this great forum) but it gives me errors. And also search examples for EnumProcessModules and thos apis but they only work con 32bits.

Thanks again to all of you, I'll continue trying to improve and fix my routine. If you know how to fix it, thanks again. Hahaha I'm feeling like a noob, sorry for that.
Back to top
View user's profile Send private message
Acubra
Advanced Cheater
Reputation: 0

Joined: 19 Jun 2011
Posts: 64
Location: C:\Windows\System32\HoG

PostPosted: Mon Feb 27, 2012 5:07 pm    Post subject: Reply with quote

Hey,
if you want to get the base address of a process look at the following API's:
CreateToolhelp32Snapshot
Process32First
Process32Next

If you need I can post a function I wrote using these API's.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 473

Joined: 09 May 2003
Posts: 25909
Location: The netherlands

PostPosted: Mon Feb 27, 2012 5:13 pm    Post subject: Reply with quote

EnumProcessModulesEx has support for 64-bit target processes

And the base address will only change in windows vista+ if it was compiled with the relocation flag set

_________________
Tools give you results. Knowledge gives you control.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Mon Feb 27, 2012 6:32 pm    Post subject: Reply with quote

Acubra wrote:
Hey,
if you want to get the base address of a process look at the following API's:
CreateToolhelp32Snapshot
Process32First
Process32Next

If you need I can post a function I wrote using these API's.


Yes please, if you have an example I'll really apreciate it.

Thank you.
Back to top
View user's profile Send private message
Stylo
Grandmaster Cheater Supreme
Reputation: 3

Joined: 16 May 2007
Posts: 1073
Location: Israel

PostPosted: Mon Feb 27, 2012 10:48 pm    Post subject: Reply with quote

Another way to get the process's base address is to access the PEB of the current process and get ImageBaseAddress.
Read about PEB( Process Environment Block ) http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/PEB.html

an example for that:
Code:

PVOID get_process_base_address() {
   PVOID   pBaseAddr;

   __asm {
      push eax
      mov eax,fs:[0x30]
      mov eax,[eax+0x8]
      mov dword ptr ds:[pBaseAddr],eax
      pop eax
   }

   return pBaseAddr;
}

_________________
Stylo
Back to top
View user's profile Send private message
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Tue Feb 28, 2012 12:36 am    Post subject: Reply with quote

Thank you so much Stylo, tomorrow I'll try your routine and I'll implement to my project.

You were right, it was not working again...
Now i fix it. It's reading the fine the memory, but I'm trying to verify in my loop if the value is a certain Text...

Code:

char* _stdcall ReadString(char *window, int Point, int Len)
{
   //char *value = (char*)malloc(Len+1) = {0};
   char value[8] = {0};

    HWND hWnd = FindWindow(NULL, window);
   DWORD proc_id;
   GetWindowThreadProcessId(hWnd, &proc_id);

   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, proc_id);
   

   BOOL bReturn = ReadProcessMemory(hProcess, (LPVOID)Point, value, 7, 0);
   if ( bReturn == 0 )
   {
      DWORD lastError = GetLastError();
      return 0;
     // error
   }
   else
   {
      // success
      return value;
   }
}


int _stdcall SearchString(char *window, char *Text)
{
   long int x;

   for(x = 0; x < 80000000; x++)
   {
       if (!strcmp(ReadString(window, x, 7),Text)) //This don't work fine :S...
      {
         return x;                     
      }
   }

   return 0;
}


Debugging it, i realized that it reads fine the value... but at the time to compare both, it's not working.

Thank you.
Regards
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 473

Joined: 09 May 2003
Posts: 25909
Location: The netherlands

PostPosted: Tue Feb 28, 2012 3:15 am    Post subject: Reply with quote

That is because the local variable named "value" has been destroyed. Don't allocate the memory in ReadString but pass it a pointer it can fill from SearchString
_________________
Tools give you results. Knowledge gives you control.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Tue Feb 28, 2012 1:14 pm    Post subject: Reply with quote

Thank you DarkByte. I've improved my "DLL", now it's working fine:

Code:
//////////////////////////////////////////////////////////////////
// Set UP the window wich we're gonna work with
//////////////////////////////////////////////////////////////////
void _stdcall SetWindow(char *window)
{
   hWnd = FindWindow(NULL, window);   
   GetWindowThreadProcessId(hWnd, &proc_id);
   hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, proc_id);
}

//////////////////////////////////////////////////////////////////
// ReadString from a certain Address and return as string type
//////////////////////////////////////////////////////////////////
std::string ReadString(int Point, int Len)
{
   //char *value = (char*)malloc(Len+1) = {0};
   char value[8] = {0};
   SIZE_T numBytesRead;
   
   if (ReadProcessMemory(hProcess, (LPVOID)Point, value, 7, &numBytesRead) == 0)
   {
      DWORD lastError = GetLastError();
      return "";
     // error - return an empty string
   }
   
   return std::string(value, numBytesRead);
}

//////////////////////////////////////////////////////////////////
// ReadLong from a certain Address and return as int (4bytes) type
//////////////////////////////////////////////////////////////////
int ReadLong(int Point) //We don't need Len (4bytes)s
{
   int tbuf;
   
   if (ReadProcessMemory(hProcess, (LPVOID)Point, &tbuf, 4, NULL) == 0)
   {
      DWORD lastError = GetLastError();
      return 0;
     // error - return 0
   }

   return tbuf;
}


//////////////////////////////////////////////////////////////////
// Search a Certain String in a process
//////////////////////////////////////////////////////////////////
int _stdcall SearchString(char *Text)
{
   long int x;
   
   PVOID ASD = get_process_base_address;

   for(x = 0; x < 80000000; x++)
   {
       if ( ReadString(x, 7) == Text )
      {
         return x; // Return the address we found                 
      }
   }

   return 0; //Error Return zero
}

//////////////////////////////////////////////////////////////////
// Search a Certain Long in a process
//////////////////////////////////////////////////////////////////
int _stdcall SearchLong(int Result)
{
   long int x;

   for(x = 0; x < 80000000; x++)
   {
      if ( ReadLong(x) == Result )
      {
         return x; // Return the address we found                 
      }
   }

   return 0; //Error Return zero
}


The only thing i would like to do now is to search from the Image Base Address of a process. Almost is 0x00400000 but it also changes in Windows 7 or Windows Vista, and I guess 64bits processors too. And then start searching from the Image Base Address of the process (pid), to make it faster and don't start from 0.

@Stylo: I tried your routine but it gives me the wrong addres, or there's something i miss to do...

Thank you.
Regards
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 473

Joined: 09 May 2003
Posts: 25909
Location: The netherlands

PostPosted: Tue Feb 28, 2012 1:30 pm    Post subject: Reply with quote

That works? Without eventually crashing due to out of memory or it returning useless garbage? (I'm not that familiar with c++ but return std::string(value, numBytesRead) seems wrong, but then again, c++ often seems wrong to me )

Edit: if it's one of those function context only objects I guess it'd work

_________________
Tools give you results. Knowledge gives you control.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Shalvaid95
How do I cheat?
Reputation: 0

Joined: 26 Feb 2012
Posts: 9

PostPosted: Tue Feb 28, 2012 1:43 pm    Post subject: Reply with quote

Yes, luckily it's working fine. I'm also new with C++... but well, asking help, and googling there's nothing you can't do. Now I'm trying to avoid start searching from 0, and do it from the image base address (0x004000 on windows xp 32b), but it seems there's no much information on the net about that.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites