Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Perfect World > PW Hacks, Bots, Cheats, Exploits
You last visited: Today at 16:11

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



PWI - Real Chat Filters - Remove red / system spam etc. AutoIt Code included

Discussion on PWI - Real Chat Filters - Remove red / system spam etc. AutoIt Code included within the PW Hacks, Bots, Cheats, Exploits forum part of the Perfect World category.

Reply
 
Old   #1
 
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
PWI / Rus / Indo - Real Chat Filters - Remove red spam etc. AutoIt Code included

EDIT: Should now work on PWI, PW Russia and Indo
Well, here it is lol... I'm too tired to do the writeup right now, but I'll try to update this post tomorrow with ins and outs of how it was all done ^_^

I figure some people will probably want it straight away due to the crazy red spam issue on PWI since the last update, hence I'm posting the code now.

A quick overview:
  • Can choose which client to attach to
  • Patches the client so that the filter overrides don't reset your filter settings when you open the game settings console
  • Can turn any chat type on or off on any chat region tab, i.e., in the image below you can see that world chat and system chat are disabled in the common chat region
  • Automatically finds all offsets required, so might be update proof :P
  • Might work on other versions of PW - I'm not sure yet and this will require testing. Please give feedback if it works on your version
I'll explain more tomorrow... All you need to know for now is:
  • Run your PWI client as normal and log in (must be logged in for the clients to be detected)
  • Run the PW_ChatFilter.au3 file from AutoIt, or alternatively, compile it first
  • (I didn't upload it as an exe because it uses some injections and therefore might throw some false positives with some antivirus programs... I can't be arsed to deal with people QQing that it has some virus, hence the code is here for all to see)
  • When you run the program, it should populate the dropdown list at the top with the character names of all your opened clients
  • Choose the one you want to fiddle with and hit 'Attach'
  • Now hit the 'Patch' button. It won't work without this (I'll probably make this automatic when attaching at a later point... can't remember why I did it like this now lol)
  • After a couple of seconds, it should hopefully tell you that it's successfully attached.
  • Now, set whatever filters you want on or off and hit the 'Apply' button
  • Yay! No more red spam!

(By the way, that red text in the screenshot showing the last login IP seems to not come under any of the normal filter categories)

As a side note, I have a feeling (not confirmed) that the last filter option (the third 'other' option) might be a Horn filter hehe.



EDIT:
Ok, finally got some time to explain the process of working this program out
I don't claim to be a great hacker or anything, but I like to explain how I do things and give an insight into my thought process when doing this sort of thing, in the hope that it might teach people something they might not have known before, or to think about things in a slightly different way in their approach to reverse engineering.
I'm sure most people will probably just scroll down and get the files and use them, but for those interested, here goes :P


So, the first thing we need to do is find out what changes when we alter the filters using the in-game settings -> game tab interface, so for this, we fire up cheat engine and attach it to the elementclient.exe process.
Now, there are 6 chat regions (common, squad, faction, etc) and in each region, there are 11 filter options (normal, world, faction, squad, etc). So intuition might tell us that there is an array of 66 values somewhere which store these filter settings. Being that there are so many, intuition might also tell us that they could be stored as bytes for efficiency (well, booleans, i.e., 1 or 0) and that a 1 would mean the filter is enabled and a 0 would mean it's disabled.
So, once CE is attached and we have the game settings tab open, make sure the 'Normal' filter is enabled in the 'Common' chat region and do a memory search in CE for a byte with a value of 1 (see pic 1).



The search will find several million results, although had we started by searching for a 0 there would have been even more... hence we search for non-zero values first.
Now, disable the 'Normal' filter and change the value in the CE search to 0 then hit next scan. Now we just have a few thousand results. Leave the search value as 0 then hit 'next scan' a few more times - The number of results will pretty much be halved.
Now, re-enable the filter and search for 1 again. Rinse and repeat this process until we only have a few results. I managed to get down to 2 results which both clearly changed each time I clicked on the filter checkbox.
Take the lowest address and right click -> browse memory region.
Now we can modify a few different filters in-game and see some bytes changing near the address we found.
So, we know we've found a memory region which reflects the chat filters, however you may notice that they do not appear to be in the same order that they appear in-game.



All is not lost... Those of you who read my might notice that they do match the order described there...
Code:
messageTypes    (see chatObj->msgScope)
    Local            // 0
    World            // 1
    Squad            // 2
    Faction          // 3
    Whisper          // 4
    5                // 5
    6                // 6
    Trade            // 7
    Notification     // 8
    System           // 9
    Gen. Info        // 0xa
    Local info(b)    // 0xb
    Local info(c)    // 0xc
