Saturday, March 17, 2012

Process Injection with SoNew

So I finally finished at least the first method of DLL injection using my new injection framework. I'm not entirely convinced my class layout is the best, but it looks at first glance like this abstraction should be OK for handling the various injection methods.  I've also had thoughts of scraping DLL injection entirely and focusing on building a custom game debugging engine that would allow me to use the power of windbg and python via the python interpreter extension to script up games. Regardless, I'm going to keep plugging away at SoNew because I'm learning a lot about windows junk that I should have known but never invested any of my time in researching.

As a side note, I have a terrible habit of buying very expensive technical books and only reading the first chapter. This game hacking project of mine has shown me I own a lot of books with good information that I can use. For example I didn't realize the Windows Via C/C++ book I bought years ago had an entire chapter on DLL injection. There's also some great information regarding Windows Internals in it as well.

So here's the basic run down of how SoNew works. There are three objects; a process, an injector, and the injector details. The Process object obviously represents the process we are injecting into. In the future I plan on exposing more methods of mucking with the internals of a remote process (exposing read/write process memory etc.). The Injector is an abstraction of the various injection methods. This is created with various attributes that the user specifies via command line arguments. Once we have our injector object created, we pass it to the process' InjectInto method which will handle the injection/execution of our DLL or code. This *should* make it easy for us to create new injection method classes and not have to change anything about how we inject, it's entirely up to the injection class to handle the details.

As for the CreateRemoteThread & LoadLibrary method of injection. I'm not going to go into gory details on how it works because there's really a ton of information out there already. However, here's the quick run down:
1. Use OpenProcess to get a handle to the remote process, making sure to pass flags that give us proper permissions.
2. Call VirtualAllocEx passing in the handle to the process and how much space we want to allocate. In this case, we only allocate strlen(<dll path string size>). It returns the address in the remote process where this string is stored.
3. Call WriteProcessMemory passing in the process handle, the address we got from VirtualAllocEx, the dll path string, and the length of said string.
4. At this point we have injected all the necessary details. We then switch to our Execute() method of our injector.
*5. We need to get the address of LoadLibraryA(or W). So we use GetProcAddress passing in kernel32's handle (via GetModuleHandle) and the LoadLibraryA string. We cast the FARPROC return value of GetProcAddress as being a PTHREAD_START_ROUTINE because it has the same basic call structure as ThreadFunc.
6. Finally we call CreateRemoteThread, passing in the process handle (from step 1), the address of  LoadLibraryA (from step 5), and the address of our DLL string in the remote processes memory (from step 2/3).

That's pretty much all there is to it. Note on step 5, I had some initial concerns that due to recent advancement of ASLR that getting the address of LoadLibraryA from SoNew's process wouldn't be the same address of the process that I'm injecting into. But thankfully the address is the same on all processes (however it does change on reboot, but again all processes share the same address, so whatever.) So, we can do this... but uh it's kind of useless. We have no way of doing communication between SoNew and the injected code. Also I only got the DllMain to fire, not an exported function. This is extremely limiting. I think I'll figure out how to call exported functions from the DLL next. Also, I've read of people using things like named pipes to synchronize information between injector and injectee which might be worth implementing.

 However, the more I think about all of this, the more I'd rather have a sweet debugger/injector that gives me access to a python interpreter. Maybe I'll make another side project for that :>.

I have also started to realize I need to start looking into what anti-debugging tricks game protection systems are using. No point in writing all this if something like PunkBuster hooks CreateRemoteThread and kills your hacks immediately (then bans the hell out of you). If anyone who does this stuff knows what methods games are using these days, please contact me :>.

As for how to actually use SoNew here's an example of me injecting the SoNewTestDll.dll into winamp.exe.
Note all it does is pop up a MessageBox.
SoNew Injecting into winamp.exe.

Oh and you can download SoNew from https://github.com/wirepair/SoNew/. Enjoy the bugginess!

2 comments:

  1. I found two values that appeared to be the stringified versions of two md5 hashes. I highly suspect this function is used to generate that GUID. I'm still doing static analysis at this point, my next post will probably clarify what is going on by setting bp's in the debugger while it runs. Game hacks

    ReplyDelete