MMOwned - World of Warcraft Exploits, Hacks, Bots and Guides - Powered by vBulletin


Donate to remove ads, get special forum and shoutbawx access
+ Reply to Thread
Results 1 to 15 of 15
  1. #1

    Contributor

    Join Date: May 2008
    Posts: 388
    Rep: 90
    Cash: 605

    Proof of Concept: dwFindPattern TLS [C#]

    Donate to remove ads, get special forum and shoutbawx access
    Truth be told, ever since WoW!Sharp, I haven't hacked/disassembled/whatever WoW in any way, shape, or form (except for writing a teleporter for an EMU server, big whoop). I've never worked with TLS--nor am I even really sure what it stands for, to be honest--before today, but I've kinda decided that I want to try to catch up with the whole scene.

    I've read almost every thread I could get my hands on over the past 24-48 hours, and have compiled and run many, many different PoCs or examples. From what I can tell, the first step in making a bot--or anything, really--is to find the s_curMgr, which allows you to loop through loaded objects (including your character?). I've seen people left in the dust when their "TLS Pointer" is outdated due to client updates, so I set out to solve that problem--or, at the very least, make it easier to solve. Enter: dom1n1k's dwFindPattern (external C# version).

    (Source with highlighting HERE.)
    Code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using MemoryLib;
    
    namespace ExternalFindPattern
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			DateTime now = DateTime.Now; //used for testing how long it takes to find the tls pointer
    			System.Diagnostics.Process.EnterDebugMode(); //gives our program debug permissions
    
    			//open wow for read/write
    			IntPtr hProcess = Memory.OpenProcess(Memory.GetProcessIdByProcessName("wow.exe"));
    			//if open process was successful
    			if (hProcess != IntPtr.Zero)
    			{
    				//search for the code pattern that we want (in this case, WoW TLS)
    				uint tlscode = dwFindPattern(hProcess, 0x410000, 0x400000,
    					"EB 02 33 00 64 8B 15 2C 00 00 00 8B 0D 00 00 00 00 8B 0C 8A",
    					"xxx?xxxxxxxxx????xxx");
    
    				//read Kynox's g_clientConnection from memory
    				uint g_clientConnection = Memory.ReadUInt(hProcess, Memory.ReadUInt(hProcess, (tlscode + 0x16)));
    				//first, the offset for the curMgr inside g_clientConnection is read,
    				//then s_curMgr is read from g_clientConnection + that offset (which may change version to version,
    				//I honestly don't know)
    				uint s_curMgr = Memory.ReadUInt(hProcess, (g_clientConnection + Memory.ReadInt(hProcess, tlscode + 0x22)));
    
    				//output to console
    				Console.WriteLine("TLS code: 0x{0:X08}ng_clientConnection: 0x{1:X08}ns_curMgr: 0x{2:X08}", tlscode, g_clientConnection, s_curMgr);
    
    				Memory.CloseHandle(hProcess);
    			}
    
    			//tell user how long it took to find and get what we wanted
    			TimeSpan timer = DateTime.Now.Subtract(now);
    			Console.WriteLine("nnTime taken: {0}msnnPlease press [ENTER] to continue...", timer.Milliseconds);
    			Console.ReadLine();
    		}
    
    		#region dwFindPattern
    		//blatantly adapted/copied from dom1n1k :)
    		static bool bDataCompare(byte[] data, int index, byte[] pattern, string mask)
    		{
    			if (pattern.Length != mask.Length) return false;
    
    			for (int i = 0; i < pattern.Length; i++)
    				if (mask[i] == 'x' && (data[index + i] != pattern[i]))
    					return false;
    
    			return true;
    		}
    
    		//blatantly adapted/copied from dom1n1k :)
    		static uint dwFindPattern(IntPtr hProcess, uint start, int length, string _pattern, string mask, char delimiter)
    		{
    			string[] p = _pattern.Split(delimiter);
    			byte[] pattern = new byte[p.Length];
    			for (int i = 0; i < p.Length; i++)
    				pattern[i] = Convert.ToByte(p[i], 16);
    
    			const int bytestoread = 1024;
    
    			int index = 0;
    			byte[] buf;
    
    			if (bytestoread > length)
    			{
    				buf = new byte[length];
    				Memory.ReadMemory(hProcess, start, ref buf);
    				for (int i = 0; i < (buf.Length - pattern.Length); i++)
    					if (bDataCompare(buf, i, pattern, mask))
    						return (uint)(start + i);
    			}
    			else
    			{
    				while (index < length)
    				{
    					buf = new byte[bytestoread + pattern.Length];
    					Memory.ReadMemory(hProcess, start + index, ref buf);
    					for (int i = 0; i < bytestoread; i++)
    						if (bDataCompare(buf, i, pattern, mask))
    							return (uint)(start + index + i);
    
    					index += bytestoread;
    				}
    			}
    
    			return uint.MaxValue;
    		}
    
    		static uint dwFindPattern(IntPtr hProcess, uint start, int length, string _pattern, string mask)
    		{
    			return dwFindPattern(hProcess, start, length, _pattern, mask, ' ');
    		}
    		#endregion
    	}
    }
    Now then, this serves two purposes:
    • Gives a program the ability to look for patterns (useful for making your program either update itself or completely ignore client version) without injecting anything into the client.
    • Finds Kynox's g_clientConnection and, subsequently, the s_curMgr externally, allowing the program to loop through loaded objects, regardless (hopefully?) of client version.

    In order to use this in the leechtastic, copy+paste way, you'll need my MemoryLib class library, located here. Source is included, though it's a bit rough around the edges and nowhere near finished (I've worked on it for a few hours here or there for nearly a year).



    Kynox, Bobbysing, UnknOwned: you guys have been doing this longer than I have, so, please, point out what I'm doing wrong, what I could be doing better, and/or any suggestions you might have, up to and including what should be my next step, in your opinion, towards a bot. I've got a few ideas of my own, but I'm really in over my head with information, at the moment. If you wouldn't mind helping me learn what it is I need to learn, I'd love the opportunity to pick your brain(s) about certain things. Let me know.



    Anyway, there's my first contribution with (hopefully) more to come as I learn and feel more comfortable. See the second post in this thread for a better explanation of what's going on in my code.




    CREDITS:
    dom1n1k
    Kynox
    bobbysing
    Anyone else that I forgot: I'm sorry. I've read a lot of threads and gleaned a lot of information from many different sources. Please, let me know if I've forgotten anyone.
    Last edited by Shynd; 05-31-2008 at 01:02 PM. Reason: added credits

  2. #2

    Contributor

    Join Date: May 2008
    Posts: 388
    Rep: 90
    Cash: 605

    Further explanation...

    Okay, on line 21:
    Code:
    uint tlscode = dwFindPattern(hProcess, 0x410000, 0x400000,
    	"EB 02 33 00 64 8B 15 2C 00 00 00 8B 0D 00 00 00 00 8B 0C 8A",
    	"xxx?xxxxxxxxx????xxx");
    This searches for what I've determined to be the easiest portion of WoW game code from which to glean the largest amount of information. In 2.4.2, it looks a bit like this:
    Code:
    00778D1B  |. 6A 00              PUSH 0                                   ; /Arg1 = 00000000
    00778D1D  |. 8BC8               MOV ECX,EAX                              ; |
    00778D1F  |. E8 ECE8FFFF        CALL <Wow.CGCurMgr_C>                    ; Wow.00777610
    00778D24  |. EB 02              JMP SHORT Wow.00778D28
    00778D26     33C0               XOR EAX,EAX
    00778D28     64:8B15 2C000000   MOV EDX,DWORD PTR FS:[2C]
    00778D2F  |. 8B0D 84AAE800      MOV ECX,DWORD PTR DS:[E8AA84]
    00778D35  |. 8B0C8A             MOV ECX,DWORD PTR DS:[EDX+ECX*4]
    00778D38  |. 8B15 B095D400      MOV EDX,DWORD PTR DS:[D495B0]
    00778D3E  |. 8981 10000000      MOV DWORD PTR DS:[ECX+10],EAX
    00778D44  |. 8982 18220000      MOV DWORD PTR DS:[EDX+2218],EAX
    00778D4A  |. A1 B095D400        MOV EAX,DWORD PTR DS:[D495B0]
    Line 21 should find the pattern that starts at 0x00778D24, or JMP SHORT Wow.00778D28. That is where we will start gathering information.

    Line 26 has two memory reads on it. In simplistic terms, it looks more or less like so: [[0x00778D24 + 0x16]] = g_clientConnection. It reads from tlscode+0x16 (0x00778D3A), which contains 0x00D495B0, and then reads from 0xD495B0 to get the address of g_clientConnection. My hope is that the pointer to g_clientConnection will always be 0x16 bytes from where my pattern is found and, therefore, will update itself with each new client.

    Line 30 has two more memory reads on it. [g_clientConnection + [tlscode+0x22]] = s_curMgr. Basically, I'm not taking chances that the offset from g_clientConnection to the s_curMgr pointer will always stay the same, so I read the offset from memory at tlscode+0x22 (0x00778D46). Hopefully this will solve some client update issues, as well, though it's less likely. Never hurts to be safe, though.

    Seriously, I have no idea if any of this helps in any way, as I've never had things break during a client update (seeing as I'm starting from scratch with today as my first day). All I'm trying to do is fix problems I've had happen to me in other games when clients update and hope that WoW will act the same way. I'm sure someone will correct me if I'm wrong--in fact, I'm hoping for it .


    Afterthought: an image says a thousand words?

  3. #3

    Warden's Mediator

    Join Date: Dec 2006
    Location: Raping your Stack
    Posts: 891
    Rep: 822
    Cash: 610
    Nice work dude!

  4. #4

    Contributor

    Join Date: May 2008
    Posts: 388
    Rep: 90
    Cash: 605
    Nothing you would change?

  5. #5

    Master Sergeant
    Join Date: May 2008
    Posts: 96
    Rep: 7
    Cash: 600
    another location is here:


    0077624E CC INT3
    0077624F CC INT3
    00776250 55 PUSH EBP
    00776251 8BEC MOV EBP,ESP
    00776253 A1 84AAE800 MOV EAX,DWORD PTR DS:[E8AA84]
    00776258 64:8B0D 2C000000 MOV ECX,DWORD PTR FS:[2C]
    0077625F 53 PUSH EBX
    00776260 56 PUSH ESI
    00776261 8B3481 MOV ESI,DWORD PTR DS:[ECX+EAX*4]
    00776264 8B86 10000000 MOV EAX,DWORD PTR DS:[ESI+10]
    0077626A 05 A8000000 ADD EAX,0A8
    0077626F 8B40 04 MOV EAX,DWORD PTR DS:[EAX+4]
    00776272 A8 01 TEST AL,1
    00776274 57 PUSH EDI


    with the:

    00776253 A1 84AAE800 MOV EAX,DWORD PTR DS:[E8AA84]
    00776258 64:8B0D 2C000000 MOV ECX,DWORD PTR FS:[2C]

    being the most important location.

    theres a lot of stable (non-changing) code around that spot as well.

    best,
    Cal

  6. #6

    Contributor

    Join Date: May 2008
    Posts: 388
    Rep: 90
    Cash: 605
    Here's a post I made on a website for a different game that may explain dwFindPattern usage better, for those of you who aren't already acquainted with it: dwFindPattern Proof of Concept [C#] - Dark Ages Underground. You shouldn't have to register to view it.

  7. #7

    New User

    Join Date: Mar 2009
    Posts: 14
    Rep: -3
    Cash: 600
    Please, can someone compile this code to .exe?
    I downloaded many proggrams, but can't launch code..
    I'm trying to find pointers to ObjectManager in 1.12.1 patch, for a week, but can't figure this out...please any help..
    Last edited by DEMON_PK; 05-27-2010 at 08:36 AM.

  8. #8

    Master Sergeant

    Join Date: Apr 2008
    Location: Denmark
    Posts: 116
    Rep: 22
    Cash: 600
    Please, can someone compile this code to .exe?
    I downloaded many proggrams, but can't launch code..
    I'm trying to find pointers to ObjectManager in 1.12.1 patch, for a week, but can't figure this out...please any help..
    notepad.exe -> new file -> paste code -> save as Program.exe -> run it

  9. #9

    New User

    Join Date: Mar 2009
    Posts: 14
    Rep: -3
    Cash: 600
    Quote Originally Posted by XTZGZoReX View Post
    notepad.exe -> new file -> paste code -> save as Program.exe -> run it
    Thank you, but this don't work..

  10. #10

    MMOwned WebDev


    Join Date: Jan 2008
    Posts: 2,555
    Rep: 1167
    Cash: 350
    I lol'd .

  11. #11

    Contributor

    Join Date: Jan 2008
    Location: Sweden
    Posts: 718
    Rep: 173
    Cash: 580
    Quote Originally Posted by DEMON_PK View Post
    Thank you, but this don't work..
    He forgot the vital part, you must append
    Code:
    #Compile -r -i -f -k
    to the program.

    Good luck.
    Welcome to this section, please read the rules *cough*
    Dahnniel [DOT] s [AT] gmail [DOT] com

  12. #12

    Corporal
    Join Date: Nov 2008
    Posts: 17
    Rep: 5
    Cash: 600
    Quote Originally Posted by DEMON_PK View Post
    Thank you, but this don't work..
    You have to convert the code first. To do so you have to reverse the complete text.

    For example:
    Code:
    return dwFindPattern(hProcess, start, length, _pattern, mask, ' ');
    ist going to be
    Code:
    ;)' ' ,ksam ,nrettap_ ,htgnel ,trats ,ssecorPh(nrettaPdniFwd nruter
    This is due the fact that the stack is growing downward.

    Have fun!

  13. #13

    Knight-Lieutenant

    Join Date: Jan 2008
    Location: South Pole
    Posts: 381
    Rep: 60
    Cash: 600
    bumping in a necro thread?
    I hacked 127.0.0.1

  14. #14

    Site Donator

    Join Date: Jan 2008
    Posts: 370
    Rep: 34
    Cash: 240
    Quote Originally Posted by fish2k View Post
    You have to convert the code first. To do so you have to reverse the complete text.

    For example:
    Code:
    return dwFindPattern(hProcess, start, length, _pattern, mask, ' ');
    ist going to be
    Code:
    ;)' ' ,ksam ,nrettap_ ,htgnel ,trats ,ssecorPh(nrettaPdniFwd nruter
    This is due the fact that the stack is growing downward.

    Have fun!
    you fool thats how they do it on linux!

    On windows they use linked lists that means you need to put the -> sign between all words
    Code:
    ->return-> ->dwFindPattern(->hProcess,-> start,-> length,-> _pattern,-> mask, '  ');->

  15. #15

    New User

    Join Date: Mar 2009
    Posts: 14
    Rep: -3
    Cash: 600
    sorry, but i need this 2 old offsets, and i will find it))
    Founded them using CE and hand made memory scanner...

    Thanks
    Last edited by DEMON_PK; 06-10-2010 at 01:56 AM.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
Go to the top of the page

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56