DLL function crashes my program

Oct 24, 2016 at 7:48pm
Hello everyone. I've a simple problem, but I couldn't solve it yet because I'm a newbie in programming. See if you can help me:

I'm creating a C++ trainer for a game. I've created a lot of trainers before, but what happened to me this time is curious: I'm not able to use WriteProcessMemory()/ReadProcessMemory. But this only happens in Windows 7. I can use WPM and RPM normally in Win XP.

So I tried to google everything, and I found something capable of editing the memory of the game I'm targetting; Cheat Engine. But normal options in Cheat Engine couldn't edit memory (Memory Viewer just had ?? on it), I had to enable a Kernel Mode routine option for WPM/RPM (whatever). Never mind. But the important thing is that, if some program can edit that memory, mine could too. So here I am, trying to simulate the same thing CE does.

In sum, what I want is to use the WPM/RPM functions like Cheat Engine does. I think I'm in the way to do that, but just need a simple help. Have a look at my

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h> 
#include <objidl.h> 
#pragma comment(lib, "user32.lib") 
int newdata;
DWORD newdatasize;




typedef   HANDLE   (__stdcall *OPfunc)(DWORD dwDesiredAccess,BOOL  bInheritHandle,DWORD dwProcessId); 
typedef   bool   (__stdcall *WPMfunc)(HANDLE  hProcess,LPVOID  lpBaseAddress,LPCVOID lpBuffer,SIZE_T  nSize,SIZE_T  *lpNumberOfBytesWritten); 
typedef   bool   (__stdcall *RPMfunc)(HANDLE  hProcess,LPVOID  lpBaseAddress,LPCVOID lpBuffer,SIZE_T  nSize,SIZE_T  *lpNumberOfBytesWritten); 



void enableDebugPrivileges() {  
    HANDLE hcurrent=GetCurrentProcess();  
    HANDLE hToken;  
    BOOL bret=OpenProcessToken(hcurrent,40,&hToken);  
    LUID luid;  
    bret=LookupPrivilegeValue(NULL,"SeDebugPrivilege",&luid);  
    TOKEN_PRIVILEGES NewState,PreviousState;  
    DWORD ReturnLength;  
    NewState.PrivilegeCount =1;  
    NewState.Privileges[0].Luid =luid;  
    NewState.Privileges[0].Attributes=2;  
    AdjustTokenPrivileges(hToken,FALSE,&NewState,28,&PreviousState,&ReturnLength);  
}


BOOL SetProcessEditPriv(LPCSTR Priv, HANDLE pHandle) 
{ 
   HANDLE hToken; 
   LUID luid; 
   TOKEN_PRIVILEGES Privs; 
   ZeroMemory (&Privs, sizeof(Privs)); 
   if (!OpenProcessToken (pHandle, (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), 
      &hToken)) 
   { 
      printf("No se pudieron modificar los privilegios");
      return FALSE; 
   } 
   if (!LookupPrivilegeValue (NULL, Priv, &luid)) 
   { 
      CloseHandle (hToken); 
      return FALSE; 
   } 

   Privs.PrivilegeCount = 1; 
   Privs.Privileges[0].Luid = luid; 
   Privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

   BOOL retValue = AdjustTokenPrivileges(hToken, FALSE, 
      &Privs, sizeof(Privs),NULL,NULL); 
   CloseHandle(hToken); 
   return retValue; 

}




void EnableDebugPriv()
{
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);

    CloseHandle(hToken); 
}

