guide: debug pwi, find function addresses and offsets, write a bot(c++ code included)

01/28/2010 18:03 FunkU#31
Do you mean this function?
When I set breakpoint on it and click "Trade and repair service" in NPC dialogue box the game freezes. So that means that this function is related with clicking the dialogue options. It looks like there's many subfunctions of this function. Maybe we need to call only one of subfunctions? And there's too many parameters to send in this function. I don't even imagine where to start search. (
01/28/2010 18:47 AlexGD#32
Yeap, you right, exactly this function. Also in Rus branch I write address of subfunction that called when pressed dialog line. But all starts here: 0050E7E0
01/28/2010 19:33 vuduy#33
You guys are working with the branches and twigs. It will be nightmare to get all those addresses again whenever a new client updates.

Go to the source. Everything will eventually be sent to the server. Find the function that sends the "op codes" to the server and work from there. If the client updates, you only have to update this one function address.

The nice thing about PWE games is that they use the same core server engine... all games have the same op codes. That is why my bot can be used across all PWE games. Only one thing needs to be updated for each game version, and that is the "send function" address.
01/29/2010 00:06 toxic6666#34
i assume you guys found the same function as i did, it looks - pretty - similar. if so, this function seems to be called to notify a control that some kind of mouse action has happened that needs some kind of reaction (some kind of window proc for pw controls i assume). if you bp this function and trace to the caller, you should see, that this function is being called via

call dword ptr [esi+0x10]

it looks like theres a different function for each kind of control (which makes sense, since different controls need different logics). the block you see in your disassembly right now seems only to be executed, if some kind of reaction is needed, e.g. the left mouse button has been released over a control (action takes place, once the button has been released, not clicked). the strange thing is, this block of code is not executed for some buttons, but it is executed for most controls, that just received a left mouse click release. the function your in right now (the function that contains the code block that calls the control window proc) has 5 params. i didnt investigate it too much, but here are some observations.

the following values are all hex:

param1: whatever
param2: mouse button release state: 200: none, 201: left button down, 202: left button release, 204: right button down, 205: right button release
param3: mouse button down state: 0: no button down, 1: left button down, 2: right button down
param4: mouse coords (stored as 2 words, 1 for x, 1 for y coord)
param5: whatever

you can further trace back to the window proc to see the code flow and to know more about the unknown params.

the "control window proc" will have 3 params. param1 will be the mouse button down state (which will most likely be 0, because it is most likely called, when the left mouse button has been released). param2 will be the mouse coords (probably relative to the controls upper left corner).


maybe this helps a bit. but it looks like its not an easy task and needs a pretty good amount of time of tracing that i dont want to invest right now for a game im not really playing anymore, sorry.


when tracing back from these funcs to the dialog proc, you will most likely find out how to get control objects from a dialog as well as their layouts in memory. inside the control procs, you might find a way to emulate something like "tell the control to do this and that", but it looks like these kind of gui actions are all based on mouse click messages, which are handled seperately by the corresponding control proc to find out how to react on them. but maybe i didnt find the best place to start tracing from, and im just telling bullcrap, but this is how it looks like to me :x




@vuduy:

if you only have to update the send function, i guess you keep your own lists for mobs, items, etc.? if so, this is extremely nice. i tried to analyze decrypted (recv) packets a while ago, but i got too frustrated after a while because i got flooded by different packet types, so i stopped :x
01/29/2010 01:51 vuduy#35
lists for npcs, players, resources have never changed through updates. The static base address does. You only need to update this and the "send" function. Once in awhile, the npc/player structure changes if there's new content involved. Other than that, it's easy to update.

Don't go all the way to the encrypted packets... these are nightmares. Intercept before they are encrypted. Basically the flow is as follow:

user inputs -> command processing -> prepare packet to send -> encrypt packet -> send

What you guys are working on is at "command processing". Every button click, dialog selection, etc... has its own "command processing"; there are a lot... over 100s. But eventually, they all go to the next step "preparing packet to send". If you just work with this, then you can do everything through one function.
01/29/2010 02:14 toxic6666#36
i just got it a little wrong, i thought all you really need to do is just update the send func, which would have implied that you had to maintain your own lists.

your right, packets are pretty handy for some funcs, but i had some probs on specific tasks with packets. e.g. "moveto(x,y,z)". if i clicked somewhere to walk there, my client didnt send a "moveto(x,y,z)" packet, instead it walked there by computing the coords client-side and sending update pos packets after a specific distance and a stop packet when the target pos has been reached. this would imply that i had to compute the route and the coords myself and send update pos packets, which would be like extremely hard. this problem would also be concerning attacking. if i attacked a mob, my client checked if the target is in range, if yes, it would send an attack packet, else it would queue 2 actions, first walk into range (like moving above) and then send the attack packet. the problem was, if im not in range, i dont know how to walk there via packets. skills were a little different. no matter if i was in range or not, it would send a castspell/skill packet, which would make me move into range and cast. anyhow, i couldnt manage to do a moveto(x,y,z) via packets. did you manage to do it?
01/29/2010 03:26 vuduy#37
Moving opcodes start with "0x70 00" to indicate start moving. Then after this packet is sent, the coordinate opcodes are sent. "00 00 x2((float x) (float z) (float y)) (int timestamp) (word count)", size of opcodes is 33 bytes.

If movement is stopped, a packet of "07 00 (float x) (float z) (float y) (int timestamp) (word count)", size is 22 bytes, is sent.

Or you can just use action structure to move by memory writing (no need for injection); you can also use action structure to "queue" skill so that it gets in range before using the skill. I already posted about all of these in another thread.

