Archive

Archive for the ‘Reverse Engineering’ Category

TRose.exe the library

July 20th, 2009

So there comes a time when you decide ‘hey, I am going to have to edit the client to do this’ which is where my TRose library comes into use. I attempted to keep the interface to it as clean as possible which is why if you look at the code (I suggest you don’t :D ) you will probably be like ‘wtf is he doing’.

It works in the way that every class and its functions are defined in my library, I also have one function which must be used before all others (RoseAPI::Init()) this function goes through every class member functions and rewrites the first bytes of them to a JMP to the original code using my function ‘FixMemberFuncAddress’.

template<class T> void FixMemberFuncAddress(int troseAddr, T func){
	CodeHook::ApplyJmpHook((unsigned char*)(*((void**)&func)), (unsigned char*)troseAddr, 0);
}

The crazy recasting of func is to get around the fact that you cannot convert a member function pointer to a memory address directly so I used the redirection shown above to get around this compiler restriction.

There was one more challenge to handle though, rewriting constructor and destructor addresses, so far I only have a need for constructor so I did not bother with writing a handler for them. The reason this was a challenge is because in the c++ specification it is stated that constructors are not functions, not physically existent and thus you cannot get their address. Well, fuck the standards, we don’t want any of that shit. So I declared it was time for a workaround!

This is where my code gets dodgy and I highly recommend you use my .lib file and do not attempt to recompile the lib as this constructor code is based on the final assembly generated and it will differ between compilers.

First step was making a small function which just creates an object:

void CSlotCreator(){
	CSlot* slot = new CSlot();
}

The next step was to write a function which reads the assembly generated for this small function and attempts to get the address of the constructor, I found two types of constructing, one which used a CALL and one which used a JMP to go to the constructor, both are able to be processed in my code.

