Friday, March 23, 2012

Asmjit Based Loader

The reason I'm using asmjit is because it's much better than writing inline assembly. When I used to write memory corruption exploits and shellcode, I used to have to write __asm {} blocks, compile it, look at the generated asm in a debugger/hex editor, copy the bytes, create a char buffer with the data in hex and finally do stupidly crazy unreadable indirection to call it. Like ((void (*)(void)) &shellcode)(); I still don't understand that shit. Overall, it was a very delicate and irritating process.

With asmjit I don't have to do any of that crap. Asmjit is great because it totally abstracts out how you create your instructions, gives you type safety and allows you to serialize the code into data (which I demonstrate in this post). It also contains functions on relocating addresses for when you inject into a remote process.

Asmjit exposes two objects, a compiler and an assembler. I'm not entirely sure about all of the differences, but from what I can tell the compiler seems to be an abstraction on top of the assembler. I believe it is for writing 'higher level' assembly, but in my case I want to write to registers directly because I know exactly what I want.

So what do I want? In this case I want to write a loader that can take in arbitrary dll names and function names. When I used to write shellcode I wasn't afforded one very important luxury. I was exploiting a *remote* process and had *no* idea where any addresses were. To call any win32 functions you need two things. The base address of kernel32, and a method to find the addresses of symbol names. Basically you needed to hand code your own GetProcAddress. If you're curious of an implementation, check out this oldie but goodie at http://www.harmonysecurity.com/files/kungfoo.asm. I'm pretty sure I copied/used that shellcode at somepoint in my past :).   When I first started writing the loader for this post, I was actually rewriting that block of asm in asmjit! Then I thought to myself, what the hell am I doing? I already *know* the addresses of GetProcAddress/LoadLibrary! It's the same for all local processes.

So now I'm doing local injection which gives me, well two things. First, I can easily get the base address of kernel32 using GetModuleHandle. And second, I can get the addresses of GetProcAddress and  LoadLibrary by using none other than GetProcAddress. Then, with the awesomeness of asmjit I can insert these addresses as immediate values directly into my Assembler. I can also write my data (such as the dll path and export name) directly into this Assembler by using the data() method and specifying the buffers and their size. I use a trick which is common in shellcode to jmp down to your data then call back up to your code. By doing this, the call instruction will take the next instruction and store it on the stack for you. You can then either pop it off, or use it directly in your calls. The rest of my code basically just goes through setting up the function calls and grabbing the addresses of the buffers, pretty simple really.
Injecting a DLL and calling an exported function using asmjit


Things of course will need to be changed once I move this code into SoNew as we will be injecting into a remote process.. But without further ado, here's my test loader code, enjoy!


// AsmJitTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// AsmJit - Complete JIT Assembler for C++ Language.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <asmjit/asmjit.h>
#include <asmjit/memorymanager.h>

// This is type of function we will generate
typedef int (*MyFn)();

int main(int argc, char* argv[])
{
 using namespace AsmJit;
 const char *dll = "C:\\Research\\SoNew\\Debug\\SoNewTestDll.dll";
 const char *exported_function = "RunTest";

 HMODULE kernel = GetModuleHandle(L"kernel32"); // need kernel32's base address
 FARPROC load_library = GetProcAddress(kernel, "LoadLibraryA"); // need ll
 FARPROC get_proc_address = GetProcAddress(kernel, "GetProcAddress"); // heh :>.
 if (load_library == NULL) {
  printf("load_library is null: %d",GetLastError());
  return -1;
 }
 if (get_proc_address == NULL) {
  printf("get_proc_address is null: %d",GetLastError());
  return -1;
 }
 
 // ==========================================================================
 // Create Assembler.
 Assembler a;
 FileLogger logger(stderr);
 a.setLogger(&logger);
 {
  Label L_lib = a.newLabel();
  Label L_start = a.newLabel();
  Label L_funcname = a.newLabel();
  Label L_callfunc = a.newLabel();
  Label L_exit = a.newLabel();
  
  // Prolog.
  a.push(ebp);
  a.mov(ebp, esp);
  a.jmp(L_lib);      // jmp down to where our lib/dll is.
  a.bind(L_start);     // oh hai again!
  // Start.
  // just to show eax contains addr (next two calls not needed)
  //a.pop(eax);      // address of our dll.
  //a.push(eax);      // push on to stack for ll call
  a.call((sysint_t)load_library);  // load our dll
  a.cmp(eax, 0);      // module should be stored in eax.
  a.je(L_exit);      // make sure we have a valid module handle
  a.mov(edx, eax);     // store module in edx
  a.jmp(L_funcname);     // get the exported_func's address
  a.bind(L_callfunc);
  // just to show eax contains addr (next two calls not needed)
  //a.pop(eax);      // the name of our exported func
  //a.push(eax);      // push name of our exported func
  a.push(edx);      // push addr of our dll
  a.call((sysint_t)get_proc_address); // get exported_func's addr.
  a.cmp(eax, 0);      // func should be stored in eax.
  a.je(L_exit);      // if not bomb out
  a.call(eax);      // and call it!  
  // Epilog.
  a.bind(L_exit);
  a.mov(esp, ebp);
  a.pop(ebp);
  a.ret();
  // our "data" section
  a.bind(L_lib);
  a.call(L_start);
  // write our dll path as data.
  a.data(dll, strlen(dll)+1);
  a.bind(L_funcname);
  a.call(L_callfunc);
  // write our exported function name as data
  a.data(exported_function, strlen(exported_function)+1);
 }
 // This is entirely to demonstrate how we can treat the 
 // code as data. If we are going to inject into a remote
 // process we will need to relocate it differently.
 // But for local processes it gets the point across!
 size_t code_size = a.getCodeSize();
 MemoryManager *mm = MemoryManager::getGlobal();
 void *p = mm->alloc(code_size, MEMORY_ALLOC_FREEABLE);
 if (p == NULL) {
  printf("Error allocation of our code buffer returned null!");
  return -1;
 }
 void *data = a.make();
 memcpy(p, data, code_size); 
 a.relocCode(p);
 printf("Code size: %d\nNow Calling...", code_size);
 ((void (*)(void)) p)();
 MemoryManager::getGlobal()->free(p);
 // Or screw all that above noise and just cast and call.
 // MyFn fn = function_cast<myfn>(a.make());
 // fn();
 // MemoryManager::getGlobal()->free((void*)fn);

 return 0;
}

