[C#][Tutorial] How to become an EndScene() hooker menu

User Tag List

Results 1 to 14 of 14
  1. #1
    revertlife's Avatar Private
    Reputation
    11
    Join Date
    Jun 2010
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [C#][Tutorial] How to become an EndScene() hooker

    NOTICE: I am a C# noob and this tutorial is for other C# noobs. I have no doubt that I have broken countless C# coding conventions and good practices and it is best to assume the way I did everything is one of the least efficient possible. Credits go to many people, some of which I will mention towards the end of the tutorial.

    Things you will need:
    • Microsoft Visual Studio 2010 - You can easily write this with any other version of Visual Studio that supports C# and .Net 2.0 and higher but for the sake of this tutorial I will be using VS2010
    • SlimDX - This is the managed wrapper around DirectX which we will be using to handle DirectX as well as find the function address of EndScene. SlimDX can be downloaded here: SlimDX Homepage
    • EasyHook - This is a great library for injecting DLLs and hooking functions in C#. With this you can hook managed as well as unmanaged functions (more about that later). Download here: easyhook-continuing-detours - Project Hosting on Google Code


    A quick explanation of the object model
    I'm not going to explain the object model in detail, I'm just going to explain where the info we want is and what we're going to do with it. Whenever an instance of an object is created in memory, memory is allocated for that object and all of its properties (variables). However, it would be insanely messy and inefficient to allocate memory for every function of that object and copy those functions there. Instead, a VMT is allocated, which points to all to the methods which are already in the memory of the DLL (in the case of Direct3D) and any and all instances of the object will point to the same function.

    This makes it very simple for us once we have injected a DLL: Create a Direct3D object and find EndScene in its VMT. Hook our object's EndScene and we will be hooking the same EndScene that WoW uses. Simple... right?

    The Work Space
    This is where the inefficiency comes in. My workspace, especially the layout of the files is pretty awful, but deal with is.

    First off, you want to create a project and a solution. File->New->Project and call it whatever you want, something along of "host" or "injector" so that you know which is which and select Console application for its type. Then, in the solution browser, right click on the solution and select Add->New Project. Name this one something along the lines of "DLL" or "InjectedDll" or whatever and select "Class Library" for its type.

    Next, go to the Properties of the DLL and under Build change the build path to ../[Host name]/bin/Debug/ or click browse and point it to the bin/debug folder of the first project (the console application). This way, whenever you build solution both the DLL and the injector are built into the same folder and you don't have to do any of the copying from one folder to the other nonsense.

    References
    Now due to the way that interfaces are set up to communicate between the injected DLL and the host, the DLL must reference the executable in order to be able to create an instance of the interface class.

    First, in the host process (the console application), add a reference to EasyHook.dll and copy all of the EasyHook binaries to your /bin/Debug folder (I'll let you figure out which ones on your own, but for now just copy all of them). Also I would copy the SlimDX.dll from the SlimDX binaries folder just to save yourself some trouble. That's it. That's all you gotta do for the host. Now, the using code:

    Code:
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.Remoting;
    using EasyHook;
    System.Diagnostics is needed for finding the PID of WoW and System.Runtime.Remoting is required in order to allow the DLL to communicate with the host process.

    Now do the same with the inject DLL project and add the EasyHook.dll as a reference. Then, add SlimDX (from the .Net tab) and from the Projects tab add a reference to the host project from the DLL.

    Code:
    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using EasyHook;
    using SlimDX;
    using SlimDX.Direct3D9;
    Same thing as before but now you add SlimDX so that you can create a device and use the WoW D3D device. (Windows.Forms is for a MessageBox in EndScene to know whether its working)

    Setting up the communication interface
    Like I said, I am a noob. Seriously, a total noob, so all I know so far is how to do one way communication but for the purposes of this tutorial that's all you need. What happens is you define your communication interface in the host process and then the DLL can call functions from inside the memory space of the host.

    Here's the interface I'll use:
    Code:
        public class WoWInterface : MarshalByRefObject
        {
            public void IsInstalled(Int32 InClientPID)
            {
                return;
            }
    
            public void WriteConsole(String Write)
            {
                Console.WriteLine(Write);
            }
    
        }
    Very simple, no? All you're doing is create a class that displays something on the console. Put this in the main namespace of your project.

    The actual injection!
    Once again, this part is very simple thanks to EasyHook. The first thing you want to do is declare a static string called "ChannelName" which will be the random name of our IPC communication channel. Then, in your main function you'll want to put something like this:

    Code:
                int wowPid;
                Config.Register("WowInjector App", "InjectedDll.dll", "DllInjector.exe");
    
                Process[] procs = Process.GetProcessesByName("WoW");
    
                wowPid = procs[0].Id;
    
                RemoteHooking.IpcCreateServer<WoWInterface>(ref ChannelName, WellKnownObjectMode.SingleCall);
    
                RemoteHooking.Inject(wowPid, InjectionOptions.Default, "InjectedDll.dll", "InjectedDll.dll", ChannelName);
    The first thing you'll want to do is add your executable and dll to the Global Assembly Cache. According to the internet god, "The Global Assembly Cache or GAC is a machine-wide .NET assemblies cache for Microsoft's CLR platform. The approach of having a specially controlled central repository addresses the shared library concept and helps to avoid pitfalls of other solutions that lead to drawbacks like DLL hell." (Wikipedia). Basically, it's supposed to make management of DLLs a bit easier (ala the theory of .NET: Let the coder have as little control as possible). The first argument is a quick note about what it is, doesn't matter what you put here. The rest of the function is a list of all the assemblies you want to add. Essentially, just add your executable and dll (EasyHook and all those are automatically added. Don't worry).

    The next 2 lines create an array of processes with the name "WoW.exe" (not case sensitive) and choses the first one and get its Process ID. Because it's an array you can always make some kind of dialog which asks for the instance to inject into on your own.

    Now on to the more complex line, creating the IPC server. The server basically serves the interface which other functions call. The object in the < > is the one that will be open for the clients to use while the "ref ChannelName" is essentially a pointer to the string where the name of our IPC server will be stored. This is totally irrelevant for this tutorial but "WellKnownObjectMode.SingleCall" means that a new instance of the WoWInterface object will be created for each client while "WellKnownObjectMode.Singleton" would set it so that a single instance is used for all clients.

    The injection line is also very simple. The first argument is the PID of the process we want to inject, the second is the options (Look it up for yourself), the third argument is the DLL to inject in the case of 32 bit while the 4th is the DLL for 64 bit which in our case would be the same for both. If you make your own bot I would recommend differentiating between the 2 DLLs because the SlimDX reference could come in both 32bit and 64bit varieties. And last but not least we the arguments we will pass to the DLL which in our case would be only the ChannelName for the IPC connection.

    The DLL!
    The first thing you want to do with the DLL is to make sure that the namespace for the DLL is the same as the namespace in your host project. Don't ask me why, it's just a quirk with EasyHook that I have run into. Make your life simple and just do it.

    The next step is specifying the entry point of your DLL which EasyHook wants. In this case it is always jsut " : EasyHook.IEntryPoint"

    Code:
        public class Main : EasyHook.IEntryPoint
        {
            WoWInterface Interface;
            LocalHook EndSceneHooker;
    This declares our Main class and sets it as the entry point EasyHook is looking for. THIS IS ABSOLUTELY NECESSARY! Otherwise your DLL will never get injected.

    The variables we declare are an Instance of the IPC interface and the LocalHook object we will use to hook EndScene.


    The Main function
    Code:
            public Main(RemoteHooking.IContext InContext, String InChannelName)
            {
                Interface = RemoteHooking.IpcConnectClient<WoWInterface>(InChannelName);
                Interface.WriteConsole("Dll successfully injected.");
            }
    This functions sole purpose is to create the communications interface and confirm that the DLL is injected.

    Once again, the IPC call has the object we will be using for the interface in < > and the only argument is the ChannelName (which was passed to our DLL by EasyHook). Then we call a function from that interface which we declared earlier called WriteConsole which is just Console.WriteLine.

    Code:
            public void Run(RemoteHooking.IContext InContext, String InChannelName)
            {
                Device dev;
                dev = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1 });
    
                IntPtr addy = dev.ComPointer;
    
                addy = (IntPtr)Marshal.ReadInt32(addy);
    
                addy = (IntPtr)((int)addy + 0xA8);
                addy = (IntPtr)Marshal.ReadInt32(addy);
    
                EndSceneHooker = LocalHook.Create((IntPtr)addy, new DEndScene(EndSceneHook), this);
                EndSceneHooker.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
    
                while (true)
                {
                }
            }
    This is the Run function which is the lifeblood of your DLL (at least until you inject). I BELIEVE (I do not know for sure) that if you return from this function your DLL might be unloaded by EasyHook so that's why every example I've seen had some sort of unending while loop.

    Then we create Direct3D device. This is a copy pasta from SlimDX except I changed the form pointer to IntPtr.Zero and the buffer to 1x1. Then by setting addy to the ComPointer (the real D3D device object) we get the pointer we need to get our VMT.

    We then read the Int32 at that address (and cast it to IntPtr) and this new address is the VMT. Then, since EndScene() is the 42 function we add 0xA8 (A8h = 168 = 42 * 4) to that to get the address of EndScene().

    Sidenote: You can always use Black/White magic or whatever their names are (White rain?) to read the values, just use "addy = (IntPtr) WhiteMagic.Read<Int32>(addy);" since it's basically the same thing.

    THAT IS ALL THIS IS!

    Boom we have the address of EndScene (protip: this is the address of EndScene() in any version of WoW and in almost any game that uses DirectX9).

    These last two lines hook the function to our own.

    Code:
                EndSceneHooker = LocalHook.Create(addy, new DEndScene(EndSceneHook), this);
                EndSceneHooker.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
    The first argument of LocalHook.Create() is the address of the function, the second is an unmanaged pointer (I'll explain it in a bit) and the last is a pointer to the Main object that makes up most of the DLL. (Look at EasyHook examples, I won't explain how all of that works.)

    OK I honestly have no idea what ThreadACL.SetExclusiveACL does or why you need it. That line is a copy pasta from the EasyHook examples so go read about it yourself. From what I can tell, I don't need to worry about it.

    The last code is here:
    Code:
            [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Unicode,
            SetLastError = true)]
            delegate int DEndScene(
                IntPtr Direct3dDevice);
    
            public int EndSceneHook(IntPtr Direct3dDevice)
            {
                using (Device d3d = Device.FromPointer(Direct3dDevice))
                {
                    MessageBox.Show("LOL");
                    return d3d.EndScene().Code;
                }
            }
    The Unmanaged pointer declaration just makes it possible for us to pass the EndSceneHook function to the LocalHook.Create. In the function itself, we do using directive to set our device object (d3d) to the one passed to the function. Thus, our d3d object is actually the Direct3D object that WoW uses. Thus we can manipulate the graphics and do whatever the **** we want.

    The return line just calls the original EndScene and returns the error code (or success code or w.e)


    And... that's it. This code will continuously spam that MessageBox and WoW will never render because of the MessageBoxes blocking the thread.

    Sorry for my crappy explanations but now that you have the code in front of you it should be pretty easy to figure it out and this tutorial is more for WoW hacking noobs, not for people who don't even know the most basic features or syntax of the language. (I left out Strong name signing for a reason). I also made this pretty fragmented so that you had to know at least something to be able to use this tutorial and not be able to just copy paste.

    Also, I have no idea how to release the Device created in that code but since its a managed DLL its already heavy on the memory.

    If I missed something, message me or something and I will correct it. I made sure to create a project from scratch and copy pasted all this code and it worked perfectly (though since this is on a computer it might not work as exactly on yours. If it doesn't, please provide more information than just "it doesn't work"). Tested on a 64bit Windows 7.

    Big note: Any time you get an exception that says something along the lines of your binaries not being in the GAC it is probably because you are not running the executable with administrator privileges. Save yourself the trouble and just run Visual Studio as Administrator

    Now, WTB TUTORIAL ON HOW TO CALL WOW FUNCTIONS AND GET RETURN VALUES!

    Credits go to:
    http://www.rohitab.com/discuss/index...howtopic=34411
    http://spazzarama.wordpress.com/2010...t3d-api-hooks/
    and the EasyHook and SlimDX examples. COPY PASTE FTW!
    Last edited by revertlife; 07-07-2010 at 06:21 PM.

    [C#][Tutorial] How to become an EndScene() hooker
  2. #2
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So you're now in process.... but not quite in process?

  3. #3
    revertlife's Avatar Private
    Reputation
    11
    Join Date
    Jun 2010
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Apoc View Post
    So you're now in process.... but not quite in process?
    What do you mean by not quite in process?

  4. #4
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're injecting a DLL (EasyHook) to hook EndScene. Why bother? Just inject your own library, and take full usage of the power of injection.

    Instead, you're causing a bunch of overhead from opening an IPC channel, among other things. Plus, you're subject to bugs in EasyHook.

  5. #5
    revertlife's Avatar Private
    Reputation
    11
    Join Date
    Jun 2010
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Apoc View Post
    You're injecting a DLL (EasyHook) to hook EndScene. Why bother? Just inject your own library, and take full usage of the power of injection.

    Instead, you're causing a bunch of overhead from opening an IPC channel, among other things. Plus, you're subject to bugs in EasyHook.
    If I was going to make my own injecting code and if I was afraid of the overhead I wouldn't be using C# anyway. Using EasyHook and SlimDX just makes it much simpler while I am still learning how to mem edit in WoW and I don't have to worry about nonsense memory offsets (which in the case of D3D was giving me a major headache before I switched to this method). And yes I am actually planning to draw on the window so I would have used SlimDX anyway.

    The IPC channel is wholly unnecessary. The whole app would function just as usual with all of that taken out. As for bugs in EasyHook, it's in version 2.5b with a long development history, I'd be more likely to make my own set of bugs than EasyHook already has while hooking EndScene().

  6. #6
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by revertlife View Post
    If I was going to make my own injecting code and if I was afraid of the overhead I wouldn't be using C# anyway. Using EasyHook and SlimDX just makes it much simpler while I am still learning how to mem edit in WoW and I don't have to worry about nonsense memory offsets (which in the case of D3D was giving me a major headache before I switched to this method). And yes I am actually planning to draw on the window so I would have used SlimDX anyway.

    The IPC channel is wholly unnecessary. The whole app would function just as usual with all of that taken out. As for bugs in EasyHook, it's in version 2.5b with a long development history, I'd be more likely to make my own set of bugs than EasyHook already has while hooking EndScene().
    Any reason to not use C#?

    There are already multiple accounts of people successfully using C# while injected. (It's actually nearly on par with C++ in some aspects.)

  7. #7
    revertlife's Avatar Private
    Reputation
    11
    Join Date
    Jun 2010
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Apoc View Post


    Any reason to not use C#?

    There are already multiple accounts of people successfully using C# while injected. (It's actually nearly on par with C++ in some aspects.)

    I don't know enough about C/C++ vs C# to answer that but if you want to have that debate I'm certain there are many programmers on either side.

    I use C# because it simplifies things a lot and I'm not inclined to care about a few kilobytes (or hundreds of kilobytes for that matter) of extra memory in this day and age. Looking at the EasyHook source, most of it is written in C++ with only a small managed wrapper (at least for the LocalHook inside the DLL). The RemoteHook (injecting the DLL) seems to be more complex because it adds in a service (for who knows what reason) but once again, not that big of a deal since I can just close the Host once the DLL is injected.

    SlimDX itself is also a relatively small wrapper and given that I AM trying to draw on the WoW screen it is a small sacrifice for complete access to the Direct3D device.

  8. #8
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by revertlife View Post
    I don't know enough about C/C++ vs C# to answer that but if you want to have that debate I'm certain there are many programmers on either side.

    I use C# because it simplifies things a lot and I'm not inclined to care about a few kilobytes (or hundreds of kilobytes for that matter) of extra memory in this day and age. Looking at the EasyHook source, most of it is written in C++ with only a small managed wrapper (at least for the LocalHook inside the DLL). The RemoteHook (injecting the DLL) seems to be more complex because it adds in a service (for who knows what reason) but once again, not that big of a deal since I can just close the Host once the DLL is injected.

    SlimDX itself is also a relatively small wrapper and given that I AM trying to draw on the WoW screen it is a small sacrifice for complete access to the Direct3D device.
    It adds a service because EasyHook supports 'global' process hooks. (They do it the smart way; via a service. Why it's not optional, I don't know. But whatever)

    We've had the C# vs C/C++ debate on these forums quite a few times. While there's really very little that's impossible with C# that you can do with C++, everyone agrees C# is much nicer for general usage, especially if you do what most of us do. (Write bots.)

    SlimDX is far from a 'small wrapper'. It has support for 4 (5 now?) different versions of DirectX, full DirectInput/Draw/etc etc, and the list goes on. It's a very large wrapper. However, in comparison to frameworks like MDX and XNA, it's small.

    Lastly; complete access to the DX device can only be achieved by using C/C++ (or delphi, etc) type languages. The managed wrappers have missing bits of the DirectX framework, and even some missing parts of the Direct3D device itself. The missing stuff is trivial, but still missing.

  9. #9
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Apoc View Post
    You're injecting a DLL (EasyHook) to hook EndScene. Why bother? Just inject your own library, and take full usage of the power of injection.

    Instead, you're causing a bunch of overhead from opening an IPC channel, among other things. Plus, you're subject to bugs in EasyHook.
    +1 (Filler)

  10. #10
    XTZGZoReX's Avatar Active Member
    Reputation
    32
    Join Date
    Apr 2008
    Posts
    173
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A few things:

    Code:
                Device dev;
                dev = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1 });
    You're forgetting to dev.Dispose(); it.

    Code:
            public int EndSceneHook(IntPtr Direct3dDevice)
            {
                using (Device d3d = Device.FromPointer(Direct3dDevice))
                {
                    MessageBox.Show("LOL");
                    return d3d.EndScene().Code;
                }
            }
    It would be a very wise idea to cache this Device object to avoid GC thrashing. Also, I would watch out with that 'using' statement; I don't know what SlimDX does under the hood, but running a Dispose() on WoW's device probably isn't a good idea.

    Apoc also has a valid point; using EasyHook is not really necessary for a scenario like this. You can just make your own tiny injector and be done with it, since you probably don't need 95% of EasyHook's functionality.

    Other than that, your code generally seems okay to me.
    Last edited by XTZGZoReX; 07-08-2010 at 05:27 AM.

  11. #11
    Seifer's Avatar Site Donator
    Reputation
    129
    Join Date
    Apr 2007
    Posts
    270
    Thanks G/R
    1/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Good tutorial.

  12. #12
    ctao's Avatar Member
    Reputation
    6
    Join Date
    Apr 2009
    Posts
    1
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am not sure if easyhook hosts the clr in the target process or not. But even if it does it's still pretty easy to setup. I know it's injection method just calls a function from the injected Dll so that would be easy to replicate. If you want to look up more on hosting the clr check out CLRCreateInstance for .net 4.

    But nice tutorial. You could look into finding another way to get the device that doesn't involve calculating it with static offsets. It could be problem.. theoretically.

  13. #13
    Seifer's Avatar Site Donator
    Reputation
    129
    Join Date
    Apr 2007
    Posts
    270
    Thanks G/R
    1/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by ctao View Post
    I am not sure if easyhook hosts the clr in the target process or not. But even if it does it's still pretty easy to setup. I know it's injection method just calls a function from the injected Dll so that would be easy to replicate. If you want to look up more on hosting the clr check out CLRCreateInstance for .net 4.

    But nice tutorial. You could look into finding another way to get the device that doesn't involve calculating it with static offsets. It could be problem.. theoretically.
    EasyHook is written in C# if I recall correctly, so it's safe to assume it does.

  14. #14
    Millow's Avatar Member
    Reputation
    5
    Join Date
    Mar 2007
    Posts
    49
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I'm willing to risk a flame and ask a question ! I've spent so many hours (serious) trying to get this code working, but I just can't resolve my problem. I've looked at the Easyhook's wiki, but still, I'm doing something wrong and I dont't know what it is.
    Code:
    
    RemoteHooking.Inject(wowPid, InjectionOptions.Default, "InjectDLL.dll", "InjectDLL.dll", ChannelName);
    
    This line is my problem, I always get a nullReferenceException "object not set to an instance of the object".
    But, I don't see why, wowPid is an in, the 2nd parameter can be taken out and I still get the error, the 3rd and 4th are just strings. I even tried to puth the path to the DLLs there to no avail.
    It leaves ChannelName, it has to be the problem I guess.
    Code:
    
    staticString ChannelName = newString('c',6);
    staticString ChannelName = null;
    staticString ChannelName = "areyougonnacompiledamn";
    static string ChannelName = null;
    static string ChannelName = "comeonwork"
    I tried defining the ChannelName in a few different ways, to no avail once again, I don't know what to try next. Usually I just try to figure it out by myself with help from the threads in the forum, but this one stomps me, and it must be simple...but still...
    I followed the instructions step by step, my namespaces are the same, my references are set properly, easyhook and slim's dll are in the debug folder, I build the dll and the exe in the same folder, my exe and my dll are strong named.

    If anyone has any advice, I'm all ears.
    Thx to whoever helps
    Good thing is I've learned a few things through this, now I want the cherry on top, seeing it compile finally !
    "What can be asserted without proof can be dismissed without proof." --- Christopher Hitchens

Similar Threads

  1. How to become invisible in sunken temple!
    By artkiller in forum World of Warcraft Exploration
    Replies: 1
    Last Post: 10-26-2007, 02:12 PM
  2. How to become Invisible to EVERYONE (including GMs)
    By Gooday in forum World of Warcraft Emulator Servers
    Replies: 10
    Last Post: 10-10-2007, 09:08 PM
  3. [GUIDE] How to: Become a GM
    By jimmy2222 in forum World of Warcraft Emulator Servers
    Replies: 7
    Last Post: 10-06-2007, 10:52 AM
  4. My first scam - how i become famous
    By Maku in forum WoW Scam Prevention
    Replies: 5
    Last Post: 09-10-2007, 01:48 PM
  5. Tutorial: How to be Sarcastic
    By Alkhara Majere in forum Community Chat
    Replies: 14
    Last Post: 05-21-2007, 03:40 PM
All times are GMT -5. The time now is 11:38 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search