This also indicates that there are not 11 filters per region as previously expected, but 13 - The final two are hidden. Merkada has confirmed that the 13th filter value is actually for horns... Not so sure about the 12th.
So, we actually have 13 * 6 = 78 filters and the offsets from here for each chat region are:
Code:
Common -> Normal =     0
Squad -> Normal =     0xD
Faction -> Normal =     0x1A
Whisper -> Normal =     0x27
Trade -> Normal =     0x34
General -> Normal =     0x41
So, now we know we've found something associated with the chat filters, lets try something...
In the 'browse memory region' window, adjust one of the values for which we know which filter it applies to, i.e., the common -> normal filter. Change the value in CE and you will notice it doesn't change in game. However, if you change the value, then click on a different chat region (i.e., squad) then click back on 'Common' you'll see it has changed! If we adjust the next byte after the 'Normal' chat filter (world chat) then switch regions, then switch back to common, we'll see that the world chat filter is unchecked. You can now click apply, and any world chat messages will be removed from the in-game chat window. Yay! Seems we're almost there huh? Well, not quite.
Adjust the world chat filter to 0 (off), switch regions, switch back, click apply... World chat disappears. Awesome... Now click confirm, or close the game settings interface.
Now open the game settings interface again. Bugger... World chat is enabled again. All the previous world chat messages haven't been restored in the chat window though, but any subsequent messages will be displayed.
So, we now know that there must be another storage area for these filters.
There are a couple of ways we could find this... The first way is to do a search for an array of bytes that matches the array we've already found (do this after applying any filters you've adjusted).
Alternatively (and in my opinion, preferrably) we can find out what writes to this address.

For this, I will use OllyDbg simply because the disassembly is more readable and I can copy and paste code from it more easily :P

So, fire up OllyDbg and attach it to the PW client (you will need to detach CE from the process if you have previously attached it). Once Olly has attached, press F9 to unpause the client.
In the "Executable modules" list (Alt+E) double click "ElementClient" twice to take us to the elementclient module.
Now click in the memory dump area then hit Ctrl+G (Goto address) and type in the address of the memory location we found in CE which stores the filter byte for Common->Normal.
Now right click on this address and set a memory breakpoint on write access (see pic_3 - Depending on the version of Olly you have, this interface might look slightly different)



Now open the game settings interface and we should get a hit at:
Code:
00569167 - 8D 85 1C020000  - lea eax,[ebp+0000021C]
If we examine the code around here, we can see this:
Code:
00569151  |.  8B40 18       MOV EAX,DWORD PTR DS:[EAX+18]    ; settings base address
00569154  |.  8DBD 14020000 LEA EDI,[EBP+214]
0056915A  |.  B9 3A000000   MOV ECX,3A                ; Number of integers to copy
0056915F  |.  B2 01         MOV DL,1
00569161  |.  8DB0 55010000 LEA ESI,[EAX+155]            ; ** static filters offset **
00569167  |.  8D85 1C020000 LEA EAX,[EBP+21C]            ; points to the filters byte array we found
0056916D  |.  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS
If we now remove our memory write breakpoint and run the client again, then set a normal breakpoint at the line:
Code:
00569151  |.  8B40 18       MOV EAX,DWORD PTR DS:[EAX+18]    ; settings base address
Then open the game settings interface again, we'll see that EAX contains the value of our baseCall static offset ( &baseCall = 0xAFF144, *baseCall = AFF7E8).
Just for your information, the code above is basically like a block memory copy, which copies our non-static filter values to an area of memory that actually contains the static game settings.

So, from these few lines of code, we can get our complete offset list for the static filters offset, which is:
Code:
[[[baseCall]+0x18]+0x155]
Add this to your CE offset list and set the type to 'Array of bytes' and set the size to 78 bytes (pic 4)



You can also add the address we found earlier for the non-static filters in the same format, i.e., array of 78 bytes so we can compare side by side (pic 5)



But wait a minute... They don't seem to quite correlate. The static ones seem to be offset by 4 bytes, so what are these first 4 bytes? Well if we examine the 4 bytes of memory just before our non-static filters, and then change the 'Basic' settings in the game tab, then hit apply, we'll see that these bytes contain the boolean values for those four checkboxes (Zoom, A,D Keys, Squad Invites, Trade).
We can also find some of our other settings around this area, such as the autoreply status and message, which is somewhere just after our filters.

So to get to our chat filters offset, add 4 to the final offset we had before, i.e.,
Code:
[[[baseCall]+0x18]+0x159]
Now our two arrays of bytes in CE should be aligned (after setting filters and clicking apply).