Thursday, March 22, 2012

Asmjit Installation

While some what known in the game hacking community. I don't think a lot of people know about asmjit. While it's taken me a bit to wrap my head around how it works (boy did that take a while) I must say it's pretty damn cool. So what it is asmjit? Well it let's you basically dynamically create assembly opcodes via C++. Why would you want to do that? Because in-lining asm is a pain when you want to play with the raw bytes. This way we can dynamically create our PIC and hopefully be able to stuff it into a remote process. Infact, the authors of  asmjit apparently already saw this as a good use and already created a remote injector for us!

So asmjit isn't a very straight forward setup. Here's the steps I had to do to get it all working.
1. Download asmjit from svn:
    svn checkout http://asmjit.googlecode.com/svn/trunk/ asmjit
2. Download cmake from: http://www.cmake.org/cmake/resources/software.html
3. Go to <where you downloaded>\AsmJit\AsmJit-1.0\Util. and run configure-windows-vs2008-x86.bat or which ever arch/Visual Studio version you want. If it doesn't work make sure cmake is in your path (or just modify the bat file to call the full path of cmake.exe
4. Now go to your AsmJit-1.0\Build folder and you should see all the project files. Open up AsmJit.sln or just AsmJit.vcproj and build it.
5. The last step should have produced a Debug directory and the AsmJit.dll and AsmJit.lib files.

Now to use AsmJit in your project do the following:
1. Create a new visual studio project -> win32 -> console -> Console Application  and make sure "Precompiled header" is selected, and finish.
2. Right click on the project properties  and add the "Include Directories", in my case it was in E:\Research\...

3. Now go down to Linker and add the AsmJit.lib
4. Of course Visual Studio needs to know where to find AsmJit.lib, so in VS 2008 you will need to add it to your library path.
5. Now you should be able to build and play with asmjit. (You'll probably need to copy the AsmJit.dll file to your executable's directory before running.)


I've got some working code already for calling MessageBox via assembly but I'll post that tomorrow. Enjoy for now!

Tuesday, March 20, 2012

A Quick Look at Punk Busters Installation.

