[4.0.0 12025] Opcode ID changed ?

On domingo, 15 de agosto de 2010 0 comentarios

Hey, i have patched my cataclysm alpha to the next build (12025) and i have try to adapt emulator for this. Ok, so i have decompile with IDA in pseudo-code wow.exe ...etc.

When i try to find the new offset for ReadUint32, HandleOpcode i have find that :


//----- (004BC690) --------------------------------------------------------
void __cdecl sub_4BC690()
{
void *v0; // eax@2


if ( !dword_C1C980 )
{
v0 = sub_7A6F40(57752, (int)".\\FriendList.cpp", 1207, 0);
if ( v0 )
dword_C1C980 = sub_4B68E0(v0);
else
dword_C1C980 = 0;
sub_4B3B80(0x2FEDu, (int)sub_4BC370, 0);
sub_4B3B80(0x3B68u, (int)sub_4B69D0, 0);
sub_4B3B80(0xCBEBu, (int)sub_4B6A10, 0);
sub_4B3B80(0xBFECu, (int)sub_4BC350, 0);
sub_4B3B80(0x7FECu, (int)sub_4BC300, 0);
sub_5F9E60((int)"whois", (int)sub_4B78F0, 0, (int)"Ask the server to do an account/real name lookup on a character name");


Ok, so sub_4B3B80 is a function for handle recv opcode from the server, so the first argument of the function is opcode id !

Here you can view the same function for build 11927 :

//----- (00FriendList__Initialize) --------------------------------------------------------
void __cdecl sub_FriendList__Initialize()
{
void *v0; // eax@2


if ( !dword_B8E3E0 )
{
v0 = sub_SMemAlloc(57752, (signed int)".\\FriendList.cpp", 1207, 0);
if ( v0 )
dword_B8E3E0 = sub_FriendList__FriendList(v0);
else
dword_B8E3E0 = 0;
sub_ClientServices_SetMessageHandler(99, (int)sub_Packet_Packet_SMSG_WHO, 0);
sub_ClientServices_SetMessageHandler(101, (int)sub_Packet_Packet_SMSG_WHOIS, 0);
sub_ClientServices_SetMessageHandler(510, (int)sub_Packet_Packet_SMSG_RWHOIS, 0);
sub_ClientServices_SetMessageHandler(103, (int)sub_Packet_Packet_SMSG_CONTACT_LIST, 0);
sub_ClientServices_SetMessageHandler(104, (int)sub_Packet_Packet_SMSG_FRIEND_STATUS, 0);
sub_ConsoleCommandRegister("whois", (int)sub_4B1890, 0, (int)"Ask the server to do an account/real name lookup on a character name");
Read more ...»

World Of Warcraft Memory Offsets

On 0 comentarios

Reading offsets


playerbase = 0x00B366D0 + 0x34 + 0x24 // Reads players level
playerbase + 0x798 // Read players xlocation
playerbase + 0x79C // Read players ylocation
playerbase + 0x7A0 // Read players zlocation
playerbase + 0x7A8 // Read players rotation
playerbase + 0x19D8 // Read players MAXhp
playerbase + 0x19B8 // Read players current hp
playerbase + 0x8+ (0x36 * 4) // Reads players level
0xC4EB14, 30 // Read current zone text, 30 is lenght
0xBB4428, 12 //reads player name, 12 is lenght
0x0BF3F10 + (i * 0x17C0)) + 0xbf4, 255)

//0x0000 - Sender GUID
//0x0008 - Unknown
//0x003c - formatted message, 3000 bytes
//0x0bf4 - pure text, also 3000 bytes
//0x17ac - messageType
//0x17b0 - channelNumber
//0x17b4 - sequence
//0x17b8 - time

Write offsets:

0xB9251C + 0x80 // writes a X coord where we are moving
0xB9251C + 0x84 // writes a Y coord where we are moving
0xB9251C + 0x88 // writes a Z coord where we are moving
0xB9251C + 0x10// makes moving action

Read more ...»

[Tutorial] How to find simple stuff

On 0 comentarios

Hello,

I'm here for some time now and I have decided to start learning things instead of asking for offsets or stuff.

Today I have decided to take the time to make a short tutorial with my level of knowledge speaking about how to find something with IDA.

For those who knows IDA this thread will talk about the String window and how to read subs.

Most of you already know the things I'm going to explain but this thread is mostly for all of the users that are/was like me, searching for things here and not doing by there own.

So here we go, what you need is :

- Ida Pro (http://www.hex-rays.com/idapro/ IDA Pro Disassembler - multi-processor, windows hosted disassembler and debugger)
- Hex-Rays (http://www.hex-rays.com/decompiler.shtml Hex-Rays Decompiler) <- facultative
- wow.exe .. 3.2.2 here

Step 1 - Opening "wow.exe" with IDA.

First thing is to open 'ida pro', do not forget to run as administrator if you're using windows vista or seven.
We'll have to open wow with IDA to tell ida that we want to disassemble the file to start searching for stuff.
Here you just have to click "File..Open.." select the binary 'wow.exe' and Open.

If you've got a popup after clicking Open, select Portable Executable File (PE).
It takes a certain time for ida to disassemble the binary, so go take a cup of coffee and wait.




Step 2 - The strings window.

So at this point you should have an IDA pro opened with an analyzed wow.exe. What we want is search for something, at this point the easiest way to find something with our poor knowledge is looking at the 'Strings Window'.

- Hit "Shift + F12", wait a moment. This will generate what we call strings.

We will use that window to search for something.

So what you'll do is locate the string "GetMinimapZoneText"

- Hit "Alt + T" type "GetMinimapZoneText".
- Ctrl + T if you want to move to the next occurrence.

You should obtain something like this.





Step 3 - Where is dA c0d3 ?.

Well double click the "GetMinimapZoneText" line, this will bring you to the ida "View-A" of the code.
To access the sub view of the code you will have to click on the .data address.





Step 4 - Show me dA c0d3 !!.

So know you have your IDA pointing on "GetMinimapZoneText" the .data:address.
To view the asm code and start working by your own you will have to click on the "sub_ADDRESS".




Step 5 - What now ?!?.

Well in the View-A of IDA you have the ASM code representing our function.

You have to start reversing by your own now. In this example with have our "GetMinimapZoneText" function located at 0x113D778. I have the "Hex-Rays" plug-in so hitting "F5" show me the pseudocode C.


And finally in C# :

string minimapZoneText = SMemory.ReadASCIIString(mp.WindowHandle, SMemory.ReadUInt(mp.WindowHandle,0x113D778), 30);


Console.WriteLine("GetMinimapZoneText : " + minimapZoneText);
Credits goes to all of you who want to learn things like me the other are not smart enough to understand things...

I'm pretty sure this thread is not perfect, feel free to edit / discuss / comment.

Special thanks :

Apoc (because it's an awesome guy)
kynox (his blog / work is also awesome)
Cypher (love the blog)
wraithZX
unkn0wn0x (because i'm sure the Aion bot is going to be good)

Credits by nopz
Read more ...»

wow offsets and pointers

On 0 comentarios

I spent a lot of time last days reading materials about this issue. It seams not many developers are eager to share info. Here is a way I found to get a few hundreds function pointers:

  1. Google: ollydbg. Unzip and run ollydbg.exe
  2. Start Wow.exe
  3.  In Ollydbg. File -> Attach -> WoW.exe -> Attach. Give the debugger a few seconds to parse the big list of modules and hurry up to resume the execution (press the "play" button on toolbar), so WoW can be happy.
  4. View -> executable modules (or press ALT-E) and select WoW. Press Enter or double click it.
  5. Right-click -> Analysis -> Analyse code (or press CTRL-A). Wait for the debugger to parse the modules. This is good that we will be able to spot beginning/ends and params of the functions found.
  6. In the new window, right click -> Search for -> All referenced text strings. Wait a few seconds for the debuger to parse the modules.
  7. In the new window, right-click -> Search for text. Type "Usage:" and make sure the entire scope is checked. Press Enter on a found entry to get sent in the CPU window to the function body.
  8. Use the markings made by the analysis to find the beggining of the function.
  9. Press CTRL-L in the text strings window to go to the next function

 The good part, these pointers never change, they are static.

The sad part, these are all public LUA function, so nothing juicy like your character position, orientation or things like that.

But its always "healthier" to call UnitHealth(player) than trying to read the health variable directly from the data segment, because that one is different each time you load the game.

I'd like some feedback from anyone who found any more "juicy" internal functions. C'mon, don't be "shy"

EDIT: maybe not all those functions found with my method are innocent.

E.G.: 00405CB0 worldport [x y z] 
Read more ...»

Using OllyDBG To Get Addresses In CSS

On 0 comentarios

i like this forum so i like give to people like others. i write tutorial to inform all about some helpful thing cus look like many are start to play css. i see all the mods give address but dont show how they get address. this is what this tutorial is for.

for example i will use C_PlayerResource. thing 1 is to open sdk and do search for C_PlayerResource in client project. you get probably 34 results. let open C_PlayerResource.h

in that file we get 2 thing, the virtual class and the external pointer css use to glabaly access the it. in order to able use we need to get address of that pointer.

extern C_PlayerResource *g_PR;
let us open C_PlayerResource.cpp and we look for g_PR. one of thing catch your eye should be this function

IGameResources * GameResources( void ) { return g_PR; }
if look back at class definition we see IGameResources is one of 2 inherited class, so now it possible to get C_PlayerResource from IGameResources pointer. but how we get poitner? we well need find address of function GameResources

so now let do search for GameResources function in sdk. one place we find called is in void CSpectatorMenu::OnThink()

void CSpectatorMenu::OnThink()
{
BaseClass::OnThink();


IGameResources *gr = GameResources();
if ( !gr )
return;
in function that there are 2 string both "player" and in next function first string is "%d:%02d\n" so let now open ollydbg. start css and attatch olly to. since we know class defin i n client project we load client module from css module list.

next we right click, "search for", "all referenced text strings". let load and when finished load right click in result box and select "search for text". put in box "%d:%02d\n" without the qutos. you result 1 and above result u should see "player" and "player" above that, so you know you are right place

double click where it say it and it should bring you to part of code in client.dll where that text is. the function above is the function where we want. scroll up and you will see a function where there are two "player".

if we look back at original function in sdk we see that GameResources is one of first function calles, and we know also if it is null result the function leave. so lets look at top of function that we in ddebug.

240853B0 53 PUSH EBX
240853B1 56 PUSH ESI
240853B2 57 PUSH EDI
240853B3 8BF1 MOV ESI,ECX
240853B5 E8 868B1900 CALL client.2421DF40 ; first call but nothing stored
240853BA E8 B10B0700 CALL client.240F5F70 ; second call
240853BF 8BF8 MOV EDI,EAX ; store result of call
240853C1 85FF TEST EDI,EDI ; check result
240853C3 0F84 BE000000 JE client.24085487 ;this lead to return from function
hmm the second call look right so lets check it out

240F5F70 A1 E8433024 MOV EAX,DWORD PTR DS:[243043E8]
240F5F75 85C0 TEST EAX,EAX
240F5F77 74 06 JE SHORT client.240F5F7F
240F5F79 05 80040000 ADD EAX,480
240F5F7E C3 RET
240F5F7F 33C0 XOR EAX,EAX
240F5F81 C3 RET
hmm this function look right becuase it is just return a pointer if pointer is valid. so it look like our search is in success! but if you are lazy like me you dont want define function you just want pointer! and by look at function the pointer to "C_PlayerResource *g_PR" is 0x243043E8

but what if this change? let make sure we always have this address and we do this with help dominik codes that search for signature. but how could we select signature that will only find this peice code in client.dll? well if you are really parranoid you can see use whole function becuase it small so your sig would look this:

\xA1\xE8\x43\x30\x24\x85\xC0\x74\x06\x05\x80\x04\x00\x00\xC3\x33\xC0\xC3
"x????xxxxxxxxxxxxx"
with code above we can do this

DWORD d = (DWORD)(findpattern( ... )+0x01);
that give us address of pointer. but we can make this shorter and i will leave to you to find that.

so, now you got auto update for C_PlayerResource pointer. so what can use for? i use for alive list.

i hope you like this, i just try to give back to good comunity. thankQ for reading and i would like to see response

Credits by KidBuu
Read more ...»

Making an Aimbot

On viernes, 13 de agosto de 2010 0 comentarios

I want to make an aimbot for a game and from what i gathered about making one i need three things to make it work:

A. My Position
B. There Position
C. The angle between me and that player
D. (For instant headshots and what not) X, Y cords for the head postion or as some people have called it: Bones (not sure if im completely correct on that lol)

Theres one other criteria but i forgot, ill go reasearch again and post it but for now thats the basics of what i want to do.

What im asking is where to start? Its kind of overwhelming yet seems so simple.

Any ideas where to start?

Dont get the wrong idea, i plan on using this on the client side.

I play shooters legit and i dont like either

If you dont agree with my wanting to make one then please, dont bother posting

jus press the back button. If you dont agree i already know it.
Read more ...»

_CIpow en Delphi

On 0 comentarios

function _CIpow (x,y: double) : double;
begin
  result := power(x,y);
end;
Read more ...»

Como analizar una Dll en Delphi

On 0 comentarios

  • Abre el codigo dll en delphi...
  • Despliega el menu Run...
  • Selecciona la opcion Parameters
  • En la opcion Host application pon la ruta del ejecutable que llama a tu dll...
  • No olvides poner un BreakPoint en la funcion que quieres "debuguear"...

 
De esta forma se ejecuta el programa que llama a tu dll... Y en el momento que se ejecute el codigo se detiene en el BreakPoint que pusiste, asi puedes checar donde esta el posible error...
Read more ...»

[DELPHI] - Generate Random Password

On 0 comentarios

function RandomPassword(PLen: Integer): string;
var
  str: string;
begin
  Randomize;
    str := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW XYZ';
    Result := '';

  repeat
    Result := Result + str[Random(Length(str)) + 1];
  until (Length(Result) = PLen)
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  label1.Caption := RandomPassword(10);
end;
Read more ...»

[Guide] Hooking the Console Input and Output

On 0 comentarios

My next guide is more of a boring one, but it is necessary to show the concepts now since I will be using them in an upcoming guide (assuming I can get it done before any client updates)! There are no images to show really and I don't expect anyone to really spend a lot of time on this one now, but it will be a good reference for later on when I use the concepts.

Just remember all of the guides up to now are setting the stage for future guides (barring anything that might prevent me from doing more) so I have to show all these concepts in their own standalone form first. This guide really marks the last of the foundation guides that shows generic client specific techniques that I use.

After this guide, I will be working on a more practical guide series that I think a lot of people should find useful and like, but it might be a little controversial. There are only so many things that fit in that category, but I'll leave it to your imagination for now. :)

Hooking the Console Input and Output

I. Purpose

This guide will show an implementation of a console hook for input and output in Silkroad. This logic is based on some of the work I had done for Silkmod way back in the day. Silkmod was where chat block originated from before it was moved into Softmod when I stopped updating it.

This guide is an important development tool to understand because there will be times we want to be able to interact with the client without having to go through another GUI or external window. If we can use what we have in front of us, we can develop and test our code more rapidly and safely as we do not have to worry about thread safety issues.

The techniques for actually finding this stuff from scratch in the client are not going to be covered in depth. There’s no real way to teach that stuff so this guide is more of a code and explanation guide. Once you understand what is going on though, the information remains relevant for other tasks and you should be able to apply it in trying to find similar locations in other games.

II. Requirements

This guide is similar to the previous guides of extracting packets and integrating AntTweakBar. There is a mix of assembly logic with C++ programming. There are not really any new concepts presented though, we just use our codecaves again to steal data and make changes to logic!

In order to be able to follow along this guide, you will need:

• OllyDbg 1.10 (or equivalent)
• Visual Studio 2008 (or equivalent)

Before you continue this guide, you will also need to have already read and understood the previous guides! All of the guides build on one another in some shape or form, so it’s most beneficial to have read them all by now. Don’t forget to consult the assembly reference listed in the Loader guide if you need to look something up.

III. Theory

There is not much specialized theory in hooking the console input and output mechanisms in the Silkroad client. It’s really just a matter of finding the locations, saving the buffers, and using them as you need it. The way I went about tracking down this logic was by taking advantage of the swear filter in the game. If you type in a ‘bad word”, you will notice your text is not sent and you get a red error message in the console window.

If you find that error message in the PK2 files, you can find the associated string define for it in the client and start tracing from there. You will then be able to find the function that will show the error message as well as the logic for checking your input text. With that knowledge, it’s pretty easy to create your own swear filter bypass as well!

Like a lot of the previous guides’ concepts, it really just is a matter of getting lucky or spending enough time tracing through the client code until you find what you are looking for. Don’t expect to be able to open the client and just find this type of stuff without a bit of work! The code I’m showing in this guide probably took a good couple of days of tracing and testing to come up with when I first made it a while back.

With that said, and nothing really to cover, we can look at our specific code.

IV. Implementation

Basically we have 3 tasks to complete here. The first is to hook the input logic. This is the code that is called whenever we type something into the client. Silkroad has a special logic handler to where it will not display or send any text that has a / at the beginning of the line. We can use this to our advantage in implementing custom commands and arguments in our programs. For example, some of you might remember the Softmod command set, /sun, /rain, /snow, /min, /max, etc… As mentioned before, the chat input was found by finding where the swear filter took place and tracing backwards from that.
The second task we have is to hook the output logic. This was not too hard of a task if you use the approach I mentioned about finding the swear filter logic and then looking at the code that showed the error message if your text contained illegal words. In addition, there is a starting welcome message that you always see when you start the game that you could also track down in the client and base your function on. Either way, this task is not terribly hard for Silkroad!

The third and final task we have is to expose the function for displaying text in the console box. Since we are hooking the console output function, we can just call the function like the client does and voila! We are able to print to the console box. The method shown in this guide is the simple way to do it.

The last thing I should talk about is the additional logic used in the console output hook. I have added in additional code to check to see if the message should be displayed or not. While this is not required, it is a little extra feature I wanted to throw in because those spam bots in towns make for a very annoying development time if you are trying to output to the console! You will need to write a bit of code to implement a chat block, but it’s a lot easier having this code in place.



V. Conclusion

By following this guide, we now have additional tools available at our disposal. Being able to hook the console input allows us to implement direct interactions with our client for additional flexibility in our programs. Hooking the console output helps with logging and being able to block certain text from being on the screen. Finally, the display function helps give in game debug printing capabilities without having to rely solely on our console.

With this guide concludes most of the main core functionality we should need for our own custom injected DLLs. So far, most of the guides in this series provide a solid foundation of functionality and techniques to use to accomplish various tasks. Now that this knowledge has been disseminated, future guides can make use of it all to provide a more in depth look at complex programs that make use of all of these things.

That warps up this guide. I hope you have enjoyed it! I will be soon utilizing all of the concepts presented in my guides in one larger guide that shows something worthwhile!

Drew “pushedx” Benton
edxLabs
Read more ...»

[Guide] Extracting Built Packets in Silkroad

On 0 comentarios

Extracting Built Packets in Silkroad

I. Purpose

This guide will provide a complement to the previous guide of extracting the parsed packets in Silkroad. This time, we will learn how to extract packets the client sends the serer as they are built. Because most of the concepts in and theory are the same, this guide will be much shorter than the previous so please refer back to that article for all the nitty-gritty details.

An article like this is also just as important to understand as the previous was for any development that makes use of packets. If you are writing a client based tool, a clientless tool, or even a Silkroad emulator, you need to understand how packets are built and the format they follow. Using the techniques provided in this guide should help you achieve that.

I wanted to do make this a separate article as the previous one was getting pretty long itself. With all of the concepts explained already though, we can move through this one pretty fast. This lies in line with my first guide explaining how each article will relate to the others in one way or the other and once we have our base knowledge base established, we can do fun stuff. In addition, there are a few tricky parts in replicating the client's logic that we have not come across yet.
 
II. Requirements
 
If you have been keeping up with the previous guides, you should be able to follow everything presented here. There are no new concepts used. There is a bit more assembly logic used here though, but everything is based off our previously established concepts of codecaves and inline patching.

In order to be able to follow along this guide, you will need:

 
  • OllyDbg 1.10 (or equivalent)
  • Visual Studio 2008 (or equivalent)

 III. Theory


As I discussed in the previous guide, most games use code that greatly simplifies the programming challenges that lies ahead of them. When programming a networked game, there are a lot of things the developer must take into account when designing code. When it comes to packets, the developer has to figure out a way to make sure the client cannot spam the same packet over and over flooding the server.

Silkroad does just this with a simple packet opcode checking function. While I have not explored the internals of this function in a great degree at this time, just understanding that such a function exists can greatly help in our client reversing endeavors. The client will first check the opcode to see if such a packet can be sent. If it cannot, then the function usually skips execution by jumping over the packet building code.

Assuming the packet checking function is successful, the client will then build a new packet with the given opcode. Similarly to the opcode checking function, I’ve not actively explored the internals of how packet objects are constructed, but given I know C++ programming, it’s not hard to imagine how the process goes. We can hook this function to get the opcode of our current packet that is being built just as we were able to easily get the opcode of the packet that was being processed before.

Similarly to a ReadBytes function there is also a WriteBytes function. We can hook this function and simply rip out the data as it is being passed into the packet’s data buffer. By looking at multiple sections of code that build packets, we can also look for some final function that is called on the packet object to know when we are done building the packet. We know such a function has to exist because the client has to put in security bytes into the packets and actually dispatch the packet for sending to the server.

So, with this theory in mind as well as the knowledge gained in the previous guide, we can get started!

IV. Implementation

In order to get started, we need to know a packet opcode that is sent. By now, this information can easily be obtained, so there is no need to work from scratch to obtain one. If we had to, we would just breakpoint on a WSASend call and trace back the buffer until we could determine where the opcode was in the packet.

For this example, I will be using the character action packet, which uses an opcode of 0x7017. In order to find where the functionality lies for a packet that is sent to the server, we just have to search for the opcode! To begin our search, right click on the main assembly window and choose Search for -> All constants. Type in 7017 under the hexadecimal box and hit Ok. We get a new window that has search results in it and we can see we have a couple of entries. Double click on the first one to go to the client’s location.

We arrive in the main function that builds the 0x7017 packets. We know this because we see our opcode listed. Using what we learned in the theory section, we should first see a function call that checks to see if the packet can be used or not. We find that to be the case because there is a conditional jump after the first opcode but before the second that skips over a large part of the function. So far so good!

Next, we should be finding a function that writes bytes to the packet buffer. If we remember how the ReadBytes function was setup, it took two parameters, the buffer and the size. The WriteBytes should be no different. If we were to trace the function, we would quickly find the function and be able to identify the parameters.

Finally, we need to find a common function that is called after the packet building is complete. In order to do this, we will simply follow the call to the opcode setting function and look at all the other addresses that make calls to the function. We should be able to find a common function that is called in all of them and we do.

Here is an annotated screenshot of the entire function:
 

Now that we know the logic of how packets are built. All we have to do is setup the code to extract the data. This code is going to be really similar to the previous guide’s code, so I will not go through it in detail.


However, there were a few very tricky things to figure out during the process. Packets that are spanned across multiple opcodes for example, such as group spawn, make use of our packet writing functions! I came up with a little approach that should fix that issue for us.

Next, there was a problem replacing the client logic in the codecave. Since the code made use of the stack, it would incorrectly compile in Visual Studio this making the client disconnect. To fix this issue, I just used more commands to replicate the logic as it would be if it was done the long way.

Issues like these are not uncommon when working with game clients. When you have unexpected behavior and are sure your code is right, you have to be sure you do not have a problem like this. When I first wrote the code I was sure it was right and tracked the problem down to the WriteBytes codecave. I figured the stack operation should work fine, but it doesn’t.

After replacing the code, it worked perfectly! Chalk that up as a lesson learned of how tricky this development can get at times. The code for stealing the opcode seemed to work just fine, so I'm not really sure why this wouldn't either.


V. Conclusion

You should not have a good idea of how it is possible to let your game client do most of the hard work for you, whether it is extracting the received or sent packets. By following this guide, you should be able to greatly speed up packet related development efforts as all you have to do is trigger packets and save how the client parses them. Using this information, you can further your understanding of the client and track down the specific areas in the client responsible for generating certain packets. All you have to do is search for the opcode of interest!

That wraps up this guide! Between this guide and the previous, you should be able to work a lot more efficiently now with building a packet database for use in your programs. I hope you found this it informational and beneficial. Stay tuned for future guides!

Drew “pushedx” Benton
edxLabs
Read more ...»

[Guide] Extracting Parsed Packets in Silkroad

On 0 comentarios

http://www.elitepvpers.de/forum/sro-guides-templates/270486-guide-extracting-parsed-packets-silkroad.html

I think you guys are really going to love this guide the most. Using this guide, you will be able to accomplish the holy grail of any game and that's being able to figure out packet formats with very little work! Once again I must give thanks to clockwork for showing me the basics of this approach when I was getting started with this stuff in the past.

Extracting Parsed Packets in Silkroad

 
I. Purpose

 
This guide will be especially helpful to anyone that is working with Silkroad packets in their programs. Writing a simple proxy to dump the packets from Silkroad is pretty easy, anyone can do it. However, that information is not too useful because you must then struggle to figure out how to parse the packets yourself. This is a time consuming process and as a result it hampers development efforts.  

 
This guide will show how you can easily extract packets as they are parsed in the client so you do not have any hard work of trying to figure out the parsing yourself! In the past, I released a few programs that did this for you but I don’t think I released the source because it was part of a larger framework that had too much in it to release.

 
Now with our own simple injector and DLL, we can implement the logic ourselves and speed up development! I should also mention that I did not come up with this original idea. Credits for this goes to clockwork as he figured out the packet parsing stuff in the client long before I even knew anything fun! After having learned the networking stuff and the Silkroad security process, I went back and relearned this stuff as I didn’t understand it the first time I saw it.

 
II. Requirements

 
If you have been keeping up with the previous guides, you should be able to follow everything presented here. There are no new concepts used. There is a bit more assembly logic used here though, but everything is based off our previously established concepts of codecaves and inline patching.

 
In order to be able to follow along this guide, you will need:

 
  • OllyDbg 1.10 (or equivalent)
  • Visual Studio 2008 (or equivalent)

 
This guide contains a lot more assembly than the previous and less higher level programming logic. That is because the higher level logic is for you to implement to save the data in a format that best suits you. For the sake of this guide I am just dumping it all to the console. 

 
III. Theory

 
Most modern games make use of code that makes the developers’ lives as easy as possible. With Silkroad, a custom stream processing class was designed to allow the game to easily parse data out of the data stream that arrives on the TCP channel. As a result, this code can be hooked to intercept the data that is currently being processed.

 
In this guide, I will show you how to do this task so you can see data as the client does when it is parsing packets. If you have ever seen the source code of my older sr33 or edx33 projects, you might remember a custom packet reader class or packet builder class. If you do, then that is the code that we are reversing in the client. If you don’t, that’s ok as it’s not really important for now.

 
All we have to do is locate the stream processing functionality in the client and spend some time figuring out how it works. Once we do that, we can then setup our code in our DLL to utilize the client’s existing functionality to siphon out parsed data.

 
As mentioned in previous guides, actually discovering this kind of stuff just takes some experience, patience, and luck. If you were to search for commonly used words related to packet handling code, you would definitely stumble upon a few of these locations. There is no real trick to this stuff other than being creative and working until you figure it out.

 
That's about it for the theory section. It is quite small compared to some of the other articles, but there really is not too much going on here. It's just a matter of figuring out the right code to do what we want.

 
IV. Implementation

 
The first thing we need to do is find our main packet handling function. Typically, this is going to be a huge switch statement as most games implement their packet dispatching this way. Locating it in Silkroad can be found via two ways. Either you trace the raw packet data from the WSARecv functions and eventually hit the handler or you stumble upon it through searching the client’s referenced text strings.

 
Here is a screenshot of the function in OllyDbg. You can easily find this in any client if you search for a referenced text string that is shown.


That is quite a bit of assembly! However, if we look at the top of the function we can see a huge range of packet opcodes exist in a switch statement as seen in the predefined Olly comment. Further looking down the function and seeing the referenced text strings that are listed, we can have a pretty good idea we are in the right area.


Now just by intuition and looking at the start of the function, we can kind of assume the current packet opcode is stored into the EAX register on the 4th line of the function. This is important to remember since we can hook this location and save the current packet’s opcode if needed.

When we have functions like this, it’s good to understand the exit points so we can get a feel of where we need to perform our codecaves at. I have placed breakpoints on 3 out of the 4 exit points above. If you were to run Silkroad, you should not be able to trigger the 1st two breakpoints under normal circumstances and the 3rd breakpoint only triggers when you exit the client. The unmarked return seems to be the normal exit point. This is important information to keep in mind.

That’s just a general overview of our main packet handling function. We do not yet know where our packets are parsed or how to get the functions for individual packets. We can do that now. Let’s say we had done some preliminary packet research and saw the client sends us a packet with opcode 0x3667 on a chat message. Let’s say we just had a proxy program that dumped out all the packets for us. The first thing we would want to do is search the client for that opcode!

To begin our search, right click on the main assembly window and choose Search for -> All constants. Type in 3667 under the hexadecimal box and hit Ok. We get a new window that has search results in it and we can see we have one entry. Double click on it to go to the client’s location.

Eureka! This looks interesting! We can see a pattern of opcodes and function addresses. We can only assume one thing now! I’ve cheated a little and already labeled the function, but here is a screenshot for reference:
 

So, how do we read this stuff? The opcode is listed first, 0x3667. The function that should be called when the packet is received comes next, in this case 0x775D40. Let’s go ahead and go to that address in Olly to check it out. There is nothing too exciting at first glance. If you had no idea of what you were looking at, you would just set a breakpoint on the entry and trace through it when you got a packet in the client.

However, this is indeed our chat packet processing function. If we look down a ways, we see a switch that has cases from 1 to 16 (0x10) and these represent the different chat types. I’m not going to list out all of the various chat types and their associated values, but rest assured it’s all there.

Now we need to figure out which function calls this packet’s handler. If we were to set a breakpoint on the function and log in to the game and received a chat packet, we would hit our breakpoint. Here’s a look at the stack when we hit the breakpoint:
 

Immediately we can see the function that called us. If we hit Enter on the line, we will trace back to the calling function. Here is that function:



This makes sense to have a function pointer call because we know a different function is called for each packet opcode. We assume there is a map of opcode function mappings that is stored in the client. To assume this, you would have to had some programming experience with a map/dictionary data type. Let’s go back one more level to see what called this function. We will want to highlight the second return line in the stack and hit Enter on the line.

Lo’ and behold, we arrive at our main packet handling function we discovered earlier! We now know that the function right before our common return exit point is what dispatches the packet handler for whichever packet we are currently processing. This is good news now since we now know almost everything we need to about how the client processes packets.

What’s left is figuring out how the client actually parses them. If we were to study a few of the packet processing functions, we should notice a recurring pattern. There seems to be code that pushes a constant, pushes an address, and then calls the same function. If we were to investigate this function and check the parameters on entry, we would discover that this is the packet reading function! Here is a small snippet as an example from our chat processing function:
 

I went ahead and labeled the function, but you can do that yourself. If you don’t remember how, just click on the function call, hit enter to follow it, hit Shift + ; to add a label to the line, and finally hit the number pad - to go back.

Once we add our label and revisit any of our packet processing functions, we can now see lines of ReadBytes calls as well as how many bytes are being read. In some cases, there is no constant, which means it is a variable read.

At this point, we now know everything we should for being able to extract the packets as they are being parsed. We can now move on to the specific code we need to accomplish our task.

We first need to figure out how we are going to save our current opcode. This is pretty easy as it turns out because we have a 5 byte line to codecave at the beginning of the function. We can just rip the current opcode from EAX! As you see, our codecave function is really small since all we have to do is save the opcode into our variable and execute the original code.

Once we have our opcode saved, we now need to think about how we want to handle the packet reading functions. If we were to place a codecave in the function itself, we might have issues as it is a global function and might be used in more than one place for non packet parsing. Since we cannot rule this out, we will do what we did in our previous article to toggle the codecave for the function.

By setting up a codecave on top of the function call, we can easily toggle our logic on and off without interfering with other uses of the function. So far, so good. Now, we need to create another codecave specific for the packet reading function. Since we know we have a variable buffer and size, we have a little work to do. First, we have to codecave the start of the function to save the output buffer and the output size. Next, we need to let the function execute to parse the packet into that buffer. Finally, we need to process the final result using the stored buffer and then allow the function to return normally.

The logic above takes some time to come up with, but if you think about solving the problem, you should eventually reach the same conclusion on the best way to go about it.

One thing I did not explicitly mention is how to find the location to codecave. This can only be done if you trace the function without stepping into any calls and seeing what is the latest point in execution that you can reach while still having the data accessible. In my case, I managed to find a spot where the buffers were intact, however the codecave extend to the end of the function so I had to integrate that into the codecave itself.

You should understand why this had to be done if you read through the codecave tutorial! Remember you have to check all the locations of the possible jmps in the function to ensure you do not create an invalid instruction for another branch.

Once we have that code in place, we should be set for a test! Here is our final code for DLL.cpp:
 
#include


#include “../common/common.h”



// Global instance handle to this DLL

HMODULE gInstance = NULL;



// Function prototype

void UserOnInject();



// Main DLL entry point

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)

{

UNREFERENCED_PARAMETER(lpReserved);

if(ulReason == DLL_PROCESS_ATTACH)

{

gInstance = hModule;

// Do not notify this DLL of thread based events

DisableThreadLibraryCalls(hModule);

}

return TRUE;

}



// This is the main function that is called when the DLL is injected into the process

extern “C” __declspec(dllexport) void OnInject(DWORD address, LPDWORD bytes)

{

// Restore the original bytes at the OEP

DWORD wrote = 0;

WriteProcessMemory(GetCurrentProcess(), UlongToPtr(address), bytes, 6, &wrote);



// Call our user function to keep this function clean

UserOnInject();

}



namespace CC_ExtractPacket

{

FARPROC fpHandler = (FARPROC)0x6AE8F0;



DWORD currentOpcode;

LPBYTE currentBuffer;

DWORD currentSize;



void OnProcessDataStart()

{

printf("=== %X ===\n", currentOpcode);

}



void ProcessData()

{

for(DWORD x = 0; x < currentSize; ++x)

{

printf("%.2X ", currentBuffer[x]);

if((x+1)%16 == 0)

printf("\n");

}

printf("\n");

}



void OnProcessDataEnd()

{

printf("\n\n");

}



DWORD codecave_ExtractPacket_ReturnAddress = 0;



__declspec(naked) void codecave_ExtractPacket()

{

__asm pop codecave_ExtractPacket_ReturnAddress

__asm mov currentOpcode, eax

__asm pushad

OnProcessDataStart();

__asm popad

__asm CMP EAX, 0x3369 // Original code

__asm push codecave_ExtractPacket_ReturnAddress

__asm ret

}



DWORD codecave_ReadBytes_ReturnAddress = 0;



__declspec(naked) void codecave_ReadBytes()

{

__asm pop codecave_ReadBytes_ReturnAddress



__asm mov currentBuffer, eax

__asm mov currentSize, ebx



__asm pushad

ProcessData();

__asm popad



// Emulate the rest of the function since our codecave overlaps it all

__asm POP ESI

__asm MOV EAX,EBX

__asm POP EBX

__asm RET 8

}



void EnableParseHook()

{

edx::CreateCodeCave(0x4C42FC, 7, codecave_ReadBytes);

}



void DisableParseHook()

{

static BYTE patch[] = {0x5E, 0x8B, 0xC3, 0x5B, 0xC2, 0x08, 0x00};

edx::WriteBytes(0x4C42FC, patch, 7);

OnProcessDataEnd();

}



DWORD codecave_InvokeHandlers_ReturnAddress;

__declspec(naked) void codecave_InvokeHandlers()

{

__asm pop codecave_InvokeHandlers_ReturnAddress



__asm pushad

EnableParseHook();

__asm popad



// We have to use this trick as VS does not support calling direct memory addresses

__asm call fpHandler



__asm pushad

DisableParseHook();

__asm popad



__asm push codecave_InvokeHandlers_ReturnAddress

__asm ret

}



void Setup()

{

edx::CreateCodeCave(0x74BDDA, 5, codecave_ExtractPacket);

edx::CreateCodeCave(0x74BE85, 5, codecave_InvokeHandlers);

}

}



// The function where we place all our logic

void UserOnInject()

{

// Create a debugging console

edx::CreateConsole("SilkroadFramework Debugging Console");



// Mutex for the launcher, no patches required to start Silkroad now

CreateMutexA(0, 0, "Silkroad Online Launcher");

CreateMutexA(0, 0, "Ready");



CC_ExtractPacket::Setup();

}

When we run the program, we should notice we do not get any login server packets. This is because we only hooked the world server packet logic. We do not really need to worry about login server packet parsing as it is really easy to do by hand and there are not many packets at all. Packet should be flying by on the console. While it’s not easy to read unless you go to a quiet area, this should show the example in action. Here’s a screenshot of the console:



Woot! We are all done now. I designed the code so you can easily change up how you process the packets through the OnProcessDataStart, ProcessData, and OnProcessDataEnd functions. You might want to save to a file or route to a GUI, be creative.


V. Conclusion

Hopefully by now you have a good idea of how it is possible to let your game client do the hard work for you. By following this guide, you should be able to greatly speed up packet related development efforts as all you have to do is trigger packets and save how the client parses them. If you play around with this some, you might notice some oddities in some specific packets such as group spawn, character data, and storage. Try and reason out those issues yourself to think what the client is doing under the hood.

There is still a few more things that can be learned in this process by analyzing the client code, but that requires a bit of experience with assembly and understanding how code is generated. For the most part, you should be able to discover most of what you need to know only using the parsings. However, for some packets, you do need to look at the client code to figure out what is going on.

That wraps up this guide! As you can hopefully see, it's not that much code overall once you have a good idea of what to do. I hope you found this it informational and beneficial. Stay tuned for future guides, I will see what I can come up with next.

Drew “pushedx” Benton
edxLabs
Read more ...»

[Guide] Extracting Built Packets in Silkroad

On 0 comentarios

http://www.elitepvpers.de/forum/sro-guides-templates/271029-guide-extracting-built-packets-silkroad.html

Extracting Built Packets in Silkroad
 
I. Purpose

This guide will provide a complement to the previous guide of extracting the parsed packets in Silkroad. This time, we will learn how to extract packets the client sends the serer as they are built. Because most of the concepts in and theory are the same, this guide will be much shorter than the previous so please refer back to that article for all the nitty-gritty details.

 
An article like this is also just as important to understand as the previous was for any development that makes use of packets. If you are writing a client based tool, a clientless tool, or even a Silkroad emulator, you need to understand how packets are built and the format they follow. Using the techniques provided in this guide should help you achieve that.

 
I wanted to do make this a separate article as the previous one was getting pretty long itself. With all of the concepts explained already though, we can move through this one pretty fast. This lies in line with my first guide explaining how each article will relate to the others in one way or the other and once we have our base knowledge base established, we can do fun stuff. In addition, there are a few tricky parts in replicating the client's logic that we have not come across yet.

 
II. Requirements

 
If you have been keeping up with the previous guides, you should be able to follow everything presented here. There are no new concepts used. There is a bit more assembly logic used here though, but everything is based off our previously established concepts of codecaves and inline patching.

 
In order to be able to follow along this guide, you will need:
  • OllyDbg 1.10 (or equivalent)
  • Visual Studio 2008 (or equivalent) 
III. Theory

 
As I discussed in the previous guide, most games use code that greatly simplifies the programming challenges that lies ahead of them. When programming a networked game, there are a lot of things the developer must take into account when designing code. When it comes to packets, the developer has to figure out a way to make sure the client cannot spam the same packet over and over flooding the server.

 
Silkroad does just this with a simple packet opcode checking function. While I have not explored the internals of this function in a great degree at this time, just understanding that such a function exists can greatly help in our client reversing endeavors. The client will first check the opcode to see if such a packet can be sent. If it cannot, then the function usually skips execution by jumping over the packet building code.

 
Assuming the packet checking function is successful, the client will then build a new packet with the given opcode. Similarly to the opcode checking function, I’ve not actively explored the internals of how packet objects are constructed, but given I know C++ programming, it’s not hard to imagine how the process goes. We can hook this function to get the opcode of our current packet that is being built just as we were able to easily get the opcode of the packet that was being processed before.

 
Similarly to a ReadBytes function there is also a WriteBytes function. We can hook this function and simply rip out the data as it is being passed into the packet’s data buffer. By looking at multiple sections of code that build packets, we can also look for some final function that is called on the packet object to know when we are done building the packet. We know such a function has to exist because the client has to put in security bytes into the packets and actually dispatch the packet for sending to the server.

 
So, with this theory in mind as well as the knowledge gained in the previous guide, we can get started!

 
IV. Implementation

  
In order to get started, we need to know a packet opcode that is sent. By now, this information can easily be obtained, so there is no need to work from scratch to obtain one. If we had to, we would just breakpoint on a WSASend call and trace back the buffer until we could determine where the opcode was in the packet.

 
For this example, I will be using the character action packet, which uses an opcode of 0x7017. In order to find where the functionality lies for a packet that is sent to the server, we just have to search for the opcode! To begin our search, right click on the main assembly window and choose Search for -> All constants. Type in 7017 under the hexadecimal box and hit Ok. We get a new window that has search results in it and we can see we have a couple of entries. Double click on the first one to go to the client’s location.

 
We arrive in the main function that builds the 0x7017 packets. We know this because we see our opcode listed. Using what we learned in the theory section, we should first see a function call that checks to see if the packet can be used or not. We find that to be the case because there is a conditional jump after the first opcode but before the second that skips over a large part of the function. So far so good!

 
Next, we should be finding a function that writes bytes to the packet buffer. If we remember how the ReadBytes function was setup, it took two parameters, the buffer and the size. The WriteBytes should be no different. If we were to trace the function, we would quickly find the function and be able to identify the parameters.

Finally, we need to find a common function that is called after the packet building is complete. In order to do this, we will simply follow the call to the opcode setting function and look at all the other addresses that make calls to the function. We should be able to find a common function that is called in all of them and we do.

 
Here is an annotated screenshot of the entire function:
 

Now that we know the logic of how packets are built. All we have to do is setup the code to extract the data. This code is going to be really similar to the previous guide’s code, so I will not go through it in detail.


However, there were a few very tricky things to figure out during the process. Packets that are spanned across multiple opcodes for example, such as group spawn, make use of our packet writing functions! I came up with a little approach that should fix that issue for us.

Next, there was a problem replacing the client logic in the codecave. Since the code made use of the stack, it would incorrectly compile in Visual Studio this making the client disconnect. To fix this issue, I just used more commands to replicate the logic as it would be if it was done the long way.

Issues like these are not uncommon when working with game clients. When you have unexpected behavior and are sure your code is right, you have to be sure you do not have a problem like this. When I first wrote the code I was sure it was right and tracked the problem down to the WriteBytes codecave. I figured the stack operation should work fine, but it doesn’t.

After replacing the code, it worked perfectly! Chalk that up as a lesson learned of how tricky this development can get at times. The code for stealing the opcode seemed to work just fine, so I'm not really sure why this wouldn't either.

Here is our final DLL.cpp file:
 
#include


#include "../common/common.h"



// Global instance handle to this DLL

HMODULE gInstance = NULL;



// Function prototype

void UserOnInject();



// Main DLL entry point

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)

{

UNREFERENCED_PARAMETER(lpReserved);

if(ulReason == DLL_PROCESS_ATTACH)

{

gInstance = hModule;

// Do not notify this DLL of thread based events

DisableThreadLibraryCalls(hModule);

}

return TRUE;

}



// This is the main function that is called when the DLL is injected into the process

extern "C" __declspec(dllexport) void OnInject(DWORD address, LPDWORD bytes)

{

// Restore the original bytes at the OEP

DWORD wrote = 0;

WriteProcessMemory(GetCurrentProcess(), UlongToPtr(address), bytes, 6, &wrote);



// Call our user function to keep this function clean

UserOnInject();

}



namespace CC_ExtractSentPacket

{

DWORD currentOpcode;

LPBYTE currentBuffer;

DWORD currentSize;



void OnProcessDataStart()

{

printf("=== %X ===\n", currentOpcode);

}



void ProcessData()

{

for(DWORD x = 0; x < currentSize; ++x)

{

printf("%.2X ", currentBuffer[x]);

if((x+1)%16 == 0)

printf("\n");

}

printf("\n");

}



void OnProcessDataEnd()

{

printf("\n\n");

}



void EnableParseHook();

void DisableParseHook();



DWORD codecave_SetOpcode_ReturnAddress = 0;

__declspec(naked) void codecave_SetOpcode()

{

__asm pop codecave_SetOpcode_ReturnAddress

__asm MOV AX,WORD PTR SS:[ESP + 0x04] // Original code

__asm mov currentOpcode, eax

__asm pushad

EnableParseHook(); // Start hooking writes

__asm popad

__asm push codecave_SetOpcode_ReturnAddress

__asm ret

}



DWORD codecave_WriteBytes_ReturnAddress = 0;

__declspec(naked) void codecave_WriteBytes()

{

__asm pop codecave_WriteBytes_ReturnAddress



__asm mov currentBuffer, eax

__asm mov currentSize, ebp



__asm pushad

ProcessData();

__asm popad



// Even though this comes first, we will use EBX and then fix it up

// afterwards. This is ok since ECX is not disturbed.

//__asm MOV EBX, ECX



// This line seems to give the client problems when compiled in VS,

// so we have to rewrite it a little. This might be one of the hardest

// things to figure out if you were doing this yourself and not

// too experienced.

//__asm MOV DWORD PTR SS:[ESP + 0x10],EAX



__asm

{

mov ebx, esp

add ebx, 0x10

mov [ebx], eax

}



// Now set our EBX value to what it should be

__asm MOV EBX, ECX



__asm push codecave_WriteBytes_ReturnAddress

__asm ret

}



DWORD codecave_PostProcessPacket1_ReturnAddress;

__declspec(naked) void codecave_PostProcessPacket1()

{

__asm pop codecave_PostProcessPacket1_ReturnAddress



// We choose this line because it is the easiest to codecave and won't likely change

__asm MOV EAX, 0x1008 // Remember #s have to be in HEX! 1008 != 0x1008



__asm pushad

DisableParseHook();

OnProcessDataEnd();

__asm popad



__asm push codecave_PostProcessPacket1_ReturnAddress

__asm ret

}



void EnableParseHook()

{

// A little trick I came up with to filter out the packets received

// that make use of this functionality. Not sure if it'll always work,

// but it "should" since the higher 4 bytes of any C->S packet in the

// executable will be 0 since they are hard coded into the client!

DWORD result = currentOpcode & 0xFFFF0000;

//printf("Result = %i\n", result); // Debugging

if(result == 0)

{

// Hook the byte writing function

edx::CreateCodeCave(0x4D66CC, 6, codecave_WriteBytes);



// Hook the post build processing function

edx::CreateCodeCave(0x741CBE, 5, codecave_PostProcessPacket1);



// Let the user know we have an new packet being built

OnProcessDataStart();

}

}



void DisableParseHook()

{

// Restore the byte writing function code

static BYTE patch1[] = {0x8B, 0xD9, 0x89, 0x44, 0x24, 0x10};

edx::WriteBytes(0x4D66CC, patch1, 6);



// Restore the post build processing function code

static BYTE patch2[] = {0xB8, 0x08, 0x10, 0x00, 0x00};

edx::WriteBytes(0x741CBE, patch2, 5);

}



void Setup()

{

edx::CreateCodeCave(0x507B40, 5, codecave_SetOpcode);

}

}



// The function where we place all our logic

void UserOnInject()

{

// Create a debugging console

edx::CreateConsole("SilkroadFramework Debugging Console");



// Mutex for the launcher, no patches required to start Silkroad now

CreateMutexA(0, 0, "Silkroad Online Launcher");

CreateMutexA(0, 0, "Ready");



CC_ExtractSentPacket::Setup();

}

You should be able to compile and run. Here is an example screenshot of the program in action:



V. Conclusion

You should not have a good idea of how it is possible to let your game client do most of the hard work for you, whether it is extracting the received or sent packets. By following this guide, you should be able to greatly speed up packet related development efforts as all you have to do is trigger packets and save how the client parses them. Using this information, you can further your understanding of the client and track down the specific areas in the client responsible for generating certain packets. All you have to do is search for the opcode of interest!

That wraps up this guide! Between this guide and the previous, you should be able to work a lot more efficiently now with building a packet database for use in your programs. I hope you found this it informational and beneficial. Stay tuned for future guides!

Drew “pushedx” Benton
edxLabs
Read more ...»

[Guide] Hooking the Console Input and Output

On 0 comentarios

http://www.elitepvpers.de/forum/sro-guides-templates/278783-guide-hooking-console-input-output.html

My next guide is more of a boring one, but it is necessary to show the concepts now since I will be using them in an upcoming guide (assuming I can get it done before any client updates)! There are no images to show really and I don't expect anyone to really spend a lot of time on this one now, but it will be a good reference for later on when I use the concepts.

Just remember all of the guides up to now are setting the stage for future guides (barring anything that might prevent me from doing more) so I have to show all these concepts in their own standalone form first. This guide really marks the last of the foundation guides that shows generic client specific techniques that I use.

After this guide, I will be working on a more practical guide series that I think a lot of people should find useful and like, but it might be a little controversial. There are only so many things that fit in that category, but I'll leave it to your imagination for now. :)

Hooking the Console Input and Output

I. Purpose

This guide will show an implementation of a console hook for input and output in Silkroad. This logic is based on some of the work I had done for Silkmod way back in the day. Silkmod was where chat block originated from before it was moved into Softmod when I stopped updating it.

This guide is an important development tool to understand because there will be times we want to be able to interact with the client without having to go through another GUI or external window. If we can use what we have in front of us, we can develop and test our code more rapidly and safely as we do not have to worry about thread safety issues.

The techniques for actually finding this stuff from scratch in the client are not going to be covered in depth. There’s no real way to teach that stuff so this guide is more of a code and explanation guide. Once you understand what is going on though, the information remains relevant for other tasks and you should be able to apply it in trying to find similar locations in other games.

II. Requirements

This guide is similar to the previous guides of extracting packets and integrating AntTweakBar. There is a mix of assembly logic with C++ programming. There are not really any new concepts presented though, we just use our codecaves again to steal data and make changes to logic!

In order to be able to follow along this guide, you will need:
• OllyDbg 1.10 (or equivalent)
• Visual Studio 2008 (or equivalent)

Before you continue this guide, you will also need to have already read and understood the previous guides! All of the guides build on one another in some shape or form, so it’s most beneficial to have read them all by now. Don’t forget to consult the assembly reference listed in the Loader guide if you need to look something up.

III. Theory

There is not much specialized theory in hooking the console input and output mechanisms in the Silkroad client. It’s really just a matter of finding the locations, saving the buffers, and using them as you need it. The way I went about tracking down this logic was by taking advantage of the swear filter in the game. If you type in a ‘bad word”, you will notice your text is not sent and you get a red error message in the console window.

If you find that error message in the PK2 files, you can find the associated string define for it in the client and start tracing from there. You will then be able to find the function that will show the error message as well as the logic for checking your input text. With that knowledge, it’s pretty easy to create your own swear filter bypass as well!

Like a lot of the previous guides’ concepts, it really just is a matter of getting lucky or spending enough time tracing through the client code until you find what you are looking for. Don’t expect to be able to open the client and just find this type of stuff without a bit of work! The code I’m showing in this guide probably took a good couple of days of tracing and testing to come up with when I first made it a while back.

With that said, and nothing really to cover, we can look at our specific code.

IV. Implementation

Basically we have 3 tasks to complete here. The first is to hook the input logic. This is the code that is called whenever we type something into the client. Silkroad has a special logic handler to where it will not display or send any text that has a / at the beginning of the line. We can use this to our advantage in implementing custom commands and arguments in our programs. For example, some of you might remember the Softmod command set, /sun, /rain, /snow, /min, /max, etc… As mentioned before, the chat input was found by finding where the swear filter took place and tracing backwards from that.

The second task we have is to hook the output logic. This was not too hard of a task if you use the approach I mentioned about finding the swear filter logic and then looking at the code that showed the error message if your text contained illegal words. In addition, there is a starting welcome message that you always see when you start the game that you could also track down in the client and base your function on. Either way, this task is not terribly hard for Silkroad!

The third and final task we have is to expose the function for displaying text in the console box. Since we are hooking the console output function, we can just call the function like the client does and voila! We are able to print to the console box. The method shown in this guide is the simple way to do it.

The last thing I should talk about is the additional logic used in the console output hook. I have added in additional code to check to see if the message should be displayed or not. While this is not required, it is a little extra feature I wanted to throw in because those spam bots in towns make for a very annoying development time if you are trying to output to the console! You will need to write a bit of code to implement a chat block, but it’s a lot easier having this code in place.

As I said in the beginning, this guide is more of a code and explanation guide rather than a how to from scratch. The binary snippet for the console out was from 2007, so it should be safe for a while. The console input method is best found using the string and then looking for nearly identical code. The actual line being hooked has changed in the past. Here is the complete [B]DLL.cpp[/B] file with all of our concepts in place:

#define _CRT_SECURE_NO_WARNINGS
#include
#include "../common/common.h"

// Global instance handle to this DLL
HMODULE gInstance = NULL;

// Function prototype
void UserOnInject();

// Main DLL entry point
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
if(ulReason == DLL_PROCESS_ATTACH)
{
gInstance = hModule;
// Do not notify this DLL of thread based events
DisableThreadLibraryCalls(hModule);
}
return TRUE;
}

// This is the main function that is called when the DLL is injected into the process
extern "C" __declspec(dllexport) void OnInject(DWORD address, LPDWORD bytes)
{
// Restore the original bytes at the OEP
DWORD wrote = 0;
WriteProcessMemory(GetCurrentProcess(), UlongToPtr(address), bytes, 6, &wrote);

// Call our user function to keep this function clean
UserOnInject();
}

//-------------------------------------------------------------------------

void OnConsoleInput(std::string input);

namespace CC_HookConsoleInput
{
wchar_t * message;

void HookInput()
{
char mbMessage[4096] = {0};
wcstombs(mbMessage, message, 4095);
OnConsoleInput(mbMessage);
}

// Look for "UIIT_MSG_CANT_CHATTING" and scroll down a lot, code looks like:
/*
006CCC4E |. 8DBC24 FC000000 LEA EDI,DWORD PTR SS:[ESP+FC]
006CCC55 |> 896C24 24 MOV DWORD PTR SS:[ESP+24],EBP
006CCC59 |. 896C24 18 MOV DWORD PTR SS:[ESP+18],EBP
006CCC5D |. 896C24 1C MOV DWORD PTR SS:[ESP+1C],EBP
006CCC61 |. 896C24 20 MOV DWORD PTR SS:[ESP+20],EBP
006CCC65 |. 392D 08B9D300 CMP DWORD PTR DS:[D3B908],EBP
006CCC6B |. 889C24 70040000 MOV BYTE PTR SS:[ESP+470],BL
*/
DWORD codecave_HookInput_ReturnAddress = 0;
__declspec(naked) void codecave_HookInput()
{
__asm pop codecave_HookInput_ReturnAddress
__asm mov message, EDI
__asm pushad
__asm call HookInput
__asm popad
__asm MOV BYTE PTR SS:[ESP + 0x470], BL // Original code
__asm push codecave_HookInput_ReturnAddress
__asm ret
}

void Setup()
{
edx::CreateCodeCave(0x6CCC6B, 7, codecave_HookInput);
}
}

//-------------------------------------------------------------------------

bool OnConsoleOutput(int type, std::string output);

namespace CC_HookConsoleOutput
{
BOOL chatblocked = FALSE;
wchar_t * msgaddr = 0;
DWORD msgtype = 0;

void HookOutput()
{
char mbMessage[4096] = {0};
wcstombs(mbMessage, msgaddr, 4095);
chatblocked = OnConsoleOutput(msgtype, mbMessage);
}

// Bin: 8B 44 24 10 8B 54 24 08 50 8B 44 24 10 6A 00 52 8B 54 24 10 50 52 6A 01 6A 01
DWORD codecave_HookOutput_ReturnAddress = 0;
__declspec(naked) void codecave_HookOutput(void)
{
__asm
{
pop codecave_HookOutput_ReturnAddress
MOV EAX, DWORD PTR SS:[ESP + 0x10]
MOV EDX, DWORD PTR SS:[ESP + 0x8]
mov msgtype, EAX
mov msgaddr, EDX
pushad
CALL HookOutput
cmp chatblocked, 0
mov chatblocked, 0
jne LABEL1
popad
ret 0x10
LABEL1:
popad
push codecave_HookOutput_ReturnAddress
ret
}
}

void Setup()
{
edx::CreateCodeCave(0x697DA0, 8, codecave_HookOutput);
}
}

//-------------------------------------------------------------------------

void DisplayText(DWORD color, std::string text)
{
// Bin: 8B 44 24 10 8B 54 24 08 50 8B 44 24 10 6A 00 52 8B 54 24 10 50 52 6A 01 6A 01
// (The address of the function we hook above!)
FARPROC ConsoleOutFunc = (FARPROC)0x697DA0;
wchar_t outputText[4096] = {0};
wchar_t * pOutputText = outputText;
mbstowcs(outputText, text.c_str(), 2048);
color |= 0xFF000000; // Make sure alpha is set
__asm
{
MOV ECX, DWORD PTR DS:[0xF5CA74]
push 1
push color
push pOutputText
push 1
CALL ConsoleOutFunc
}
}

//-------------------------------------------------------------------------

// The function where we place all our logic
void UserOnInject()
{
// Create a debugging console
edx::CreateConsole("SilkroadFramework Debugging Console");

// Mutex for the launcher, no patches required to start Silkroad now
CreateMutexA(0, 0, "Silkroad Online Launcher");
CreateMutexA(0, 0, "Ready");

CC_HookConsoleInput::Setup();
CC_HookConsoleOutput::Setup();
}

void OnConsoleInput(std::string input)
{
printf("[INPUT] %s\n", input.c_str());
DisplayText(0x00FF00, input); // Color is in RRGGBB format.
}

bool OnConsoleOutput(int type, std::string output)
{
printf("[OUTPUT][%i] %s\n", type, output.c_str());
return true; // Keep the output
}
Here is what an example output looks like:





V. Conclusion

By following this guide, we now have additional tools available at our disposal. Being able to hook the console input allows us to implement direct interactions with our client for additional flexibility in our programs. Hooking the console output helps with logging and being able to block certain text from being on the screen. Finally, the display function helps give in game debug printing capabilities without having to rely solely on our console.

With this guide concludes most of the main core functionality we should need for our own custom injected DLLs. So far, most of the guides in this series provide a solid foundation of functionality and techniques to use to accomplish various tasks. Now that this knowledge has been disseminated, future guides can make use of it all to provide a more in depth look at complex programs that make use of all of these things.

That warps up this guide. I hope you have enjoyed it! I will be soon utilizing all of the concepts presented in my guides in one larger guide that shows something worthwhile!

Drew “pushedx” Benton
edxLabs
Read more ...»