void FixConstructorAddress(int addrROSE, unsigned char* createFunc){
	unsigned char* addr = createFunc;
	if(addr[2] == 0xE8){
		for(int i = 0; i < 0x20; ++i){
			if(addr[i] != 0xE9) continue;
			int relAddr = *(int*)(addr + i + 1);
			int cAddr = (int)(addr + i);
			int ctorAddr = cAddr + relAddr + 5;
			unsigned char* codePtr = (unsigned char*)ctorAddr;
			DWORD oldProtect;
			VirtualProtect(codePtr, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
			codePtr[0] = 0x8B;
			codePtr[1] = 0xC8;
			VirtualProtect(codePtr, 5, oldProtect, &oldProtect);
			CodeHook::ApplyJmpHook(codePtr + 2, (unsigned char*)addrROSE, 0);
			break;
		}
	}else{
		addr = addr + 0x30;
		for(int i = 0; i < 0x20; ++i){
			if(addr[i] != 0xE8) continue;
			int relAddr = *(int*)(addr + i + 1);
			int cAddr = (int)(addr + i);
			int ctorAddr = cAddr + relAddr + 5;
			unsigned char* codePtr = (unsigned char*)ctorAddr;
			DWORD oldProtect;
			VirtualProtect(codePtr, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
			codePtr[0] = 0x8B;
			codePtr[1] = 0xCE;
			VirtualProtect(codePtr, 5, oldProtect, &oldProtect);
			CodeHook::ApplyJmpHook(codePtr + 2, (unsigned char*)addrROSE, 1);
			break;
		}
	}
}

So as you can see, it reads the bytes until it finds a JMP or CALL and then reads the address to the constructor, once this is done it rewrites the first bytes of the constructor to MOV ECX, ESI or MOV ECX, EAX (depending on CALL or JMP style) then JMP to the original TRose constructor! Hurray, that was fun.

Download the code and library here: TRose.lib.

admin C++, Open Source, Programming, ROSE Online, Reverse Engineering

TGameCtrl_r.lib, doing the impossible :D

June 11th, 2009

After my lovely TriggerVFS.lib I decided to move onto something a bit more complex, making a lib for TGameCtrl_r.dll, which is probably over 9000% more complex as it uses full classes, multiple inheritance and virtual functions. Making a lib for that would be madness surely!

Yes it is madness, but I actually got it to work. I still can’t believe it even works to be honest as it is completely reliant on Visual C++ compiling my lib (with all its inheritance and virtual functions) to be identical to the ROSE dll. Which is ridiculous, yet worked.

Most likely you will not understand how ridiculous it is that this works unless you have a good knowledge of C++ and how those aforementioned features compile into assembly.

What does this mean then? This means it is piss easy to create a custom dialog for ROSE Online, simple link to my library and include required header files such as #include ‘TDialog.H’ or ‘WinCtrl.h’ or w/e you want :) .

Custom dialogs are now as easy as this:

class TestDialog : public CTDialog {
public:
	TestDialog(){}
	virtual ~TestDialog(){}
};

void AddTestDialog(){
	TestDialog* testDlg = new TestDialog();
	testDlg->Create("dlgAchievements");
	AddDialog(1339, testDlg, testDlg->GetControlID());
	testDlg->Show();
}

How simple eh? It is as if we actually have the real code to TGameCtrl, this is how it would be used in ROSE, with the simple inheritance, all the virtual functions working properly and everything :D .

Pretty awesome :) .

It is not yet ready for release as I have many more classes to reverse from TGameCtrl_r.dll, below is a list of what I have done so far after many hours of reverse engineering. It may look light a random assortment of classes but it is basically every class which CTDialog depends on, other than the scroll bar related ones, I began implementing them now so I can implement the ZListBox class so I can fully recreate my achievements dialog with my new code.


Directory of C:\Programming\Libraries\TGameCtrl\TGameCtrl

221 ActionListenerList.h
161 IActionListener.h
115 IScrollModel.cpp
495 IScrollModel.h
79 ITControl.cpp
340 ITControl.h
134 ITDraw.h
319 SinglelineString.h
886 TButton.cpp
1,300 TButton.h
677 TCaption.cpp
886 TCaption.h
171 TCommand.h
217 TCommandQ.h
2,281 TDialog.cpp
2,582 TDialog.h
345 TGameCtrl.h
5,878 TGameCtrl.vcproj
593 TImage.cpp
923 TImage.h
131 TObject.cpp
256 TObject.h
1,012 TScrollBar.cpp
1,289 TScrollBar.h
190 TScrollBarType.h
704 TScrollBox.cpp
974 TScrollBox.h
251 TStatusBar.cpp
411 TStatusBar.h
2,156 WinCtrl.cpp
2,892 WinCtrl.h
33 File(s) 28,869 bytes

Sorry if you guys are not as excited as I am but I thought this was totally awesome, it might not seem as awesome if you do not know how C++ works and how it compiles into ASM.

Expect a release soon.

admin C++, Open Source, Programming, ROSE Online, Reverse Engineering

Tutorial: ‘My First Inject DLL’

June 6th, 2009

In a bid to compete with xadet’s blog I have realised I must post something useful on here, so I have come up with the idea of this tutorial which is rather patronisingly title ‘My First Inject DLL’, how whimsical of me. Also this allows me to continue the TRose.exe name colour tutorial properly, which expect to come very soon (I can’t be bothered to wait for Ruff to come back up, I am just going to do it without running ROSE :P )

In this tutorial we will make an EXE to inject our DLL into ROSE Online, or any other program, but of course this tutorial will focus on ROSE, we will also learn how to do hook code and how to call functions in the ROSE online exe, how exciting does that sound? Very.

So go ahead and create a new solution and add a win32 console application project, tick Empty Project so visual studio does not create worthless code that we do not want! Note that this first project will be for the EXE so name it something applicable, such as ‘My First Injector’!

Obviously the first thing to do with our new project is add a main.cpp file and put in the default code:

int main(int argc, char** argv){
	return 0;
}

Brilliant start I would say, now we have to add #include as pretty much every function we use will be from the windows API! Before we can attempt to inject any dll we must start the application so we shall use CreateProcess for that.

So here is a snippet showing you how to use it:

char* exename = "TRose.exe @TRIGGER_SOFT@ _server 127.0.0.1"

STARTUPINFOA si = { sizeof( si ) };
PROCESS_INFORMATION pi;

if(!CreateProcessA(NULL, exename, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi)){
	printf("Failed to CreateProcess for trose.exe!\n");
	return 0;
}

Once we have called CreateProcessA, if it succeeds, it will return the new process handle in ‘PROCESS_INFORMATION pi;’ struct, we can now use this handle for injecting our dll, I went ahead and put the actual injection code in a separate function, ill paste the code below and then explain it to you:

bool InjectDLL(HANDLE hProcess, const char* dll){
	DWORD dwWritten;
	LPVOID pStringInRemoteProcess;

	if(!hProcess) return false;
	pStringInRemoteProcess = VirtualAllocEx(hProcess, 0, strlen(dll)+1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	if(pStringInRemoteProcess == NULL) return false;

	WriteProcessMemory(hProcess, pStringInRemoteProcess, dll, strlen(dll)+1, &dwWritten);
	if(dwWritten != strlen(dll)+1) return false;

	CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"), pStringInRemoteProcess, 0, 0);
	return true;
}

So yes this looks complicated, but it is all required! Basically, we use VirtualAllocEx so we can allocate memory in the remote process (TRose.exe) with which to write the dll name, as obviously we cannot call a function across processes with its parameters coming from our process! WriteProcessMemory then writes this dll name to the previously allocated memory. Now the main code, CreateRemoteThread, this does as named, it creates a new thread in the remote process of TRose.exe! This code automatically runs the function LoadLibraryA which is imported from kernel32.dll, and passes it the argument of the pointer to the previously allocated memory which contains our dll’s name!

That was complicated and it is not important that you understand it as the windows API is funtastic, the main point of this tutorial is to teach you about the actual inject dll, not the exe which injects it!

So my final code for the main procedure is:

int main(int argc, char** argv){
	const char* dllname = "myfirstinject.dll";
	char* exename = "TRose.exe @TRIGGER_SOFT@ _server 127.0.0.1";

	STARTUPINFOA si = { sizeof( si ) };
	PROCESS_INFORMATION pi;

	if(!CreateProcessA(NULL, exename, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi)){
		printf("Failed to CreateProcess for trose.exe!\n");
		return 0;
	}

	if(!InjectDLL(pi.hProcess, dllname)){
		printf("Failed to inject the dll!\n");
		return 0;
	}

	printf("Successfully injected the dll to TRose.exe!\n");

	return 0;
}

You should customise that code to include your dll’s name and the IP of the server you will be connecting to!

Now we shall add a new project to the solution for the dll, set it as a win32 console application but then in the wizard that comes up select DLL for the application type and tick the empty project again :) .

Once again add a main.cpp or whatever you like to call it and add the entry point code, it is slightly different for a dll:

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){
	UNREFERENCED_PARAMETER(hModule);
	UNREFERENCED_PARAMETER(lpReserved);

	switch(ul_reason_for_call){
		case DLL_PROCESS_ATTACH:
			break;
		case DLL_PROCESS_DETACH:
			break;
	};

	return TRUE;
}

