As part of my bot project I've been working on an infrastructure for running a headless Wow client on linux, controlled completely by an out of process bot. Here's some notes about my implementation for anyone else interested in botting on linux. Nothing really innovative here, just some basic info. Seems like this is an under-appreciated topic around here for some reason.
For those of you who aren't familiar with it, there is a project called WINE [www.winehq.org] which stands for Wine Is Not an Emulator. It is an open source implementation of the windows API, so in effect a windows application runs under wine and wine then translates it's Windows API calls into whatever the underlying OS provides. Typically the underlying OS is linux or OS X. WINE works great for WoW, since WoW uses such a minimal set of Windows APIs, particularly when it is running with the OpenGL GFX API which is almost exactly the same on linux.
There are two fantastic aspects of this for botting:
1) Running WoW in wine on linux is an allowed activity being done by many 100% legitimate players, yet it almost completely neuters the effectiveness of warden to detect an mischievous environment, since...
2) The source code for wine is freely available and there are thousands of variants on it out there, so you can modify it to your hearts content and nobody is going to have any clue whatsoever so long as you don't distribute binaries that could be detected by hashing. Why hook system calls and inject DLLs when you can just compile your own versions of the OS DLLs to include whatever you want, I always say.
So grab the wine source, and hack away. Here's some things I've done for starters:
1) Modified winex11 driver so that WoW runs completely headless. It's graphics output is sent to an off screen GLX context, its keyboard/mouse input is coming from another process via a network socket. This is completely transparent to Wow, since it's all happening inside the Win API calls themselves, not via extra modules interposed or injected.
The off screen GLX context is shareable, so my out of process bot can hook up to it and see what the client sees if desired. When nobody is looking, the GL calls can be stubbed out inside wine. E.g., ignore glDrawElements, glCallLists, etc, to improve performance. I'm ultimately hoping to get this to a point where the WoW clients will run without any GPU in the first place, since the OGL calls will be so minimal that doing them in software is OK.
2) All of the network traffic to/from WoW is captured and sent off when it makes winsock calls. Again, we just add code to the send/receive functions to squirrel away the data. No extra function calls appear in the stack, no additional modules are loaded either in Windows or in linux.
3) WoW memory can be read whenever it makes a system API call, since we own the source to all the system calls. We can also call WoW engine functions from inside system calls and hide them from stack inspection, but I wouldn't do that since it could still be detected within the client by other means if warden guy were so inclined.
4) KSM [kernel samepage merging] enabled in linux kernel allows multiple copies of Wow to run and share any identical memory pages, which can reduce the memory usage significantly. You can also run each client in Wow directories that are all symlinked to a single copy of the Data directory, so that the linux kernel will use the same read cached data for all the clients, reducing disk seek thrashing, which is otherwise the biggest problem for multi-boxing.
WoW should have no idea that there are multiple WoW clients on the box, since each can be run in it's own Wine environment with it's own process space, etc. I presume that any bot process you run will also be invisible to WoW, since your bot will be a native linux process and WoW is only going to see other windows processes within it's wine environment, of which there will be zero. I haven't checked if wine has any calls to let a Windows application inspect the unix process space, but I doubt it. If so, just modify the necessary calls, after all we have the source...
All of this can be done with only a couple thousand lines worth of mods to wine. It's actually way easier than botting on windows, in my opinion, since you don't have to do anything weird to avoid detection, you just write your code inside calls that wow expects to exist and everything just works.
Here's some source pointers, all relative to the base of the wine source tree.
dlls/winex11.drv contains the source for the X11 driver. This is what converts the screen/keyboard/mouse APIs in windows into screen/keyboard/mouse calls in X11. You can modify where the rendering goes by modifying the context generation in opengl.c. Mouse/keyboard events are in mouse.c and keyboard.c, respectively. I run a daemon inside this module that talks to my bot over a socket. How you do this depends on whether or not you want to retain the ability to control the client via X in the normal way. I don't, so I simply removed 90% of this code and added really simple calls to just inject my inputs.
dlls/opengl32/opengl_norm.c contain the wrappers to convert WGL calls into GL calls, so if you want to modify WoW's openGL calls, this is where you'd do so. It's really simple, most functions are 3-4 lines long. Note that this is just the pure OpenGL stuff. If you want to control the GLX stuff, that's in winex11. Make sure your wow client is configured to use the openGL api in the Config.wtf file. D3D on wine is a lot less stable.
Code:
void WINAPI wine_glClear( GLbitfield mask ) {
TRACE("(%d)\n", mask );
< do nefarious stuff here>
ENTER_GL();
glClear( mask );
LEAVE_GL();
}
The winsock2 code that Wow uses to communicate with the server is in dlls/ws2_32/socket.c. This converts the wow communication into BSD socket stuff. Have a look at the recv and send functions.
X11 window handling is all in dlls/winex11/window.c, so if you don't want a window or want to be able to minimize the X11 window without WoW thinking the window is minimized, look at all the functions starting with X11DRV_. E.g, X11DRV_CreateWindow, X11DRV_ShowWindow.