What are opcodes good for?
- buying/selling
- taking and handing in quests
- refines
- pickup (for filtering + remote looting)
- interacting with NPC
- selecting targets
- regular attack
- using item
- using ground item (pickup resources)
- using skill (self-cast skill) - for targeted skills, better to use action structure
- pets command
- teleporting <<< these are actually "quests"
- and many more...

EDIT: So yes, it is possible to speed hack by a little bit (not too much), by writing packets directly. The only downside is that you lose the client-side moving animation; it will look like you are teleporting.
01/29/2010 08:49 muchenberg#38
vuduy, so and when you use such a "speedhack", you dont get a pushback by server sync?
01/29/2010 13:22 toxic6666#39
@vuduy:

the problem with moving via packets only for me are not the packets structures themselves, but how to find out y at (x,z). if you dont let the client calculate the coords, its kind of hard to find out the correct y value at pos (x,z). this would be much harder than to just find out how to let the client do the moving.
01/29/2010 13:54 sup3rTrad3r#40
i need help with PEt HP offsets i found the address in hex is 00000ff8 for the current version of PWI when i add it to smurfin it doesnt read pet hp so i wanted to know if they changed anything related to pet hp offsets ?? Afcourse i am converting it into decimal its 4088.
01/29/2010 14:29 AlexGD#41
@Vuduy

17 of 18 needed pointers my program find automatically in exe by several seconds ;) Now I search manually only for BaseAddress.
01/29/2010 17:01 AlexGD#42
@Toxic
If I right understand you - you are working with wallhack now. Main problem with it - rollback of char after synchronisation with server.

So, what I have to say. I works with flyhack. Yeap, noway. Swimhack - noway too. But jumphack is works. Strange way, but works.

But I have some difficulties with full realization of jump hack. So, let me describe on example.

1. My char stay in the dangeon.
2. I inject jump 3 times with ~sleep(100) between jumps (pers is jumping 3 times. synchronization no time to return pers to initial altitude)
3. I move pers in needed direction and wait 250ms (pers falldown WITHOUT sinchronization and move).
I do 2 and 3 in cycle. All go fairly some time. But after 15-20 seconds of this "waving" - client crash. I understand that something I do wrong (

Code of injection:

Code:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~ Jump inject (c) dwar
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
procedure JumpCall(aPParams: PParams); stdcall;
var
  BaseCallAddress: DWORD;
  JumpCall: Pointer;
begin
  BaseCallAddress := aPParams^.Param0;
  JumpCall := Pointer(aPParams^.Param7);
  asm
    pushad
      push  $0
      push  $C8
      push  $1
      push  $3F800000
      push  $4
      mov   esi, dword ptr [BaseCallAddress]
      mov   esi, dword ptr [esi+$1C]
      mov   esi, dword ptr [esi+$20]
      mov   ecx, esi
      mov   eax, $41200000
      mov   dword ptr[ecx+$Bd8], $1
      mov   dword ptr[ecx+$B88], eax
      mov   dword ptr[ecx+$BE0], eax
      mov   dword ptr[ecx+$B64], $0
      mov   dword ptr[ecx+$B80], $0
      mov   dword ptr[ecx+$B7C], $0
      mov   dword ptr[ecx+$B78], $0
      call  JumpCall
    popad
  end
  ;
end;
Do you have any suggetions how to prevent client craching? Or at least - why it crashes...
01/29/2010 17:37 vuduy#43
Quote:
Originally Posted by toxic6666 View Post
@vuduy:

the problem with moving via packets only for me are not the packets structures themselves, but how to find out y at (x,z). if you dont let the client calculate the coords, its kind of hard to find out the correct y value at pos (x,z). this would be much harder than to just find out how to let the client do the moving.
To calculate the x,y,z is very easy. Basically, you have your current x,y,z; you calculate the vector using the direction facing (from player structure) with the moving speed to calculate the new x,y,z. As I said, you don't have much to gain via packets moving; and you lose the normal moving animation as well. It is much easier to move by memory writing to the action structure and let the client takes care of it.

For me, I use the "auto routing" function in my bot for all movements. In JD, there's a feature "auto routing" that can calculate the path to a destination around obstacles. For all other functions, I use the "send" function.
01/29/2010 23:52 toxic6666#44
@vuduy:

damn, is it really that easy? i thought that method would just give a "measurement" of the new y coord. i always thought you calculate (x,z) the way you explained and then need to look up y via terraindata.


@AlexGD:

i never called Jump that way and i dont know what these offsets you are accessing in your code would be on my pw version. but it looks like your overwriting some variables that are used during the whole movement(note that jumping is also "moving") and collision detection process that i came across when making a wallhack. i just have a theory, but some more info would be good. what kind of exception occurs when your client crashes. i couldnt get jump hack to work on my version. it uses the same principle on pos updates as walking, which means i got pushbacks as well.
since you alter some variables that are needed during the movement and collision detection process, it might be possible that your overwriting these variables after they have been set to the correct values. but if they are still needed for further processing, they will have wrong values that might make the client crash. maybe something like that is happening. i guess the code your using is not just a ripoff of the original jump function? your writing to these variables to avoid the 2 jumps limit? if so, i guess

mov dword ptr[ecx+$Bd8], $1

writes 1 to the current jump state?
maybe the offsets your using are outdated? did you try to patch the instruction that checks the current jump state and just call the original jump function instead?
from what i can tell, your function looks a bit "dangerous", at least if you inject this code while your char pos is being updated (e.g. while jumping or moving)
01/29/2010 23:54 diablokoaiua#45
To be honest.. This is a oldschool way.. You can use program named offset finder now.. Use that .. way faster.. Ofcourse you could use this but.. Just for you to know!