So now is where the magic happens, the main point in this tutorials existence and it only took 730 words to get here! Yay!

I am sure you can decipher the code above, UNREFERENCED_PARAMETER is a macro used to prevent the compiler giving me warnings about unreferenced formal parameters, from the switch cases I believe it is simple that the code we will be writing will be in the ATTACH section but I have included the detach case if you wanted to do any clean up or dumping :) .

The first thing we are going to do is rival xadet’s recent post on sending chat messages to ROSE but hopefully our end result will be prettier because we are using C++ and not that .NET managed rubbish.

We are going to hide the code in a header file so it can be reused in your other applications, so go ahead and create a file called ‘RoseAPI.hpp’ or whatever you want, but that is what I am calling mine :) .

Because the function which adds text messages to the chatbox is actually a class function we need to create a fake class, following the naming convention from xadet’s tutorial I shall call it CIT_MGR, it will be defined simply by adding a small declaration to the header, I have also added a function which returns the IT_MGR class from the TRose memory by casting 0×697AD0 (which is the location of this class in TRose.exe) to a CIT_MGR* pointer.

class CIT_MGR {};

static inline CIT_MGR* IT_MGR(){
	return reinterpret_cast<CIT_MGR*>(0x697AD0);
}

That was simple, now it gets a bit more complicated, we must define the function declaration which is:

typedef void (__thiscall IT_MGR::*PTR_AddChatText)(const char* message, int type, unsigned int customColour);

As you can see it uses the __thiscall mechanism which states it is a call to a class function, this looks like a typical function pointer, you can read more about them here.

The next part requires some trickery due to how class function pointers work, due to the nature of class pointers we cannot directly convert an address to a class pointer which is why I have found this rediculous method:

const int addr_TR_AddChatText = 0x48D890;
static const PTR_AddChatText TR_AddChatText = *((PTR_AddChatText*)&addr_TR_AddChatText);

#define AddChatText (IT_MGR()->*TR_AddChatText)

