Click here to Skip to main content
15,888,269 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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 "Example". (7 len)

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

C++
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 == 'Example')
        //{
        //       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: "Example" (7 len). I would like to compare it and verify if actually it is "Example" 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 "Example" 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

ps: I am using VC++ 6.0
Posted

in c++ you compare strings with the strcmp[^] function

So your if statement would become

if (!strcmp(value,"Example"))<br />
        {<br />
              return 10;<br />
        }<br />
 
Share this answer
 
Gday there mate.

I can see two things that may help you right off the bat.

1. You need to allocate memory for your buffer - char *value; won't cut it. You need to allocate at least the number of bytes that you plan on reading. 1 more byte if you plan to read a string into this buffer and print it from there.
Perhaps something like: char *value = (char*)malloc(len+1);

2. If you want to compare a string, you should look into the strcmp functions. They offer both case-sensitive and case-insensitive comparing, ANSI and Unicode too.
E.g
C++
if (strcmp(value, "Example) == 0)
{
  //do something since the string in value is "Example"
}
 
Share this answer
 
Comments
ShirkoPro 26-Feb-12 22:48pm    
Thank you so much for your help. 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!!!
PS: I also included "#include <string>" ...

My VB 6.0 Code:

<pre lang="vb">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</pre>

I respond only 1 time because the two solutions give me the same error, thanks both of you!!
I'd like to add code, since the comments aren't particularly conducive to that end, I'll put it here.


My thoughts are that you're getting an access violation when trying to open the process's memory. Here's some code I used to read the game-board from WinMine, back when I created a bot to play the game for me.

The code was called thusly:

C++
// read board Size - number of tiles on board, e.g 9x9, 16x16, 16x30
resCode = readMemBlock("WINmine.exe", 0x1005334, sizeof(e_bwSize), &e_bwSize);
if (resCode == 0)
    return -1;
printf("Board size: %d,%d\n", e_bwSize.iWidth, e_bwSize.iHeight);
iBoardWidth = e_bwSize.iWidth;
iBoardHeight = e_bwSize.iHeight;

// read board array
resCode = readMemBlock("WINmine.exe", 0x1005361, iBoardWidth*iBoardHeight, boardBuffer);

C++
unsigned long _GetProcessId( char* szProcName )
{
    PROCESSENTRY32 pe32;
    HANDLE hHandle;

    hHandle = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    pe32.dwSize = sizeof( PROCESSENTRY32 );

    if( !Process32First( hHandle, &pe32 ) )
        return 0;

    while( Process32Next( hHandle, &pe32 ) )
    {
        if( stricmp( szProcName, pe32.szExeFile ) == 0 )
        {
            CloseHandle( hHandle );
            return pe32.th32ProcessID;
        }
    }
    CloseHandle( hHandle );
    return 0;
}


// reads a chunk of memory from a running program's memory space
// Buffer must already be allocaed and hold space for length bytes
bool readMemBlock(char *szProgName, unsigned long dwMemAddr, unsigned long length, void *Buffer)
{
    HANDLE hHandle;
    SYSTEM_INFO sysInfo;
    MEMORY_BASIC_INFORMATION mbi;
    bool resCode;
    DWORD lastErrCode;

    hHandle = OpenProcess( STANDARD_RIGHTS_REQUIRED|PROCESS_VM_READ, FALSE, _GetProcessId( szProgName ) );
    //PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|


    if( hHandle == INVALID_HANDLE_VALUE || hHandle == NULL )
    {
        printf("Error opening process\n");
        if (!hHandle)
            printf("hHandle == NULL\n");
        else
            printf("INVALID_HANDLE_VALUE");

        LPVOID lpMsgBuf;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                                    NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                                    (LPTSTR) &lpMsgBuf, 0, NULL);
        // Display the string.
        printf("Get last Error: %s\n", lpMsgBuf);
        // Free the buffer.
        LocalFree( lpMsgBuf );

        return false;
    }

    resCode = ReadProcessMemory( hHandle, (unsigned long*)dwMemAddr, Buffer, length, NULL );
    CloseHandle(hHandle);
    return resCode;
}
 
Share this answer
 
ReadProcessMemory(hProcess, (LPVOID)Point, &value, 7, 0);

The above code is wrong. you should pass a buffer equal to the size of memory you want to read.

char value[8] = {0};<br />
ReadProcessMemory(hProcess, (LPVOID)Point, &value, 7, 0); 


after this compare the content of the "value" using functions like strcmp
 
Share this answer
 
Comments
ShirkoPro 27-Feb-12 12:55pm    
Thank you all of you, As the 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;
}
}

I had tried to compare my 2 values 3 days ago using strcmp, but it was not working because the 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 ****ing 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 will not work properly.

I've tried an example with apis but it gives me errors. And also search examples for EnumProcessModules and those apis but they only work on 32bits.

Thank you again. I'll continue trying to improve and fix my routine and optimize it of course. If you know something, thanks again.
Regards
Naveen 27-Feb-12 21:49pm    
Your current code is ok. But better improve it. First find the window, open the process and then do the for loop to read the process memory. Also remeber to close the handle returned by openprocess.

Now to get the exe modules base address and size, it better to use the module32first and module32next function. Good luck.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900