We've now established where our filters are statically stored, where they are temporarily stored for the gui, and that the normally 'disabled' filters (world chat, whispers, etc) somehow get adjusted back to default when we reopen the game settings tab after successfully disabling them. So, let's find out what evil witchery keeps forcing us to endure that annoying red and yellow spam...
We know that world chat is one of the filters that gets forced back on, so lets set a memory write breakpoint on this in OllyDbg. I'll save us some time here by mentioning that the static filter isn't specifically modified, but the non static one is - The non-static filters are then bulk copied to the static offsets.
So, the address is our non-static filter base + 1. If you've lost the address of your non-static filters, I'll save some more time here and tell you it's at [[[[[baseCall]+0x18]+0x8]+0x4B0]+0x218] so put the breakpoint one byte above this address (for world chat filter) then open the game settings tab. It will break first where it did last time, so when it hits, hit F9 again to run to the next BP... Which hits a few lines down, here:
Code:
00569186  |.  8895 19020000 MOV BYTE PTR SS:[EBP+219],DL
When you open the game settings tab, what actually happens is something like this:
Static filter settings are copied to the non-static ones (the gui ones)
Some of the non-static ones get forced to different values (i.e., world / system chat)
Non-static filters are copied back to the static ones and the gui is displayed.

So, basically, there is no way we can just modify the filters and have them 'stick' the next time the game settings interface is opened. Bummer, eh? Well this just means we need to do a little patch.
Going back to the code we found a minute ago which modified the world chat filter, below that we can see that a few others get modified too.

Code:
00569186  |.  8895 19020000 MOV BYTE PTR SS:[EBP+219],DL    ; Common -> World On
0056918C  |.  889D 5A020000 MOV BYTE PTR SS:[EBP+25A],BL    ; General -> World off
00569192  |.  889D 62020000 MOV BYTE PTR SS:[EBP+262],BL    ; General -> System off (red)
00569198  |.  889D 5D020000 MOV BYTE PTR SS:[EBP+25D],BL    ; General -> Whisper off
0056919E  |.  889D 65020000 MOV BYTE PTR SS:[EBP+265],BL    ; General -> Horn? off
Yeah... the 'General' chat region sounds like heaven. Unfortunately we're not given it as an option in the actual game chat regions lol.
Now, you might notice that those offsets don't cover any of the normal annoying settings, i.e., red system spam in all the other channels. If we scroll up a little bit in OllyDbg, we can see the culprit for this:

Code:
00569174  |>  8850 05       /MOV BYTE PTR DS:[EAX+5],DL
00569177  |.  8810          |MOV BYTE PTR DS:[EAX],DL
00569179  |.  8850 08       |MOV BYTE PTR DS:[EAX+8],DL
0056917C  |.  83C0 0D       |ADD EAX,0D
0056917F  |.  49            |DEC ECX
00569180  |.^ 75 F2         \JNE SHORT 00569174
This loops through each chat region (hence the ADD EAX, 0D) and sets a few filters. Note that earlier I gave the offset for the non-static filters as [[[[[baseCall]+0x18]+0x8]+0x4B0]+0x218], but a few lines above this loop we can see the line:
Code:
00569167  |.  8D85 1C020000 LEA EAX,[EBP+21C]
So we start at the 5th filter on the Common chat region, which is 'whisper', so this loop above forces some filters on as follows:
Code:
00569174  |>  8850 05       /MOV BYTE PTR DS:[EAX+5],DL        ; Red system
00569177  |.  8810          |MOV BYTE PTR DS:[EAX],DL        ; Whisper
00569179  |.  8850 08       |MOV BYTE PTR DS:[EAX+8],DL        ; Horn? (filter 13 or 0xC)
The only way we can stop these filters being reset every time we open the game settings interface is to apply a patch. In my program, I do the patch on the already opened client, i.e., in the client's program memory rather than patching the actual .exe file... 'cause that would be naughty :P

