00586744
Code:
struct CameraInfo
{
BOOL CameraRecordDisplay;
BOOL RenderGUI;
BOOL DisableBars;
float WS_Speed;
float AD_Speed;
float QE_Speed;
float RF_Speed;
unsigned int CameraRecordSelectedIndex;
unsigned int Unknown1;
unsigned int Unknown2;
unsigned int Unknown3;
unsigned int Unknown4;
BOOL LadyGailEvent_Display;
DWORD LadyGailEvent_X;
DWORD LadyGailEvent_Y;
char LadyGailEvent_CPConvert_State;
char LadyGailEvent_GetItem_State;
char LadyGailEvent_GetClose_State;
char LadyGailEvent_Unknown_State; // probably place holder
unsigned int Unknown5; // Full FF
unsigned int GameTime; // ?
////......
};
Well I have no idea what the LadyGail event is and have no CP to test it but it apparently cashs in CP for an item. Might ban your char or something but feel free to try it if you wish. Dont blame me though if something bad happens :P
CameraInfo _CameraInfo = (CameraInfo*)0x00586744;
_CameraInfo->LadyGailEvent_Display = TRUE;
_CameraInfo->RenderGUI = FALSE; // Turns off GUI etc..
// Parts above each of these would be for the camera recording movement as it has a set speed to move so it should be possible to make it use that code and then we can configure the speed at which to rotate the camera possibly useless atm.
Code:
004556AC |> \68 0000C040 PUSH 40C00000 ; /Arg1 = 40C00000
004556B1 |. B9 60515700 MOV ECX,00575160 ; |Pan Left
004556B6 |. E8 653C0D00 CALL <RotateCamera> ; \RotateCamera
Code:
004556F6 |> \68 0000C0C0 PUSH C0C00000 ; /Arg1 = C0C00000
004556FB |. B9 60515700 MOV ECX,00575160 ; |Pan Right
00455700 |. E8 1B3C0D00 CALL <RotateCamera> ; \RotateCamera
Theres conditional jumps above it at
004556D5, 00455686
Nop them and it uses the other code
Yep you could call those if you wanted..
warning untested code!
Code:
void RotateCamera(float Movement)
{
__asm
{
MOV ECX,Direction
PUSH ECX
MOV ECX,0x00575160
CALL 0x00529320
}
}
Usage
RotateCamera( 5.00f ); // Right
RotateCamera( -5.00f ); // Left
I wonder if we can enable recording so that it records to .avi or something...
theres also movement for WS QE and RF
So camera can be controled like this
Turn Left,Right
Look Up,Down
Straff Left,Right
Move Vertically
All of these would be in this function I bet.
From the start of the code ive been looking at it and working out what things do
Code:
00454480 >/$ 55 PUSH EBP ; HandleKeyboardInput
00454481 |. 8BEC MOV EBP,ESP
00454483 |. 81EC D4020000 SUB ESP,2D4
00454489 |. 898D 40FDFFFF MOV DWORD PTR SS:[EBP-2C0],ECX
0045448F |. 833D 682C1801>CMP DWORD PTR DS:[<Screen>],6 ; If on world screen
00454496 |. 75 09 JNZ SHORT 004544A1
00454498 |. 833D 6C2C1801>CMP DWORD PTR DS:[<ScreenLoaded>],4 ; And it is loaded
0045449F |. 74 05 JE SHORT 004544A6
004544A1 |> E9 29140000 JMP 004558CF ; Jump out if not on screen
004544A6 |> 833D 70E71501>CMP DWORD PTR DS:[<InputDisabled>],0
004544AD |. 0F85 52120000 JNZ 00455705 ; if inputs disabled
004544B3 |. 833D 384B1601>CMP DWORD PTR DS:[<NormalCameraControl>]>
004544BA |. 0F85 FB050000 JNZ 00454ABB
004544C0 |. 0FB605 2D6757>MOVZX EAX,BYTE PTR DS:[57672D]
004544C7 |. 25 80000000 AND EAX,80
The addresses
NormalCameraControl 1164B38 // set to 1 to use WASD normally set to 0 to be able to control camera freely *its like a fly hack wow!* it disconnects maybe because im not a gm or it sends a packet if we can prevent the disconnect we have a fly hack...
InputDisabled 115E770 *Set to 1 to disable input*
It disconnects because its sending the packet ID 13 continuously
So ill attempt to find out where its sending this packet
Tracing code down I was able to find calls to direct X functions in an odd way its a table of all the imported functions but inside twelvesky2 memory like CALL Address then from there it JMP's to the dx function.
Starts at 0053BE2C
If you press : on the nop's or the Jmp's that are called you can write the function name below it with TwelveSky2 Prepended. If we wanted to unpack the game we might have to replace each call to this memory with the appropriate call to the d3d function.
Anyway time to set 1164B38 to 0 and breakpoint send then unbreakpoint ones that come up and press W to see where it breaks.
Then I can step out and nop the function call or look for a conditional jump yay.
Breaks here 00422DF2 Stepping out to 004A5DB9
Stepping out again to
Code:
0045454B |. 68 C3BF1801 PUSH 0118BFC3 ; /Arg1 = 0118BFC3
00454550 |. B9 18AF1801 MOV ECX,0118AF18 ; |
00454555 |. E8 26180500 CALL 004A5D80 ; \TwelveSk.004A5D80
We dont want this function to be used however its used in a lot of places
So lets go into it at 004A5D80
and change its first line to a RETN 4
then lets set 1164B38 to 0 "in cheat engine as 4 byte btw"
And woot no disconnect.
However we cant attack monsters or interact either if we can find a way to attack monsters then win there's probably some code for it getting skipped to do with this integer.
We could just toggle the address with a key enabling us to turn it on and off which would probably be better.
I have no idea why moving camera in this way sends a location to the server.
All this time and im still no closer to the check for if key A or D or up or down or left or right is pressed GRR i know its here somewhere. Ill just have to keep looking above the camera rotating part there will be a conditional jump that jumps over it. so if i look at the cmp,or test it might be a comparison if the key is down.
Ah I found it
0045566B |> \0FB60D 3A6757>MOVZX ECX,BYTE PTR DS:[57673A]
00455672 |. 81E1 80000000 AND ECX,80
00455678 |. 74 41 JE SHORT 004556BB
Its moving the byte at 57673A into ECX then checking if its fully pressed *80*
I went to this address in memory browser in cheat engine and scrolled up slightly and held down ESC in game showing me the first position in the array
If we look at the
we can see that escape is 1 we -1 and we get address of key buffer
unsigned char * KeyBuffer = (unsigned char*)0x0057671C;
if (KeyBuffer[DIK_ESCAPE])
{
// Escappe is pressed
}
KeyBuffer[DIK_UP]=0x80; would make you walk forward.
Now if we take the address for Escape 0057671D and put a 1 byte memory write breakpoint on it then remove the breakpoint when its hit we are in the function called before MangeKeyPress
Code:
00403943 B9 60515700 MOV ECX,00575160
00403948 E8 E3991200 CALL 0052D330 ; << WE ARE INSIDE IT
0040394D |. B9 00E71501 MOV ECX,0115E700
00403952 E8 290B0500 CALL <HandleKeyboardInput>
00575160 We know is the address for something we have seen it before
if we do a search for all commands and put in MOV ECX,575160 we can see everywhere this address is put into ECX
Its at the top of game step and pretty much everywhere a D3D Key press is checked or camera needs something done to it. Theres alot of stuff its used for. its in our GameInit function several times too
Anyway its a very important address to the game
Code:
0052D355 |> \8B10 MOV EDX,DWORD PTR DS:[EAX]
0052D357 |. 57 PUSH EDI
0052D358 |. 50 PUSH EAX
0052D359 |. FF52 1C CALL DWORD PTR DS:[EDX+1C] ; GetKeys
0052D35C |. 8D96 BC150000 LEA EDX,DWORD PTR DS:[ESI+15BC]
This code gets the keys or something. ESI is our important address +15BC is the offset to the data member we want that points to the address of the key buffer.
LEA means Load Effective Address so it loads the address into EDX
575160 +15BC = our keybuffer address
The code our memory breakpoint landed on was
Code:
0052D367 |. B9 40000000 MOV ECX,40
0052D36C |. F3:AB REP STOS DWORD PTR ES:[EDI]
it repeatedly stores every byte from one place into our EDI address or KeyBuffer.
Bytes | Opcodes Type| Description
F3 AB | REP STOS m32 | Fill (E)CX doublewords at ES:[(E)DI] with EAX
Its an interesting opcode you can read about it
Its moving all the data from directinput buffer into our keybuffer simply put
.
So if we get this special address 00575160 and add 15BC to it we have our key buffer
Code:
unsigned char * KeyBuffer=(unsigned char*)0x00575160+0x15BC;
Just like that its beaten
Now that we know how it works we should be able to easily find what key presses are what.
The game just checks the byte at the appropriate address so A would be
KeyBuffer[DIK_A]; which the address for that is
0x00575160+0x15BC + DIK_A which is 0x1E
SO 57673A is our address for A key
This line proves that
0045566B |> \0FB60D 3A6757>MOVZX ECX,BYTE PTR DS:[57673A]
So if we want to find the key check code for any key we just need to do the above equation substituting the key at the end then we can search for the command
MOVZX ECX,BYTE PTR DS:[OURADDRESSHERE]
or we can search for the bytes
0FB60D OUR ADDRESS IN BYTES
so if our address is 57673A we must pad it left with 0 so that it matchs 8 chars
0057673A then we type it backwards in blocks of two like so
3A675700
Then thats our address in bytes.
So we can use searching functions of cheat engine to find our key checks.
We can then change the address to whatever key address we wish it to check for instead.
Now what is even more interesting is if we detour HandleKeyboardInput function or the address 00454480
We can look at the KeyBuffer in our C++ dll and find what keys are pressed. We can also set them in there. So we detour it then look at the KeyBuffer to see if say End is pressed and if it is we can do something with our hack. Our code would only be hit when the game has focus.
Talk about winning
We can now modify game's keyboard keys it uses and set our own in our dll.
I could make Home key show a menu for my dll.
Sure we could use GetAsyncKeyState in our dll's main loop but we would then have to check if game has focus. Why not just use the games check
There is also a part after the keybuffer which tells us in more detail about the key event such as if the key has been pressed or unpressed. We could find what writes to that and detour that to have a KeyDown KeyUp event
What we can do is make a key buffer of our own and in our detour for ManageKey we can AND each byte from our key buffer into the games
so say if our key buffer has DIK_UP being 80 then the games keybuffer would have DIK_UP set to 80
Then after that operation we could set everything in our key buffer to 00 or off.
So if we want to trigger a game key we just set something in our key buffer to 80 the game would call its manage key press function which would goto ours setting our key into their buffer and then setting our buffer to be empty. the game would think the key is pressed the next operation the key would not be pressed. We can use that to simulate keys accurately.
Code:
for (unsigned int i=0;i<256;i++)
{
KeyBuffer[i]|=OurKeyBuffer[i];
}
Now we know how the game handles direct input keyboard strokes.
Can this knowledge be applied to other games? I bet it can. I tried searching for 80 when a key was down and 00 when it was not down on a game called Alex4 and found the KeyBuffer.
The game checks the keys for directional movement in this order
UP+LEFT
UP+RIGHT
DOWN+LEFT
DOWN+RIGHT
UP
LEFT
RIGHT
DOWN
Starting at 00454BFE
So if we want to change all of these to WASD we would have to change each one
Alternatively and probably better anyway we could manage this in our hook
// HANDLE WASD
OurKeyBuffer[DIK_UP]=KeyBuffer[DIK_W];
OurKeyBuffer[DIK_LFFT]=KeyBuffer[DIK_A];
OurKeyBuffer[DIK_RIGHT]=KeyBuffer[DIK_D];
OurKeyBuffer[DIK_DOWN]=KeyBuffer[DIK_S];
// HANDLE QE for rotating camera
KeyBuffer[DIK_A]=KeyBuffer[DIK_Q];
KeyBuffer[DIK_D]=KeyBuffer[DIK_E];
// Fix Skill window by moving its key to V
KeyBuffer[DIK_S]=OurKeyBuffer[DIK_V];
That would give us WASDQE movement with WASD being used for UP LEFT RIGHT DOWN and QE being used for A and D to rotate camera.
To find KeyBuffer easily in a game use cheat engine set a hotkey to do next scan exact value and next scan previous value and then search for a byte of 00 when escapes not pressed and type 80 into the box make sure you have hex ticked btw and then goto game hold escape press hot key to scan for next scan exact value let go of escape scan for origional value or alt tab back to cheat engine and search for 00 etc.
Ill do signiture and hook code later and post it up here I might also hook game loop and add sleep
After thats done we can fully simulate mouse and keyboard events even when the game is minimized.