int main( int, char *[] )
{
    
    



unsigned long PID; // We need this now to store the PID. 
HANDLE hProcess; //We will use this for OpenProcess 
HINSTANCE hDllTrainer; 
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
HWND hWindow = FindWindow(NULL, "Minesweeper"); 
GetWindowThreadProcessId(hWindow, &PID); 
DWORD ToBeWritten[]={0x90}; 
DWORD Newdatasize = sizeof(ToBeWritten); 

hDllTrainer = LoadLibrary("dbk32.dll"); 
if(hDllTrainer != NULL) { 
 
   } 
   else if(!hDllTrainer) { 
   MessageBoxA(0, "Error! Couldnt Load dbk32.dll! Quiting.", "ERROR!", MB_ICONINFORMATION); 
} 
    
    
    

OPfunc OP; 
OP=(OPfunc)GetProcAddress(hDllTrainer,"OP"); 
if(OP==NULL){MessageBox(NULL,"OP = NULL","",MB_OK);}
WPMfunc WPM; 
WPM=(WPMfunc)GetProcAddress(hDllTrainer,"WPM"); 
if(WPM==NULL){MessageBox(NULL,"WPM = NULL","",MB_OK);}
RPMfunc RPM; 
RPM=(RPMfunc)GetProcAddress(hDllTrainer,"RPM"); 
if(RPM==NULL){MessageBox(NULL,"RPM = NULL","",MB_OK);}
    
    //EnableDebugPriv();
enableDebugPrivileges();

    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    if (Process32First(snapshot, &entry) == TRUE)
    {
        while (Process32Next(snapshot, &entry) == TRUE)
        {
            if (stricmp(entry.szExeFile, "msd.exe") == 0)
            {  
                                         //HANDLE hProcess;
                HANDLE hProcess = OP(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);

//^ OP is successful in above code (OpenProcess in Kernel Mode, I think)




               if(hProcess)
               { printf("Process was found succesfully");
               
                SetProcessEditPriv(SE_DEBUG_NAME,hProcess);
               
               VirtualProtectEx(hProcess,(LPVOID)0x0001000C,256,PAGE_EXECUTE_READWRITE, NULL); 
              
               
               
               
               BYTE BufferOut = 0x00; 
   int BufferSize = sizeof(BufferOut); 
   int BufferIn; 
   SIZE_T bWritten; 
   DWORD OldProtection = -1; 
   MEMORY_BASIC_INFORMATION mbi; 
             // if (!VirtualProtectEx (hProcess, (LPVOID)0x0001000C, BufferSize, PAGE_EXECUTE_READWRITE, &OldProtection)) 
    //  printf("\n\nNo se han podido modificar los permisos de memoria. Error %d\n\n",GetLastError());
               BYTE bP = 0x00;
               if (ReadProcessMemory(hProcess, (LPVOID)0x0001000C, &bP, sizeof(BYTE), NULL)) 
{printf("\n\nLeitura feita. Resposta: %d",BufferOut);}else{printf("\n\nLeitura falhou. LastError:%d",GetLastError());}
               
               
               newdata = 30;
     		 	newdatasize = sizeof(newdata);
     		 	
     		 	
     		 	
     		 	//func(hProcess, (LPVOID)0x0001000C, &bP, sizeof(BYTE),(DWORD*)2);
     		 	
     		 	
     		 	//WPM(hProcess, (LPVOID)0x0001000C, &bP, sizeof(BYTE),NULL);
     		 	//WPM(0,0,0,0,0);
     		 	
                  
                  WPM(hProcess, (LPVOID)0x0001000C, &bP, sizeof(BYTE), NULL);// << This crashes. Why?
     		 	
      			if(WriteProcessMemory(hProcess, (LPVOID)0x0001000C, &bP, sizeof(BYTE),NULL))
			{
        				printf("\n\nMemory written succesfully.\n\n");
      			} 
      			else{printf("Erro ao manipular memoria! Codigo do erro: %d",GetLastError());}
               }





                CloseHandle(hProcess);
            }
        }
    }

    CloseHandle(snapshot);


system("pause>nul");


    return 0;
}


What is this horrible code?

Well, it turns out that Cheat Engine (the 5.X versions) uses a DLL called dbk32.dll. This DLL is somehow related to the functions of that Kernel thing. It basically loads a driver (dbk32.sys) and lets the Cheat Engine use the functions of RPM/WPM and OpenProcess (OP). So I tried to use that dll and that sys in my C++ program, in order to do what CE does (and, finally, be able to edit the memory).

I was able to somehow use the OP function (OpenProcess), and it worked. But the WPM and RPM functions crash my C++ program. Why is that?

Could you help me do what I want to do? I want to use those WPM and RPM functions properly, in order to be able to edit the memory of the game. I wish I could simply use the normal WriteProcessMemory thing.

The code above is just a scratch I created from zero, and it has nothing organized in it. Just look at the part "WPM(hProcess, (LPVOID)0x0001000C, &bP, sizeof(BYTE), NULL);// << This crashes. Why?" and tell me why it crashes.

Or, if there is another way to accomplish what I want, please help me.

Thanks!
Last edited on Oct 24, 2016 at 7:58pm
Oct 25, 2016 at 4:18am
But the WPM and RPM functions crash my C++ program.

Is there an error message? What does it say? Is it a C++ exception? How about an asynchronous exception thrown by Windows? Have you tried tracing the code with a debugger?

I found the source code here:
https://github.com/cheat-engine/cheat-engine/blob/0b3daac79d5faf12b9250914a820e2352d9c7236/Cheat%20Engine/dbk32/DBK32functions.pas

Presumably this is where WPM is defined. It's a wrapper around a Win32 API call written in Object Pascal.
Oct 25, 2016 at 7:48pm
There is no error message. The console window simply vanishes exactly in the WPM() function. I know it's exactly there because I tried inserting MessageBoxes(). No error messages are displayed.