This may look silly but oh well, the advantage we have over xadet’s methods is the pure usability of my code, no ASM required, just pure C++ trickery going on here. The first variable has the address to the function, this is then followed by the function pointer, as you can see I have crazy pointer casting going on as this is the only way to prevent any compiler errors about converting an int to a class function pointer. The define I have added is for usability, it allows the code to be easily called, thus allowing me the functionality of:

AddChatText("I am a chat message", ChatType::ALL, 0);

How handy and neat and tidy and stuff is that final code, the method to get it may have been messy due to the use of class function pointers but I am sure you will let me off with that as it is hidden away in a header file anyway!

There is only one problem with this, we have no way of really using this AddChatText as we can’t add the text when the DLL is attached as the game is only just starting! We need some sort of trigger… Some sort of ‘hook’…

How about when the client uses a / command?! Genius plan.

To do this we need to place a hook where our code will be executed whenever the client attempts to send a chat message beginning with a ‘/’, to do this we are going to hook the send packet location! :) Hurray.

First off I am going to provide you with a generic function used to hook code:

void ApplyJmpHook(unsigned char* code, unsigned char* location, int nops = 0){
	DWORD oldProtect;
	VirtualProtect(code, 5 + nops, PAGE_EXECUTE_READWRITE, &oldProtect);
	code[0] = 0xE9;
	*(int*)(code+1) = (int)location - ((int)code + 5);
	if(nops > 0) memset(code + 5, 0x90, nops);
	VirtualProtect(code, 5 + nops, oldProtect, &oldProtect);
}

ApplyJmpHook takes 3 parameters, the code to place the hook and where this hook will redirect to, it also allows a specified amount of NOP commands to be added after the JMP. In this function you can see VirtualProtect being used, this is because the executable memory in an exe is usually protected against writing, VirtualProtect allows us to write over the code memory. The rest of the code is merely writing the code to memory, 0xE9 is the prefix for the JMP command, then I write the address for the JMP, then 0×90 is a NOP command.

Beautiful. Now this function can be used in such a way like ApplyJmpHook(roseCode, &MyFunction, 1); In order to apply this hook we need to know where the SendPacket code is, I am not going to show you how to find it as that would be another long tutorial, instead I am kind and provide you with this address to use: 0×00402D5E and I shall also inform you that this hook needs 0 NOPs :) . (NOP is used to allow OllyDBG to read the code properly after we have modified it, if our code overwrites only half of a command we need to NOP the other half of it!)

There is just one more problem with this, we can’t make it JMP directly to a C++ function as it will not have the correct arguments and will lead to errors! So first we must make a little wrapper function like the one below:

static const char* TROSE_PacketEncryption = reinterpret_cast<const char*>(0x00405020);
static _declspec(naked) void ASMOnSendPacket(){
	_asm{
		PUSH ECX
		PUSH ESI
		CALL CppOnSendPacket
		POP ECX
		CALL TROSE_PacketEncryption
		POP ESI
		RETN 0x04
	}
}

Hurray, now we can declare a function CppOnSendPacket and hook the ROSE code using:
(Note that we must apply the hook in the DLL_ATTACH code!)

bool CppOnSendPacket(char* packet);
ApplyJmpHook((unsigned char*)0x00402D5E, (unsigned char*)&ASMOnSendPacket, 0);

Now it is just a matter of reading the packet, detecting if it is a chat packet and reading the chat message to look for our / commands!

bool __stdcall CppOnSendPacket(char* packet){
	unsigned short size = *(unsigned short*)packet;
	unsigned short command = *(unsigned short*)(packet + 2);

	if(command == 0x783 && size > 7){
		char* message = packet+6;
		if(_strcmpi(message, "/hello") == 0){
			AddChatText("Hello Mr. ROSE Man", ChatType::SYSTEM, 0);
		}
	}

	return true;
}

WOOOT! So now when a player types /hello in game they should be presented with a friendly message saying “Hello Mr. ROSE Man”, how lucky are they!

Hello Mr ROSE Man

Hello Mr ROSE Man

That is the end of this absolutely massive tutorial! At this point it is currently 1820 words long and took a long time to write haha :) oh well. This tutorial was needed as it is a prerequisite for other tutorials such as the name colour tutorial part 3 (which I have already wrote 500 words of but realised I needed an inject dll to continue!) and the upcoming tutorial on creating 100% custom dialogs in ROSE!

As usual the source for this tutorial is available, download it here.

1909 words, nice.