I don't want to get my gaming machine's hardware or my personal account banned, so I've setup a target game in virtualization software to insulate myself:
Free Windows XP images: Microsoft IE App Compat.
Free Virtualization software with 3d support: VMWare Player (I'm using Workstation however). You'll need to enable 3d acceleration for any DirectX game to start.
Free Kernel debugger: Microsoft's WinDBG.
Free Target game to hack: EA's Battlefield play4free.

I had to convert the IE Compat Virtual PC images to VMWare using VMWare's free image converter tool. The next step was getting the kernel debugger hooked up from my host system to the XP image.
This requires 4 easy steps:
1. Create a named pipe in VMware. From the VM settings -> Add -> Serial Port -> Named Pipe -> \\.\pipe\com_1 or whatever you want to call it.
2. Modify the boot.ini in XP to map a COM port for debugging. The config should look like this.

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - Debug" /fastdetect /debug /debugport=com1 /baudrate=115200

3. Reboot XP, select Microsoft Windows XP Professional - Debug
4. Start windbg with the following command line or make a shortcut like I did: "C:\Program Files (x86)\Debugging Tools for Windows (x86)\windbg.exe" -b -k com:pipe,port=\\.\pipe\com_1,resets=0

If everything went right you should see something like this:
WinDBG connected to our VMWare image and the PnkBstrK.sys module loaded (or rather, unloaded)
If everything *isn't* working you'll probably want to read this link on how to setup vmware for windbg debugging.

While I was installing the Battlefield Play4Free game I loaded up filemon.exe from Sysinternals to see what files got placed on the system. During the "Installing PunkBuster" splash screen I noticed the following files were installed:
- C:\windows\system32\drivers\PnkBstrK.sys - The kernel driver, appears to be partially obfuscated using XOR.
- C:\windows\system32\PnkBstrA.exe - The Punk Buster service A. (I think this just downloads B, will RE to confirm).
- C:\windows\system32\PnkBstrB.exe - The Punk Buster service B.
- C:\windows\system32\PnkBstrB.xtr - The original downloaded form of PnkBstrB.exe (I think this is a guess because file size is the same)
- C:\Program Files\EA Games\Battlefield Play4Free\pbsvc_p4f.exe - The punk buster installer / remover service checking tool
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbcl.db - Looks to be a list of servers, ports and hashes of some sort (for installed files maybe?).
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbcl.log - Client log, shows connection/update query information.
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbag.dll - Single export name of 'a' looks to be doing some sort of obfuscation. Not sure on purpose yet.

C:\Program Files\EA Games\Battlefield Play4Free\pb\pbcl.dll - Not too sure, exports two names 'ca' and 'cb' both of which look to be doing weird jmp calls. By looks of the strings appears to communicate with the punk buster servers. Guessing by the name alone, probably the punk buster client.
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbclgame.cfg - Contains the line: "cl_punkbuster 1"
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbns.dat -  Unknown data format
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbns_c.dat - Same as above, with 16 bytes differing.
C:\Program Files\EA Games\Battlefield Play4Free\pb\pbsvc_p4f.exe - The punk buster installer / remover service checking tool
C:\Program Files\EA Games\Battlefield Play4Free\pb\dll\wa001377.dll - Appears to be related to the html file full of signatures/hashes.
C:\Program Files\EA Games\Battlefield Play4Free\pb\dll\wc002244.dll - Appears to be related to the html file full of signatures/hashes.

C:\Program Files\EA Games\Battlefield Play4Free\pb\htm\wa001377.htm - Appears to be signatures/hashes. Probably for known hacks
C:\Program Files\EA Games\Battlefield Play4Free\pb\htm\wc002244.htm - Same as above.


So that's my target, of course everything I stated above is speculation as to the files purpose. I will be debugging it to learn more details the coming weeks.

Ahh it's good to have a target :>





Sunday, March 18, 2012

Anti-Cheat Systems

There's no point in cheating if you don't at least try to not get caught. However, let me make one thing perfectly clear. I hate cheaters, I think they are terrible little shit heads and they ruin games. Like, I really hate them, that is part of the reason *why* I'm doing this. I want to learn how it all works so I can actually determine if I think someone is cheating or not. Simply saying 'hax!' or 'shut off your aimbot!' is stupid, 90% of the time it's most likely because the other player is just better than you. But for those 10%... wouldn't it be nice to determine what is really possible? Well I certainly do.

There is one very big problem. I'm starting this project *really* late. I have about 10 years or so worth of catching up to do. I'm sure if any real game hackers are reading my posts they're laughing at me because they know my silly little injection methods will probably get busted immediately. Reading through some anti-cheat forums is depressing for multiple reasons; lack of English ability being a primary one (and I don't mean non-native people, holy hell) and another being for how behind I really am. But that is not going to stop me, I realized when I started this was going to be a long ass project.

From my limited research there are basically three major anti-cheating systems: nProtect GameGuardValve Anti-Cheat (VAC/VAC2) and PunkBuster. nProtect appears to be mainly focused on asian MMORPGs like Lineage II and Aion etc. I really don't like asian MMO's, so probably not worth my time. Valve's system is used in a Lot of games, a lot of which I do play like Shogun Total War 2 etc, but not so interesting for me. Finally, we have PunkBuster. This is used by a lot of EA's games. I hate EA. I mean, *really* hate EA. Part of the reason I even took up this project was because they screwed me over on a number of occasions to the point I couldn't play their games. Living in a country outside of the States has it's downsides. If you're keeping tally, I hate cheaters and I hate EA. I think I hate EA more.

So, I think I'll focus on PunkBuster, at least to begin. Free 2 play games are the new thing, and EA has a number of them. Battlefield Heroes, Battlefield free 2 play and so on, and I think these would be an excellent start because, they're free and I don't care if I get banned. One thing I have been reading about is newer versions of PunkBuster do hardware based banning. They have a device driver running in ring 0 and supposedly grab hardware ID's to use as global bans. That's not cool, but I guess I can see the point of it when you introduce free to play games. No point banning if someone can just make a new free account.

I need to create a VM (because I'm sure as shit not going to get my gaming box banned) and download the punkbuster service and start reversing. If you're bored you can read PunkBuster's 'FAQ' to get a general idea of what it does. After reading some cheater forums on these systems I realized most people don't know what the hell they are talking about. Basing anything off these people's information is stupid and dangerous. So yeah, the next few posts will probably be about reversing punk buster and hopefully learning some interesting anti-cheat methods!






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!

Thursday, March 1, 2012

Buh

OK Work has been taking up all my time (including weekends) so I haven't been able to put much time into this. Right now I'm going through QT's source tree to learn somethings and copy their command line handling code :>. It'll be a while before I release anything cool :/.