I've little to no experience with assembly debuggers, but I'm gonna give it a try, maybe I can compare the Cheat Engine's WPM instructions with the instructions of my WPM. It's gonna be hard, though.

I can't understand Object Pascal, but even so I examined the Cheat Engine source and managed to get OP to work (OpenProcess). I just need WPM and RPM now. I didn't even know what a wrapper is (now I do, googled it)



I figured out how to stop WPM to crash, but it doesn't work either, memory is not written (checked this with CE)
WPM(hProcess,(LPVOID)0x0001000c,&newdata,newdatasize,(DWORD*)2) //< doesn't crash, but memory is not changed, in sum, doesn't work yet


I'm going to let the link of the folder I'm testing all of these things. I would really like my C++ program to edit memory in Windows 7 processes, but, for that, I've to "copycat" the way Cheat Engine does it. Please help with that: http://www.4shared.com/rar/NXrxA-K0ba/WPM_and_RPM.html?


Here is the Cheat Engine code I was looking at (it's the 5.6.1 one, because the dbk32.dll is not found in 6.X versions): https://github.com/cheat-engine/cheat-engine/tree/Cheat_Engine_Old
Last edited on Oct 25, 2016 at 7:56pm
Oct 26, 2016 at 2:39am
I'm not in the best position to help, since I run only Linux machines nowadays, and haven't done any Win32 development in more than 4 years.

maybe I can compare the Cheat Engine's WPM instructions with the instructions of my WPM

What's the difference? Unless I'm misunderstanding something, your program is being dynamically linked with the Delphi code in dbk32.dll? If you are certain the code is crashing inside the shared library then you need to check your inputs before investigating lower down.

You should check the result of WPM: it is intended to return false if it is unsuccessful.

Re. the crashes:
You should check... using WinDBG(Is that the name?) to see if the program has dumped core. Random crashes could presumably be caused by certain types of faults in kernel space (nowadays not every driver bug causes a panic). Remember that you loaded a kernel module (dbk32.sys). If there is one, then it will likely offer a lead.

I debugged a driver issue for a friend about 6 months ago - the core dump was available somewhere in System32/, IIRC; do a search for filenames matching *.dmp and check the atime to see if it corresponds with the crash.
Oct 26, 2016 at 9:00pm
This is becoming too complicated.

Isn't there another way to make WriteProcessMemory() and ReadProcessMemory work for all processes?

I mean... For some of the processes I try to use them, they work, but for some others, they don't...


I tried some privilege things (I supposed there was some relation with the GetLastError 5), but nothing worked...

Isn't there another function to replace the WriteProcessMemory? I just need to modify an address... Shouldn't be that difficult
Oct 26, 2016 at 11:40pm
(I supposed there was some relation with the GetLastError 5)

You have to remember that I can't (and wouldn't) run your code -- are you saying that GetLastError returned 5? Where? This is ERROR_ACCESS_DENIED.

You should try to check the results of pretty much everything that can fail.

WriteProcessMemory() is a Win32 API.
You can invoke that directly. You will need to request access to the process you wish to modify by obtaining a process handle using the appropriate flags.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674(v=vs.85).aspx
Last edited on Oct 26, 2016 at 11:57pm
Oct 27, 2016 at 1:16am
GetLastError returned 5 when I placed it exactly after the WriteProcessMemory (the normal one, which always worked perfectly for me, but not now). What is interesting is that the very same C++ code can edit memory in Windows XP but cannot in 7 (in the very same process).

If I try to place GetLastError right after WPM() (the supposedly kernel one), I can't get anything out of it, because WPM() crashes the entire program before I can extract any info about it...

Another interesting thing is that ReadProcessMemory (w/o kernel) also returns 5 in 7, but works normally in XP (at least for me), and OpenProcess (the normal one) works just like OP (kernel one), at least "macroscopically". In 7, if I try to execute my program in non-admin mode, it doesn't find (or cannot open) processes, but if I try in admin mode, it does find the processes, but then the read and write functions return 5.

I've tried almost every combination of flags, privileges and things like that (exaggerating, but not quite much), and nothing... Always GetLastError 5

I started this post asking for the kernel version of WriteProcessMemory and WriteProcessMemory because Cheat Engine is the only thing existing in universe that can edit the program I'm trying to edit in Windows 7, but, as it's becoming too complex, I'm gonna try to fix the normal ReadProcessMemory and WriteProcessMemory.

You will need to request access to the process you wish to modify by obtaining a process handle using the appropriate flags


I've firstly tried opening the process with PROCESS_ALL_ACESS, and, since normal WPM and RPM failed, I tried with PROCESS_VM_OPERATION | PROCESS_VM_WRITE, same failure.
Topic archived. No new replies allowed.