• Sign up for TFS Icon Competition! The prize includes Otland Premium time and a medal, as well as obviously taking part in TFS history.
  • There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Feature [DLL] Simple WSAD in C++

kor

PHP ziom
Premium User
Joined
Jul 12, 2008
Messages
129
Solutions
10
Reaction score
142
Location
Bialystok, Poland
Hello.

At the beginning I wanted to ask a few questions how to approach the topic of DLL injection and hooking into functions in memory, but to be fair to this community, I am sharing with you a very very simple code that allows you to control your character using WSAD keys.


The principle of operation is that in the compilation process we get the ddraw.dll file that we put next to the Tibia.exe client (memory addresses correspond only to the client 8.60, on the others it will not work due to other addresses). Thanks to this, the client that loads the ddraw.dll system library by default, encounters this file in the same directory and it get priority in loading. Then, in the input function (rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L105)) the system library is loaded, and then the function (rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L127)) that the Tibia client needs. The graphic below shows why the choice was ddraw.dll - the client imports only one function from it (although it would probably be the same with the glu32.dll or winmm.dll libraries).

UvMyO0q.png


Next, I found the addresses in the client's memory responsible for sending the letter (0x458200), the place where sending the letter is called (0x4CFB8A) and where the CreateWindowExA function from the user32.dll library (0x5B8574) is called.

1. Hook at rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L115), then https://github.com/rookgaard/tibia-wsad/blob/master/dllmain. cpp#L58 is responsible for intercepting user actions. This is where I get information about which button was pressed (W/S/A/D) and then I change it to an arrow key (rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L21-L41)).
2. Hook at rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L112) is needed, because despite the user action being intercepted, the letter is sent to the text field anyway, so I can block it on rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L69-L83)
3. Information about the address for sending the letter in rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L111) is needed to write the letter in rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad) /blob/master/dllmain.cpp#L85 if the letter is not W/S/A/D.

The whole thing is additionally checked so that the action takes place only when the character is logged in (i.e. that when entering a password that contains, for example, the letter A, it is not changed to a left arrow) - rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L9-L11)

The code currently works on the principle that if there is a file next to the client, it is not possible to type these letters because they are converted into arrows - but this is not a problem, because you can easily add an additional flag/condition (e.g. activated with another key like ESC) which will control whether WSAD is active or not (however, this is not the topic I wanted to ask about, hence the lack of this code in the project).

What I don't like, however:
1. Mimicking the ddraw.dll system library

In the Erpegia client (formerly Fania OTS for 8.60) which I found somewhere in the internet (credits for @mateuszx), loading the erpegia.dll library was done by editing .exe files, where the application at some point "jumps" to another memory location:

4LOmc2H.png

on the left the original client with bytes 6A606858A95D00, on the right a modified client with bytes E9FA570500​

then loads the library into a free space in the code, and then recalls previously overwritten bytes:

lmnonLt.png

on the left the original client with zeros, on the right, a modified client with the name of the file to be loaded, where you can see the same overwritten bytes 6A606858A95D00​

Thanks to this, in the InitMain function (rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L101)) you can completely skip loading the system library and its functions - unfortunately it requires modification and sending the appropriate client to the users.

2. The way I capture functions
For one address I used the HookCall function (rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L88)), while in the second I had to use a different method - rookgaard/tibia-wsad (https://github.com/rookgaard/tibia-wsad/blob/master/dllmain.cpp#L114-L119) - where the common part is to reserve memory and release it for modification.

I am not a C ++ programmer myself and I feel very weak about this topic, so I do not understand why brewsterl/tibianic-dll (https://github.com/brewsterl/tibianic-dll/blob/master/main.cpp#L1911) uses two different solutions.

Could any of the subject matter experts help me evaluate/review this code? Advise what solutions are okay, which should be changed, and which are completely unacceptable? How else (apart from impersonating ddraw.dll and the mentioned client modification) can I inject dll on the user's side so that he can use WSAD?

P.S. In the repository there is a .dll file, so everyone can test it on it's own - just place it near Tibia client and press WSAD while logged in.

Sincerely,
Michał "Gubihe"
 

LordCompi

Well-Known Member
Joined
May 2, 2013
Messages
138
Solutions
1
Reaction score
71
Well, actually checked the sources before and I can vouch for this little masterpiece ;)
 
OP
kor

kor

PHP ziom
Premium User
Joined
Jul 12, 2008
Messages
129
Solutions
10
Reaction score
142
Location
Bialystok, Poland
Thanks, but there are some places I don't fully understand how they works (it was copied from tibianic dll), so I guess I've mixed different approaches.

@emil92b to work with 7.72 version, you just need to replace addresses that can be found in the tibianic repository. I can add a shortcut to toggle mode.
 

emil92b

Active Member
Joined
Aug 21, 2013
Messages
230
Solutions
6
Reaction score
48
Location
Sweden
Thanks, but there are some places I don't fully understand how they works (it was copied from tibianic dll), so I guess I've mixed different approaches.

@emil92b to work with 7.72 version, you just need to replace addresses that can be found in the tibianic repository. I can add a shortcut to toggle mode.
cool i got it to work :) can you help with toggle? :D
 

Qbazzz

Pół człowiek, pół litra
Joined
Jul 3, 2009
Messages
103
Solutions
1
Reaction score
86
Location
inside of the box
I am using IIDKing to "import" your own dll to client. You can import to client exported functions from your dll for inline usage but main of DLL is always loaded on the start of client so you dont have to carry about anything pretty much. IIDKing.zip - Serwis skanujący Jotti (https://virusscan.jotti.org/pl-PL/filescanjob/6d94pwsrs2)
HookCall is your friend :D When you hook functions you always need to check in debugger if hook is valid, for example createwindowex hook needs one nop after because its call from memory (if i remember correctly).
C++:
    //8.54 addresses 
    HookCall(0x56EC55, (DWORD)&MyCreateWindowExA);
    Nop(0x56EC5A, 1);

Gratis, you have my old hooking funcs XD
 

Attachments

OP
kor

kor

PHP ziom
Premium User
Joined
Jul 12, 2008
Messages
129
Solutions
10
Reaction score
142
Location
Bialystok, Poland

emil92b

Active Member
Joined
Aug 21, 2013
Messages
230
Solutions
6
Reaction score
48
Location
Sweden
@emil92b Here you are - addes unilicense and toggle wsad by ctrl+tab · rookgaard/[email protected] (https://github.com/rookgaard/tibia-wsad/commit/09b69221626e5192da2685a312b92b1307e24204)

@Qbazzz Thanks for response! I've seen in some clients where authors used IIDKing for import DLL, but I didn't liked how much it interfere with original executable (+ I didn't understand why I see DirectDraw functions instead of DllMain). Good point about checking hooks, I will pay attention to them.
thanks!
 

LordCompi

Well-Known Member
Joined
May 2, 2013
Messages
138
Solutions
1
Reaction score
71
Also to block opening skills or selecting all text in chat window while dancing on WSAD you will also need to block special keycodes in hooked pushLetter func.

C++:
 if ((Letter==1121)||(Letter==1139)) {
    return;
}
 
Top