admin C++, Open Source, Programming, ROSE Online, Reverse Engineering, Tutorials

China-ROSE Patch Format

May 29th, 2009

I was bored so I decided to figure out the China-ROSE Patch format, and I have nothing better to do so I shall release it here. Expect a ‘China-ROSE Patch Stealer’ program to come out soon :) .

http://update.iqicheng.com/
1. Vertions.zip {Use Password 1}
2. ServerList.zip {No Password}
3. Using ‘vertions’ patch versions, /_67555_patchlist.zip
4. /_67555_patchlist.zip {Use Password 1}
5. Patch Files: /_67555_patchlistPath/1_2019_2723778792.zip
   - Where 67555 == 1 << 16 | 2019
   - 2723778792 = ROSE hash of filename (same thing as quest hashes)

Password 1:
3asfqvf`~sdvo?uoyk;jqad85tuiuw*riha3lkpuj,ghfz10/sf9hg.,jfts1fsdf
Serverlist.lst Fileformat:
Text based format, open in text editor to seee :)

Basically its “ServerName, ip, ip, unk” with mix of whitespace and tabs inbetween

Vertions.lst Fileformat:
This is just a list of file versions on each line (0×0D0A seperator..)
Patchlist Fileformat:
dword version
dword count {
  byte unk
  dword version
  dword CRC-32
  dword strlen
  string filename
  dword strlen
  string vfsname
}
byte password length
string password for zips!

admin Open Source, ROSE Online, Reverse Engineering

Finding the ultimate SQL Injection Fix

May 28th, 2009

I am sure everyone knows that the ROSE Online servers are rubbish at protecting against SQL Injections. There are vulnerable queries everywhere, making it rather annoying when it comes to patching them.

Even if you fix one injection someone will come along and exploit a different one. To prevent this why not patch every single SQL query in the server? Sounds good to me.

Finding and patching every query manually would be one giant pain in the ass though, so I decided to come up with a better solution.

So I asked myself the question: Where does every query end up going? Eventually they all have to go through one bit of code to be sent to the MSSQL Server.

So i opened the login server and made OllyDGB show me a list of all referenced text strings, looked down, found “{CALL UserAuthenticate(’%s’);}”, sounded good to me, put a breakpoint on it and went to login. Followed the breakpoint and ended up in a function in ODBC32.dll called SQLExecDirectA.

So that is the function that all ROSE servers use to send off their SQL queries, how exciting.

The first step was to hook this function! Easy enough, make a new dll, use LoadLibrary to get the ODBC32.dll handle, GetProcAddress to get the location of SQLExecDirectA. Using this dynamic method makes it work on any server that uses ODBC32.dll, much nicer than writing down all the addresses!

Blah blah blah, after the fun ASM stuff we end up with a query string, what do we do with that? We have to use some cleverness to scan it and decided whether or not it is safe or a meany! There are a few problems with this as queries can come in many different forms, first you need to filter out all the rubbish.

I started by making my code remove all strings (anything within ” and ‘) and all comments (anything in /**/). Then I decided to create a list of banned keywords, this includes things such as ‘–’ and ‘..’ both of which are handy in an attack (– to comment out the rest of code after attack and .. used to select databases) I had to be careful to make sure this would not block any existing queries in ROSE. Doing some research I found multiple methods of ‘evading’ these sorts of filtering methods and decided to also ban a few other keywords such as EXEC which can be used in a fashion like EXEC(”SEL” + “ECT * FROM ” + … etc) which splits up a keywords to evade detection.

Another filter method is to allow only one query per transaction, so if a query was like “SELECT * FROM UserInfo WHERE user=”; DELETE * IMMAHAXOR;–” it would be prevented. This stops pretty much every SQL injection attack as long as they are not hiding their query using methods such as EXEC, but due to the keyword banning that would be stopped aswell. I found only one case where this single transaction would be prevent a real ROSE query and that was with ”DELETE FROM tblWS_MEMO WHERE (intSN IN (SELECT TOP”, so I added an exception for this.

On contrary to what I posted on the Ruff-Rose forums I have decided I will not release the full source code but I will release a framework with an empty SQL scanning function (so basically you have to do the hard bit). I might consider a binary release at some point in the future after I have confirmed my fix is fully functioning.

Download the frameworkz: ODBC32 SQL Scanner Framework (you need to edit ScanSQLStatement.cpp)

admin C++, Programming, ROSE Online, Reverse Engineering, Tutorials

Tutorial: Name Colours in TRose.exe (Part 2)

May 6th, 2009

Soo I have finally started part 2, thanks to Ruff being brought back online :) gogo deebee powarr.

The first step its to return to where we were last time, so open ROSE Online, find a player that is gonna be sitting around for a while, attach OllyDBG and go to the code we found last time (address: 0×00487F92, Ctrl+G for goto!)

Now we should establish where exactly the colour to draw the player name is coming from. The first thing is to identify which argument the colour is which is passed to the function, below I have a lovely picture showing you some info :) . As you can see from the screenshot I placed a breakpoint on the player name draw function, and observed the values in the stack (the stack is shown in the bottom right window.) It is unsure how many arguments there are in the stack but you can guess that it will be atleast 6 as that is how many there are until the player name!

Looking at the values there is one which is 0xFFFFFFFF, that looks very interesting, remember that a colour can have up to 4 components: red, green, blue and alpha, all of which can have a value between 0 and 255. A value of 0xFFFFFFFF indicates 4 colours all of which have the value 255, that means it is the colour white with 100% alpha (solid, no transparency.)

See how I said in the first tutorial reverse engineering is more about the thinking than the technical skill! Now that we have realised it is ‘argument 4′ we can count backwards from the function call all the PUSH commands until we get to number 4 this shows us where the argument is added. The PUSH command ‘pushes’ a value onto the top of the stack; knowing that the stack is used for arguments and such things we know that these are the values that get passed to the function!

Colour is Argument 4! :)

Colour is Argument 4! :)

So now we have that argument 4 we see that it is added by a command ‘PUSH ECX’, so lets be clever and see what sets that value of ECX. Look up a few lines and BAM there it is at 0×00487F61: MOV ECX,DWORD PTR SS:[ESP+14]. Right this is interesting, it gets the value from the stack, now you must know the stack is not used purely for function calls but also sometimes used for local variables inside a function. One problem with this is that the stack moves around quite a bit, although it does have a base, at the moment it uses ESP+0×14, but it could be something else. Oh well, lets look upwards in the code and try and find anything which could be of some use! Nothing too obvious on there, so I suggest at this point we go to the first line of the function (0×00487D00 SUB ESP,78) and place a breakpoint.

The start of the function

The start of the function

Once the code hits this breakpoint it is simply stepping through till we see anything setting a value of 0xFFFFFFFF, note that a ’step over’ (F8) will be sufficient for this as the value is set in a local variable so we will not need to go into any called functions!

Woohoo we have found 0xFFFFFFFF

Woohoo we have found 0xFFFFFFFF

Wow that was very quick and easy, it gets set in the very next line!! I bet you were not expecting it to be that easy! Note how it is only setting the register EAX, which means it is very temporary at the moment! We must find where it uses this EAX now, so this really is as simple as looking down to see where EAX is used!

Yay it's using that lovely EAX register!

Yay it's using that lovely EAX register!

Right, we can see that the value in EAX is now being copied to the location ESP+0×10, note how that is very similar to the ESP+0×14 we found earlier, I told you how the stack can move around! :) .

Now we have pretty much all information we will need to manipulate name colours, the next (and final) part of this mini-tutorial series will show you how to set this value and will involve actually writing some assembly instead of reading it! YAYYY!

(Sorry if you were expecting to do that in this part 2 thingy, I just felt as this section began getting big it would be good to seperate the tutorial here as the next part will also be rather large! Oh and i also apologise for that very large block of text at the beginning, pictures are indeed prettier.)

admin ROSE Online, Reverse Engineering, Tutorials

Tutorial: Name Colours in TRose.exe (Part 1)

April 20th, 2009

So I am bored and don’t really have anything to do so I have decided to write a tutorial to help people better understand reverse engineering, and hopefully show them it is not as hard as it looks! Ability to read ASM is necessary but reverse engineering is more about using your brain, you have to think, hmmm if I want to track down this particular function how could I go about it.

Assembly language is very basic, no where near as complicated as it looks, I am not going to teach you it but you can learn alot about it from here:
http://webster.cs.ucr.edu/AoA/DOS/index.html

And there is also a great instruction list here to lookup unknown instructions:
http://courses.ece.illinois.edu/ece390/books/labmanual/inst-ref-general.html

You will need OllyDBG and some basic assembly knowledge!

So to start with, run ROSE and connect to whatever server you play on!

Now open up OllyDBG and go File->Attach, try and find TRose.exe in the list, I look for ‘C:\Program Files\Triggersoft\RuffRose\TRose.exe’ in the Path column, but that obviously will not be the same path for everyone! So hit the attach button and leave it for a second whilst ollydbg attaches itself.

The first thing it will do is ‘pause’ trose.exe so go Debug->Run (or F9) this will enable ROSE to run normally, get ingame so you are running around enjoying yourself, this is where the fun starts.

So the aim of this tutorial is to add name colours for players who reach a certain level such as in Ruff-Rose where peoples names become orange at level 210.

In order to do this we need to find where in TRose.exe this name drawing goes on, the first thing is to show the code for TRose.exe as by default the code for ntdll is usually shown. To do this hit the blue button in the toolbar with E on or View->Executable Modules (Alt+E). This should bring up a list of dlls and exes, hit the column header saying path to order them alphabetically and look for  ’C:\Program Files\Triggersoft\RuffRose\TRose.exe’ or whatever your TRose.exe path is, double click on it (sometimes you have to do this twice for the code of trose.exe to come up, the picture below shows how it should look now)

Open TRose.exe code view!

Open TRose.exe in code view!

Right, so now we need to find where it actually draws the other characters names! In order to do this we need to go ingame and actually position ourselves at a point where someone’s name is visible on screen. Now we need to use our brain a little, I am sure most of you know that the znzin.dll is what handles the rendering for ROSE Online, so we can start by looking at this.

In the executable modules list right click on znzin.dll and click View Names (Ctrl+N), this will show all the Exports and Imports from znzin, hit the ‘Name’ column header to order it alphabetically. So using our brain we are trying to look for something that draws text, hmmm maybe if we scroll down and look for functions with names like ‘drawXXXXXXX’.

View Names in ZnZin

View Names in ZnZin

We do not know which one is used by ROSE to draw player names so we should place a breakpoint on one at a time, this will pause the execution of ROSE and allow us to view what is happening when the code gets to those functions. To place a breakpoint click on each drawFontXXX, select it and press F2 (or Right Click->Toggle Breakpoint, F2 is much quicker though!) Once you have placed your first breakpoint it should look like this:

Breakpoint on the first drawFontXXX

Breakpoint on the first drawFontXXX

So now we have our breakpoint click on the ROSE Window to make it attempt to render (ROSE does not waste resources by rendering when the window is not active) ollydbg should come up and ROSE should be ‘frozen’ it should look something like below, note in the Stack View in the bottom right it shows us pretty much what text this call is drawing, in the first break it always is the current player’s name, mine shows RuffRoseDevs (my clan name). Obviously this is not the correct drawFont as it shows my clan name, we are looking for the player’s name that is on screen (the one you found sitting around doing nothing earlier.)

The first breakpoint

The first breakpoint

Just to make sure we are going to hit F9 a few times (Run/Resume) to see if this particular drawFont is used for more than just clan names (they might be using the same drawFont for both clan names and player names) if you do this a few times ROSE should stop hitting breakpoints as all the rendering should be finished and if we did not see the other player’s name then this is not the correct function! Go back to the names window in znzin and remove the breakpoint of the first drawFont function and apply it to the second function.

Do the exact same procedure as before and look for the player’s name, wow it does not appear on this function, amazing… Lets try the next one…

SUCCESS!

Success! We have it!

Success! We have it!

Right now we have which function it is, go to the stack window and at the very top of it there is a line saying RETURN to TRose.00487F98, when a function is called it puts the return address at the top of the stack so it knows where to return to once the fuction is finished, this is that address. Right click on it and select Follow in Disassembler (or hit Enter..), this will take you to a line saying ADD ESP, 0×1C, if you scroll up one line you will have the function call (the return address is of course going to be after the call or we will have an infinite loop!) We should remember this address, a handy way is to just add a comment (right click on the call and hit Comment or press ‘;’ on the keyboard) type something like “Draws other player’s name”. Now if you ever lose this address (0×00487F92) then you can right click anywhere in trose.exe and go ‘Search For->User Defined Comment’.

Messy screenshot showing Comments

Messy screenshot showing Comments

That is it for the first part of this tutorial thingy, so far we have managed to find where the player’s name is being drawn, this is first vital step.

In the next part I will teach you about the colouring stuff, how exciting!

admin ROSE Online, Reverse Engineering, Tutorials