In my code, I read the client's memory into a big string, then do a string search for this code:
Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00569174  |> /8850 05       /MOV BYTE PTR DS:[EAX+5],DL
00569177  |. |8810          |MOV BYTE PTR DS:[EAX],DL
00569179  |. |8850 08       |MOV BYTE PTR DS:[EAX+8],DL
0056917C  |. |83C0 0D       |ADD EAX,0D
0056917F  |. |49            |DEC ECX
00569180  |.^\75 F2         \JNE SHORT 00569174
00569182  |.  33DB          XOR EBX,EBX
00569184  |.  8BCD          MOV ECX,EBP
00569186  |.  8895 19020000 MOV BYTE PTR SS:[EBP+219],DL
0056918C  |.  889D 5A020000 MOV BYTE PTR SS:[EBP+25A],BL
00569192  |.  889D 62020000 MOV BYTE PTR SS:[EBP+262],BL
00569198  |.  889D 5D020000 MOV BYTE PTR SS:[EBP+25D],BL
0056919E  |.  889D 65020000 MOV BYTE PTR SS:[EBP+265],BL
And then overwrite it with this:
Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00569174  |> /90            /NOP
00569175  |. |90            |NOP
00569176  |. |90            |NOP
00569177  |. |90            |NOP
00569178  |. |90            |NOP
00569179  |. |90            |NOP
0056917A  |. |90            |NOP
0056917B  |. |90            |NOP
0056917C  |. |83C0 0D       |ADD EAX,0D
0056917F  |. |49            |DEC ECX
00569180  |.^\75 F2         \JNE SHORT 00569174
00569182  |.  33DB          XOR EBX,EBX
00569184  |.  8BCD          MOV ECX,EBP
00569186  |.  90            NOP
00569187  |.  90            NOP
00569188  |.  90            NOP
00569189  |.  90            NOP
0056918A  |.  90            NOP
0056918B  |.  90            NOP
0056918C  |.  90            NOP
0056918D  |.  90            NOP
0056918E  |.  90            NOP
0056918F  |.  90            NOP
00569190  |.  90            NOP
00569191  |.  90            NOP
00569192  |.  90            NOP
00569193  |.  90            NOP
00569194  |.  90            NOP
00569195  |.  90            NOP
00569196  |.  90            NOP
00569197  |.  90            NOP
00569198  |.  90            NOP
00569199  |.  90            NOP
0056919A  |.  90            NOP
0056919B  |.  90            NOP
0056919C  |.  90            NOP
0056919D  |.  90            NOP
0056919E  |.  90            NOP
0056919F  |.  90            NOP
005691A0  |.  90            NOP
005691A1  |.  90            NOP
005691A2  |.  90            NOP
005691A3  |.  90            NOP
If you run my code (at the end of this guide) and attach to your client, then hit the patch button, you'll see that any changes you make now do not get changed back when you open the game settings tab. Yay!

So it would seem we're almost done, however, just updating the filter values in memory doesn't apply the filters to the contents of the in game chat box, i.e., say for example you filtered out world chat, the yellow text won't disappear from the current chat box although any subsequent world chat type messages will not be shown. The only way to clear previous messages in the chat box is to hit the apply button in the game filters interface. So, we need to do this automatically with some magic ^_^

I had some trouble finding the specific function in the client which actually propagates the changes to the chat box, so I took a slightly different approach and did a few injections into the client's function that handles all the button clicks within the gui menu system.

Because of the thing I mentioned earlier, whereby the filters are read from static memory into the gui memory, then back to static memory, the solution I came up with was to do the following:
Close the game settings interface if it's already open
Write your preferred filter settings to the static filter array
Call the gui control function to open the game settings interface (this syncs the static filters to the non-static ones, which are used when changes are applied)
Call the gui control function again to simulate hitting the "apply" button
Close the game settings interface

This actually often all happens so quickly that you won't even see the window open and close :P

