WoW Memory EditingWoW Memory Editing for learning purposes only.
This section is more advanced than others on MMOwnedRead the section specific rules, infractions will be given out if u break them!That is including the expectations! - If you don't meet them then don't post
First of all: this tutorial describes the very earliest phase of programming an own bot/hack/tool/whatever. Most of you do already know this info or don't have to know it due to the libraries which are out there in the net. Although, it would be nice if you could fly over the code and post suggestions for improvements that I could make. (may it be coding style or bad performance or something else...)
Since I'm also pretty new to memory editing, I want to build things by hand instead of taking a library. I want to understand what the single steps are which are processed in the background. Therefore, I've started to write some little program from scratch.
The first action you have to do to begin with reading / writing memory, is to get a process handle via the OpenProcess() function from psapi.dll. OpenProcess requires the process' ID.
You can't get this ID that easy, since there could be multiple WoW's running and therefore you can't simply enter "WoW.exe" into some magic function and get the process ids from them.
The solution is to enumerate over all active processes regardless of them being wow processes or not, and to get their process names. Then, it's a simple string comparison with "WoW.exe" and you are done.
Note that you need to add the "SeDebugPrivilege" to the own processes ProcessToken to access some processes, including the WoW process. This requires the process to be elevated to administrator rights in Windows Vista and up. The privilege has to be set as soon as you access the process with OpenProcess(); The second function takes care of setting the flag.
To elevate the process, just go to the Linker => Manifest settings in the project properties and choose requireAdministrator in the UAC dropdown field.
The attachment contains my implementation of the mentioned functions, which automates this process of getting the process ID.
If you use your tool for only one Wow.exe process, then there's easier way.
FindWindow() to get Wow window handle, GetWindowThreadProcessId() to get wow's pID (additionally you can get mainthread ID), OpenProcess to get wow process handle.
Thanks for your feedback! Very important to fix my coding errors etc. in the beginning rather than later.
Quote:
Your code is awful (riddled with potential bugs and crashes, poorly designed, etc), however the concept is there... I guess...
I think that you mean the error handling with "crashes", the fact that a process could go away in the middle of my function and respawn as a WoW.exe with the same PID with "bugs" and the ugly non-descriptive bool return type and the fact that you can't get pids without debug rights with "poorly designed".
Quote:
Just in case someone likes to see a different attempt to get that job done, here is the code I use in my lib
I think that the idea of taking a snapshot and operating on it is cleaner than having the risk of processes spawning and going away during the code. Think that I will go for it too.
I only see four small things you could add:
- the user inputted process name is not converted to lowercase. however, the process names are.
- Process32First returns a BOOL, not an int
- since PROCESSENTRY32.szExeFile is an array of TCHAR and not of WCHAR, you should use std::string instead of std::wstring to not making it crash on non-unicode systems.
- CloseHandle uses SEH and can throw exceptions if running under a debugger. However, outside of the debugger, you should be fine.
- the user inputted process name is not converted to lowercase. however, the process names are.
Yeah, you are right. Right now I am the only one using it and I consider myself smart enough to use my own code correctly, but good suggestion.
Quote:
- Process32First returns a BOOL, not an int
BOOL is a typedef to int. I personally don't like all the Windows-typedefs and as long as they are just typedefs to basic datatypes (and no structures) I rarely use them.
Quote:
- since PROCESSENTRY32.szExeFile is an array of TCHAR and not of WCHAR, you should use std::string instead of std::wstring to not making it crash on non-unicode systems.
Everything in my lib uses widestrings only.
Quote:
- CloseHandle uses SEH and can throw exceptions if running under a debugger. However, outside of the debugger, you should be fine.
just looked again at the closehandle thing on MSDN
Quote:
If the application is running under a debugger, the function will throw an exception if it receives either a handle value that is not valid or a pseudo-handle value.
since the handle stays inside the function and we ensure manually that it is valid and not a pseudo-handle value (wtf is this?), we don't need to check for this SEH exception. however, the normal exception should be caught:
Quote:
If the function fails, the return value is zero. To get extended error information, call GetLastError.
since we don't have influence of this one.
I've updated the first post with the new code. Please look at it even if you are familiar with memory editing so that I can improve with an easy sample which doesn't take much time to change. Note that it is not necessary to have debug privileges, since openprocess is not called anymore to list them.
Thanks for your feedback! Very important to fix my coding errors etc. in the beginning rather than later.
I think that you mean the error handling with "crashes", the fact that a process could go away in the middle of my function and respawn as a WoW.exe with the same PID with "bugs" and the ugly non-descriptive bool return type and the fact that you can't get pids without debug rights with "poorly designed".
No.
* You're using pointers rather than references in a totally unnecessary manner.
* You're leaking resources all over the place due to a lack of RAII. (Example: You call OpenProcessToken, then if LookupPrivilegeValue fails you throw an exception without cleaning up the handle.)
* You're using global data unnecessarily. This can cause threading issues and is simply bad style.
* Your code is a messy mix of C and C++. You use C++ containers but then use C-style strings. C++ style strings are there for a reason.
* Lots of your code lacks const-correctness.
etc
__________________
[Only registered and activated users can see links. ]Back online!
"Science is interesting, and if you don't agree you can **** off." [Only registered and activated users can see links. ]
"I can write very coherent things when I try that sound very good" -- Styles
First of all, +rep for your post, Cypher, and thanks for taking some time to look over my code.
Quote:
* Your code is a messy mix of C and C++. You use C++ containers but then use C-style strings. C++ style strings are there for a reason.
I've googled about the differences of them and just have to say that you are perfectly right. Taking an std::string isn't really more unefficient than using direct TCHAR[] although it's more "high-level" and you don't feel the inner representation that much. They are just the new way to handle strings.
=> Changed the argument to a std::string (which should be converted to std::basic_string<TCHAR> via all the typedefs and therefore to a std::wstring on unicode systems (?) )
Quote:
* You're using pointers rather than references in a totally unnecessary manner.
also read about this and have to agree with you again. Call by reference is better than call by pointer, since you don't have to check for NULL at runtime and it is easier to use. The bad side of it (and the only one where I think that call by pointer should be used) is that they you cannot use them for pointer arithmetic. for example, the following will not work. (yes i know that it's not the best example).
Code:
char x[] = "Cypher rocks!";
char *c = x;
while (*c++) {
// do something
}
Quote:
* You're using global data unnecessarily. This can cause threading issues and is simply bad style.
I think that you want to point to this "execute only once" bool out there which doesn't prevent two threads to execute the method at the same time and causing it to set the flag multiple times in some potential cases. Although it doesn't do something bad in this case (well, you set it two times, but that's just some minimal amount of time wasted by one of them), I see your point.
=> Since it is not the point of the (minimal) "library" to decide whether or not to set a flag (maybe, some other command from the user has reset the flag and you actually WANT to set it again), I've removed it.
There's one question left. How do you make some proper version of such a once function?
Quote:
* Lots of your code lacks const-correctness.
and another concept I didn't know before as I understand it, you should mark everything with const that has not to be modified.
i've found the following:
the argument of GetPidsByProcessName. however, since it is now an std::string and therefore passed by value (which is not inefficient at all, the way how strings are stored), I can ignore it.
HANDLE hProcessSnapshot, since it is not changed somewhere
HANDLE hToken: does NOT work, since it is set via reference. is there a way to const it afterwards?
(somehow, the LIST board code has stopped working)
Quote:
* You're leaking resources all over the place due to a lack of RAII. (Example: You call OpenProcessToken, then if LookupPrivilegeValue fails you throw an exception without cleaning up the handle.)
didn't heard about that either. (why aren't these concepts teached in normal tutorials... cypher you should write a c++ beginner book which takes care of such concepts :-))
will use the shared_ptr's with custom deleter to accomplish this goal as soon as service pack 1 for VS08 is downloaded and installed and I have it defined in the <memory> header file.
thanks again for your hints. will update code tomorrow
A good reason to use std::string over pointers to character-arrays is that you can't stop a user from being retarded.
What if the user gives you a pointer pointing to somewhere out of the applications memory space? Your function will crash. What if your function gets fed by a non-zero-terminated C-string ?
Problems which can't appear if you use std::strings.
Quote:
=> Changed the argument to a std::string (which should be converted to std::basic_string<TCHAR> via all the typedefs and therefore to a std::wstring on unicode systems (?) )
The C++-Lib doesn't know TCHAR. Just typedef it yourself?
1. You can still do pointer arithmetic in most cases, however you shouldn't need to in most cases so your point is moot:
void Foo(const std::string& Arg1, const std::vector<DWORD>& Arg2)
{
char const * const pBlah = Arg1.c_str(); // pointer to my string
DWORD const * const pBlah2 = &Arg2[0]; // Pointer to my buffer
}
You don't need to use the method you presented to loop over a string, C++ strings provide iterators and the subscript operator for a reason.
2. Don't take strings by value. Take them by reference-to-const. See the code I posted above for an example. Doing this is in most cases 'faster' that taking the string by value, but it is never slower. So you only stand to gain from doing it.
3. In order to do a proper 'execute-once' function I'd use boost's threading library. It offers such a function which uses the correct atomic operations in order to set/get the value.
4. You don't want a shared_ptr with a custom deleter. Check out the "EnsureCleanup" class from 'Windows via C/C++'. [Only registered and activated users can see links. ]
__________________
[Only registered and activated users can see links. ]Back online!
"Science is interesting, and if you don't agree you can **** off." [Only registered and activated users can see links. ]
"I can write very coherent things when I try that sound very good" -- Styles
damn it. downloaded the service pack for the wrong language version..... -.- have to wait the whole evening until the correct one is installed and i can merge my code with the newly gained knowledge.
@1: i know that my example is not the best but could not imagine a better one. maybe there is really absolutely never a reason for call by pointer. thanks for the hint about iterators! just knew that you can access the std::string's character also over the array index
@4: what's the exact difference between the "shared_ptr with a custom deleter" and the "ensurecleanup"? for me it looks like being similar: it takes the HANDLE and a custom deleter and calls the deleter as soon as it is not referenced anymore.
@2: it makes sense that it cannot be slower since the address of the string doesn't need to be calculated in an expensive way => will update my code with this.
@3: okay, so it seems to work with semaphores as the only way to accomplish it. since i have removed the "once"-part of the function, i'll just keep that in mind.
@flo:
- hmm: char is typedeffed to TCHAR, string is typedeffed to basic_string<char> => and therefore to basic_string<TCHAR>. am i wrong? EDIT yes was wrong. tchar is typedeffed to char.