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

  1. Csharp
    July 20th, 2009 at 12:36 | #1

    Are you gonna post a example for TGameCtrl_r.lib anytime soon? My custom windows don’t show up if I give them a Custom XML file :P

  2. July 20th, 2009 at 15:37 | #2

    Do you have the correct TSI file and the .id file?

  3. CSharp
    July 20th, 2009 at 16:04 | #3

    Nope :$ so I have to make a custom TSI and a ID file?

  4. July 20th, 2009 at 16:06 | #4

    Well if you have custom elements you are using in your xml!

  5. CSharp
    July 20th, 2009 at 17:01 | #5

    k thanks it’s working now do you maybe have a list of those wParam, lParam, uiMsg? :D

  6. CSharp
    July 20th, 2009 at 17:24 | #6

    or are they just the winapi ones?

  7. July 21st, 2009 at 15:34 | #7

    wow nice ;p

  8. Csharp
    July 21st, 2009 at 17:26 | #8

    :< just gotta know how to work with those Messages and I’ll be able to make a mp3 player :P

  9. CSharp
    July 24th, 2009 at 19:11 | #9

    nvm already figured it out :P

  10. abk
    August 26th, 2009 at 16:13 | #10

    thank you very much!!

  11. Lars
    October 12th, 2009 at 15:33 | #11

    How can you link the lib to my dll?

  12. Juan
    October 30th, 2009 at 20:48 | #12

    Correct me if i’m wrong but in your Packet class :
    change :
    template void Add(T value){
    *((T*)(mData + mSize)) = value;
    mSize += sizeof(T);
    }
    by : template void Add(T value){
    *((T*)(mData)) = value;
    mSize += sizeof(T);
    }

  13. Lars
    November 6th, 2009 at 00:15 | #13

    Was that as answer for my question?

  1. No trackbacks yet.