Finding the gui control function has actually been described before in toxic6666's awesome thread on - If you're new to fiddling with PW then I highly recommend reading this thread.
However, for continuity, I'll describe here how to actually find this function (termed 'guiCommand()' by toxic6666)
(also updated)
toxic6666's method involved using w32dasm to find a string constant, however, this program is actually pretty difficult to find these days and most downloads you might find for it tend to have infections and/or be from 'questionable' sites. Fortunately, we don't need w32dasm for this as we can do it in OllyDbg.
From within OllyDgb, right click somewhere within the code window, i.e., actually click on some line of code then choose 'Search for' -> 'All referenced strings'
This should pop up a window with a list of all the string constants used in the client. Right click in this window and choose 'Search for text' (or if you're using the newer version of Olly, just hit Ctrl+F)
Search for "Dlg_Building" - there should only be one occurrence of it. When you find it, double click this line and it should take you to the code. At this point, you could open up IDA, enter the address that you just landed at in Olly then find the start of the function. However, the code here isn't too messy so you can just scroll up a few pages until you find a bunch of NOPS. The start of the function is the first line of code after these NOPS. In the current PWI version, this is at 0x604B30 and looks like this:
Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00604B30  /.  53            PUSH EBX
00604B31  |.  8B5C24 08     MOV EBX,DWORD PTR SS:[ARG.1]
00604B35  |.  56            PUSH ESI
00604B36  |.  8B7424 10     MOV ESI,DWORD PTR SS:[ARG.2]
00604B3A  |.  57            PUSH EDI
00604B3B  |.  56            PUSH ESI                                 ; /Arg2 => [ARG.2]
00604B3C  |.  53            PUSH EBX                                 ; |Arg1 => [ARG.1]
00604B3D  |.  E8 EE221E00   CALL 007E6E30                            ; \ElementClient.007E6E30
00604B42  |.  84C0          TEST AL,AL
00604B44  |.  74 24         JE SHORT 00604B6A
The 2nd and 4th instructions here will load the gui command and the gui object pointer respectively. So, set a breakpoint at the PUSH EDI line (5th line shown above) then click the apply button in the game settings window.
When the BP hits, we'll see a value in ESI which will be the gui object and a string reference in EBX which will be the command. Fortunately, the commands used for the gui are quite reader friendly lol... The command for the apply button is simply a text string "apply".
If you do this a few times for some other things, i.e., click the game settings tab or click the close (X) button you'll get the command strings for these too. These are "gamesetting" and "Btn_Close" respectively.

Make a note of the value in ESI when you get into this function after hitting the apply button from within the game settings tab.

I won't go into detail about finding the guiBase pointers here as I think toxic6666 explained it all pretty well in his thread. He also explains how to get the offsets for the gui object for this function too, so I'll skip that part and just state that the offset we need is:
Code:
[[[[[baseCall]+0x1C]+0x18]+0x8]+0x4B0]
This is the gamesettings tab object and thankfully, all the commands we need to send are sent to this object.
Basically, this is the pseudo code for what we want to do now...
Assuming the guiCommand() function prototype is something like this:
Code:
void guiCommand(string * command, guiObjectPointer)
We would do...
Code:
If gameSettingsTab is open
{
    guiCommand("Btn_Close", gamesettingTabObject)    // close the tab
    Wait until it's closed
}
setChatFilters()    // Write our preferred filters to the static filter array
guiCommand("gamesetting", gamesettingTabObject)        // Open the tab again
guiCommand("apply", gamesettingTabObject)        // Hit apply
guiCommand("Btn_Close", gamesettingTabObject)        // close the tab again
As for how to actually inject into this function, just look at the guiCommand() function in my code - I think this explains it

I think I have explained all the relevant parts of the code... The other bits are mostly just fancy trimmings hehe. As for the offset finding stuff, that's kind of beyond the scope of this guide, but I'll be posting a handy tool I made to aid this very time consuming process... maybe tonight.

That's all folks, hope you're not all bored to sleep now!



So, here's the code - You need all three files plus NomadMemory (you should all have this)

PW_ChatFilter.au3 (thanks to t212 for multiclient fix)

filterOffsets.au3

MultiAssocArray.au3 (This is awesome! Found it )


Enjoy!!
dumbfck is offline  
Thanks
20 Users
Old 09/02/2011, 03:01   #2
 
elite*gold: 0
Join Date: May 2010
Posts: 220
Received Thanks: 203
Thumbs up

WOW, i compile it and it works...who wonder it!
dont know what should i say













@all:
amineurin is offline  
Thanks
1 User
Old 09/02/2011, 20:03   #3
 
elite*gold: 0
Join Date: Mar 2011
Posts: 44
Received Thanks: 48
Quote:
Originally Posted by dumbfck View Post
As a side note, I have a feeling (not confirmed) that the last filter option (the third 'other' option) might be a Horn filter hehe.
yep last "other" is horn, and probably id 11 "2nd other" can be GM talk, but not confirmed, never see GM talk so they write system (id 9) msgs or id 11
here is rip from my source:
Code:
		If $array[$i + 1][0] = 0 Then
			$array[$i + 1][0] = "Normal"
		ElseIf $array[$i + 1][0] = 1 Then
			$array[$i + 1][0] = "World"
		ElseIf $array[$i + 1][0] = 2 Then
			$array[$i + 1][0] = "Squad"
		ElseIf $array[$i + 1][0] = 3 Then
			$array[$i + 1][0] = "Faction"
		ElseIf $array[$i + 1][0] = 4 Then
			$array[$i + 1][0] = "Whisper"
		ElseIf $array[$i + 1][0] = 5 Then
			$array[$i + 1][0] = "Damage"
		ElseIf $array[$i + 1][0] = 6 Then
			$array[$i + 1][0] = "Combat"
		ElseIf $array[$i + 1][0] = 7 Then
			$array[$i + 1][0] = "Trade"
		ElseIf $array[$i + 1][0] = 8 Then
			$array[$i + 1][0] = "Notification"
		ElseIf $array[$i + 1][0] = 9 Then
			$array[$i + 1][0] = "System"
		ElseIf $array[$i + 1][0] = 10 Then
			$array[$i + 1][0] = "Other"
		ElseIf $array[$i + 1][0] = 11 Then
			$array[$i + 1][0] = "???"
		ElseIf $array[$i + 1][0] = 12 Then
			$array[$i + 1][0] = "Horn"
		EndIf
edit: btw nice to see how u change your opinion about AutoIT :P
Merkada is offline  
Thanks
1 User
Old 09/02/2011, 20:57   #4
 
Interest07's Avatar
 
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
****, so many regexps, I feel sorry for you

Awesome job yet again

Love seeing all the open source stuff Looking forward to the writeup as usual
Interest07 is offline  
Old 09/03/2011, 03:13   #5
 
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
Quote:
Originally Posted by Merkada View Post
yep last "other" is horn, and probably id 11 "2nd other" can be GM talk, but not confirmed, never see GM talk so they write system (id 9) msgs or id 11
Thanks for confirming it And yeah, the other "other" option might well be GM, since it is a hidden option normally and is set to 'on'... Although last time I spoke to a GM they used normal whispers.
Quote:
Originally Posted by Merkada View Post
btw nice to see how u change your opinion about AutoIT :P
I still don't like it, but I like to challenge myself :P
One of the major advantages I've just realised recently is that you can post code in AutoIt here, and most people can compile it, so there is no need to post the compiled .exe which, when using injections, invariably pisses off people's antivirus programs.
Also the whole reading a file to a string thing is quite nice and I am yet to find such a straightforward solution in C#, so offset searching is pretty sweet in AutoIt. (My extremely similar version in C# takes almost 4 times as long :O)

Quote:
Originally Posted by Interest07 View Post
Damn, so many regexps, I feel sorry for you
Yep, you might have noticed in the code that there was one offset that just wasn't practical to get from the client, so I kinda botched it a bit >.>.
Aside from that, I love regex's but I got so pissed off with it I actually made a tool which makes it a bit easier... I shall be posting the details on here soon... I think it has potential to be awesome hehe.

Hint:
Code:
"^[0-9A-F]{8}[\^|\.\>\s\\\/\$]+(([0-9A-F]{2,8}):)?([0-9A-F]{2,8})?\s?([0-9A-F]{8})?([0-9A-F]{4})?([0-9A-F]{2})?[\s:]([0-9A-F]{8})?([0-9A-F]{4})?([0-9A-F]{2})?\s+(.+)"
Nice hint, eh?
Quote:
Originally Posted by Interest07 View Post
Awesome job yet again
Love seeing all the open source stuff Looking forward to the writeup as usual
Thank you kindly, sir
There's been a lot of alcohol and drums on guitar hero tonight, and lots of work to do over the weekend, but hopefully will post the details fairly soon
dumbfck is offline  
Old 09/03/2011, 07:17   #6
 
Interest07's Avatar
 
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
Quote:
Originally Posted by dumbfck View Post
I still don't like it, but I like to challenge myself :P
One of the major advantages I've just realised recently is that you can post code in AutoIt here, and most people can compile it, so there is no need to post the compiled .exe which, when using injections, invariably pisses off people's antivirus programs.
That's definitely true. It's much easier to copy paste too, since it's all just stuck in one huge file generally (Perhaps with one or two utility files I guess). For smaller tools (codewise I mean) like the ones you're producing it is effective enough.

Quote:

Also the whole reading a file to a string thing is quite nice and I am yet to find such a straightforward solution in C#, so offset searching is pretty sweet in AutoIt. (My extremely similar version in C# takes almost 4 times as long :O)
While I admit regexps aren't the most straightforward in C# (escaping every single byte with \x is a pain and I simply hate using the bloody things), I don't find them to be slow at all. I'd even say time isn't really an issue at all as far as I've noticed (unless you were to regexp the offset every time you wish to use said offset of course ).

Quote:

Yep, you might have noticed in the code that there was one offset that just wasn't practical to get from the client, so I kinda botched it a bit >.>.
Aside from that, I love regex's but I got so pissed off with it I actually made a tool which makes it a bit easier... I shall be posting the details on here soon... I think it has potential to be awesome hehe.

Hint:
Code:
"^[0-9A-F]{8}[\^|\.\>\s\\\/\$]+(([0-9A-F]{2,8}):)?([0-9A-F]{2,8})?\s?([0-9A-F]{8})?([0-9A-F]{4})?([0-9A-F]{2})?[\s:]([0-9A-F]{8})?([0-9A-F]{4})?([0-9A-F]{2})?\s+(.+)"
Nice hint, eh?
lmao, I'd rather stay away from regexps completely (besides for addresses), they're nasty as shows in your 'hint'

offsets are usually easy enough to change with simple statements like "UPDATE pwi_offsets SET value = value + 0x4 WHERE value > 0xC40" or whatever. Substitute that code with whatever you need for how you store your offsets of course Then again, for real public use you need to bloody offset finders or you get your daily dosage of moaning at every patch

Quote:

Thank you kindly, sir
There's been a lot of alcohol and drums on guitar hero tonight, and lots of work to do over the weekend, but hopefully will post the details fairly soon
I've personally always been bad at GUI related stuff (even programming it myself) so I always find the things you produce impressive
Hope you have a fun weekend without halucinations about regexps
Interest07 is offline  
Old 09/04/2011, 23:11   #7
 
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
Updated the first post with all the gruesome details
dumbfck is offline  
Thanks
3 Users
Old 09/07/2011, 12:35   #8
 
Interest07's Avatar
 
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
Since you seem to be quite into the whole GUI bit of the game... I was wondering, do you happen to know how to figure out the x, y coords on screen of items in your inventory (and whether or not they are actually visible, in the case of inventories with scroll bar).

I'm working on integrating some little tools into the client via dll injection like this:



and kinda want to be able to drag for example a potion to a slot to indicate i want to use that potion type. Or perhaps something similar with skills and such. I might post the source code for this later if there's any interest.
Interest07 is offline  
Old 09/07/2011, 15:09   #9
 
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
Ooooh have you coded that in, or just photoshopped that for now? :O
That looks awesome hehe.

I don't know of a way to get the x,y coords based on the actual item as such, but one way you could do it is to read the position of the inventory window relative to the screen

Inventory window object = [[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]
Inventory window X pos = [[[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]+0x98]
Inventory window Y pos = [[[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]+0x9C]
Inv Window Open flag = [[[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]+0x90]

Then you could do a calculation.

Horizontal distance from the left side of the inventory window the left side of the first inventory item = 28 pixels

Vertical distance from top of inventory window to top of first item inventory item = 314 pixels

Inventory icons = 32 x 32 pixels
Horizontal spacing between inventory icons = 1 pixel
Vertical spacing between inventory icons = 2 pixels

So from those values you could calculate the bounds of each element in the inventory something like:
Code:
for i = 0 to maxSlots
{
    boxes[i][left] = 28 + (i % 8) * (iconWidth + horizSpacing)
    boxes[i][top] = 314 + (int)(i / 8) * (iconHeight + vertSpacing)
}
to get the positions relative to the inventory window, then add the window x,y to get the positions relative to the game window.

As for whether they are visible, I'd suggest finding the offsets that determine whether you are in scrolled or docked mode and if you're in scrolled mode, perhaps try to find where the value of the scrollbar position is stored and do a calculation from that.
I had just started looking for the scrolled / docked / scrollbar offsets but I ran out of lunch break :P
Although I think at one point when changing the scrollbar, I think I did glance upon a changing list of item objects although I didn't get time to investigate.


If you're doing GUI based stuff, here are a few other offsets you will undoubtedly find useful:

guiBase0 = [[[baseCall]+0x1C]+0x18]
guiBase1 = [[[[baseCall]+0x1C]+0x18]+0x8]
guiHoverOuterObj = [[[[baseCall]+0x1C]+0x18]+0x244]
guiHoverInnerObj = [[[[baseCall]+0x1C]+0x18]+0x248]

Those last two are particularly useful for finding gui object pointers. Just hover over them and read off the values.
The guiHoverInnerObj shows the object pointer for controls within gui windows / objects.
Hover over your inventory items and it looks like it actually returns the item objects? I might be wrong and again I didn't have time to investigate further.

Hope this helps ^^
dumbfck is offline  
Old 09/07/2011, 18:02   #10
 
Interest07's Avatar
 
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
Wow, that certainly looks promising
I have in fact coded the window above in using a D3D8 endscene hook . The dll loads the images in separately though, so i dont use them directly from the game files. Im on my phone right now, but ill definitely have a look at what you posted when i get home, thanks!

Edit; i currently intercept Windows messages to detect whether a user clicked a button but it might be hard to prevent qn item to fall on the ground or staying stuck under the cursor unless i find. The pointer to the object currently. being dragged so i can null it somehow
Interest07 is offline  
Old 09/07/2011, 19:41   #11
 
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
As for the accidental item dropping thing, perhaps you could inject an escape key? If you drag an item out of your inventory and hit esc it cancels the drag
Or, I wonder if it might be possible to see how the mechanism works when, for example you drag an item into another window such as when you drag an item into the slot for refining / imbuing / manufacturing?

In fact I just had a look and it seems if you drag an inventory item onto any other gui object and release the mouse, it returns it to your inventory. If guiHoverInnerObj != 0 then maybe it does some other trickery to drop it there.
Perhaps it simply checks if guiHoverOuterObj == 0, so if you can make your interface seem like a real in game interface, you might be in luck :P
Glass is always half full eh?

That endscene stuff sounds awesome btw. I'd have no idea where to even start with something like that!
dumbfck is offline  
Old 09/07/2011, 20:24   #12
 
Interest07's Avatar
 
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
lmao, I never realised the escape key did that XD

thanks for that :O

That oughta simplify this

I'll post the program / source code once I've cleaned it up a little It's my first real work in C++ so I'm prollly lacking a bit in memory management.... Oh and for endscene hooking, there should be plenty of guides available through google. PWI uses D3D8 that's all you need to know, as the method is the same regardless of the game as long you know the version of directx it uses

Quote:
Originally Posted by dumbfck View Post
As for the accidental item dropping thing, perhaps you could inject an escape key? If you drag an item out of your inventory and hit esc it cancels the drag
Or, I wonder if it might be possible to see how the mechanism works when, for example you drag an item into another window such as when you drag an item into the slot for refining / imbuing / manufacturing?

In fact I just had a look and it seems if you drag an inventory item onto any other gui object and release the mouse, it returns it to your inventory. If guiHoverInnerObj != 0 then maybe it does some other trickery to drop it there.
Perhaps it simply checks if guiHoverOuterObj == 0, so if you can make your interface seem like a real in game interface, you might be in luck :P
Glass is always half full eh?

That endscene stuff sounds awesome btw. I'd have no idea where to even start with something like that!
Interest07 is offline  
Old 09/08/2011, 00:58   #13
 
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
Small update:
The scroll / dock offset is: [[[[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]+0x214]+0x78]
This is a single byte, 1 for scroll, 0 for dock.

The scroll bar position is:
[[[[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]+0x214]+0x140]
This is a value between 0-4
0 shows items 0-31
1 shows items 8-39
2 shows items 16-47
3 shows items 24-55
4 shows items 32-63


That should simplify things a bit :P
Seems to be another value that changes too when adjusting the scrollbar. Not sure what these numbers correlate to though.
[[[[[[[baseCall]+0x1C]+0x18]+0x8]+0x404]+0x214]+0x12C]
Position 0 = 0xF = 15d
Position 1 = 0x22 = 34d
Position 2 = 0x35 = 53d
Position 3 = 0x48 = 72d
Position 4 = 0x5C = 92d

Edit: It's the position of the scrolly thingy relative to the top of the control- Prolly not very useful lol
dumbfck is offline  
Old 09/08/2011, 01:27   #14
 
Interest07's Avatar
 
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
Wow, you work fast

I posted my lil tool in a separate thread with source included in case you're interested

I'll see how to integrate proper dragging and dropping items later, shouldn't be too hard
Interest07 is offline  
Old 10/25/2011, 17:55   #15
 
elite*gold: 0
Join Date: Sep 2008
Posts: 24
Received Thanks: 0
hi dumbfck,
I got a little idea about EP buffer for TW.. can we targeting people that whispering to us? if that possible, can you teach me how to make it? Idk how to start from..
hantuman is offline  
Reply


Similar Threads Similar Threads
PWI - Guide for SENDING Chat messages [C# and AutoIt examples included]
09/16/2013 - PW Hacks, Bots, Cheats, Exploits - 32 Replies
Ok, so some time ago I posted a guide for finding the offsets to read chat messages from within the game, which sparked some interest and seems to have proved useful in a couple of bots for PM detection. Around the time I figured that stuff out, I had tried a few times to work out how to send messages too, but never quite got there. Well, it seems taking a short break has helped because I've finally figured it out http://www.elitepvpers.com/forum/images/smilies/bi ggrin.gif Sure,...
PWI - Guide for finding chat message offsets - C# code included
03/23/2013 - PW Hacks, Bots, Cheats, Exploits - 179 Replies
I've been lurking here for a while, so I figured it's time I contributed. I've seen several requests for this around this forum, including from the Prophets, so here goes; my guide to finding and traversing chat messages / objects in PWI. Load up PWI from fresh (don't just relog, physically start a new client because the last chat index isn't reset by a relog) Open CE before actually logging your character in and attach it to the process. Set up a scan ready to do a search for a 4 byte...
Need Help: AutoIt Code to Examine Contents of Chat Window
10/14/2010 - Perfect World - 0 Replies
I'd like to develop some AutoIt code that looks at the chat window and puts up a window or beeps when a user defined string is presented. Can anyone help me out?
[Release]-omtheWorld System (Hack Pack Included)
12/17/2007 - GunZ - 0 Replies
- omtheWorld System + Others Includes: - Weapon Damage. (All Swords, Daggers, Some Guns - Weapon Delay. (All Swords, Daggers, Some Guns - Clip Sizes.



All times are GMT +1. The time now is 16:12.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.