PWI - Guide for finding chat message offsets - C# code included

04/15/2011 12:10 dumbfck#1
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 number between 1 - 20.
Log your character in and wait for at least 1 chat message to appear in the chat box, or post a dummy message in squad chat or something.

Start the first CE scan - You'll get thousands of results.
Wait for another message to appear in the chatbox or type another one yourself, then scan for an increased value.

Keep repeating the increased value scan every time a new chat appears until you're left with 3 green addresses at the top of your list, plus a bunch of junk below them (pic_1)

[Only registered and activated users can see links. Click Here To Register...]

We want the 2nd one, AE962C in my example, so add it to the address list.
Now do a "Find out what accesses this address" scan and wait for another chat to appear in the window. The scan should find a few hits. Choose any of them and click "More information" (pic_2)

[Only registered and activated users can see links. Click Here To Register...]

So, it's [[AE9620]+C].

Open IDA and load up elementclient (see elsewhere for tutorials on IDA if you're unfamiliar with it or have no idea what I'm talking about here).
Hit Alt+I (or Search -> Immediate value), enter 0xAE9620 and check the "Find all occurences" box.
IDA should find 3 hits (pic_3) - Double click the second one to take you to the code.

[Only registered and activated users can see links. Click Here To Register...]

We're now in the section of code that updates the chatbox (pic_4). You can see our searched value, which is the static chatObjectsBase and just above it, we can see the first value we found in CE (0xAE962C) - This is the static lastChatObject offset.

[Only registered and activated users can see links. Click Here To Register...]

For some reason, searching in IDA for the 0xAE962C value didn't work for me even though we can see it there, plain as day. I'm no IDA expert, so if anyone knows why that is, please let me know ^_^.

This pic also shows the size of each object (0x1C), so we can now figure out how to traverse the list of chat objects.
I'll save you the hassle and show you my findings of the chatObject structure:


Code:
struct chatObj
{
    uint        uk1;        // 0x00 Unknown
    char        msgScope;    // 0x04 I.e., world, private, faction (see messageTypes)
    char        smileySet;  // 0x05
    char         uk3;        // 0x06
    char        uk4;        // 0x07
    wchar        *p_msg    // 0x08 Pointer to actual unicode message string
    uint        dwItemId    // 0x0C ID of an item linked in chat
    uint        msgId        // 0x10 Unique message ID (can be different from index)
    uint        uk5;        // 0x14
    uint        uk6;        // 0x18
}
I haven't investigated all of the info types fully, mainly just the ones I'm interested in.
Code:
messageTypes    (see chatObj->msgScope)
    Local            // 0
    World            // 1
    Squad            // 2
    Faction          // 3
    Whisper          // 4
    Damage           // 5
    Combat           // 6
    Trade            // 7
    Notification     // 8
    System           // 9
    Gen. Info        // 0xa
    Local info(b)    // 0xb
    Local info(c)    // 0xc
So, to traverse the chat objects....
Code:
// 0 - 199 max
For(i = 0 ; i < lastChatObject ; i++)
{
    p->chatObject = [[chatObjectsBase] + i*0x1C]
    // Actual message
    p->message = [[[chatObjectsBase] + i*0x1C]+0x8]
}
Here's some sample c# code that you can play around with to test this (PWI only - Sorry, tutorial might work for other versions too, in which case you can just change the offsets. I don't really fancy downloading all the other clients, so if anyone wants to try this out, be my guest ;)

Some of the code is borrowed from Interest07's excellent thread on [Only registered and activated users can see links. Click Here To Register...]
So thanks Interest, your thread actually convinced me to get into C# hehe. You might be interested in my little resolveNestedPointer function and maybe the way I did the structure definitions and handling in C#... Although you probably have a better way ;)

And guys.... C# Express is free and plenty enough to work with, plus it has a great debugger. Beats this AutoIt rubbish hands down.

Hope my first thread helped someone :)

[Only registered and activated users can see links. Click Here To Register...]

EDIT: As I get asked a lot for help finding these offsets after updates etc, here's a little tool to find them automagically :P
Full AutoIt script to find chat offsets:
Code:
getChatOffsets()

Func getChatOffsets()
    $path = "elementclient.exe"
    $file = FileOpen($path, 16)
    $data = FileRead($file, FileGetSize($path))
    FileClose($file)
    
    $search ='.*?' & _
            '8B0D(.{8})' & _    ; /MOV ECX,DWORD PTR DS:[elementclient.0B2DE40]
            '8B4C0E.{2}' & _    ; |MOV ECX,DWORD PTR DS:[ECX+ESI+0C]
            '85C9' & _            ; |TEST ECX,ECX
            '74.{2}' & _        ; |JE SHORT elementclient.004F1586
            '8B11' & _            ; |MOV EDX,DWORD PTR DS:[ECX]
            '6A.{2}' & _        ; |PUSH 1
            'FF12' & _            ; |CALL DWORD PTR DS:[EDX]
            'A1(.{8})'            ; |MOV EAX,DWORD PTR DS:[elementclient.0B2DE4C]
    
    $matches = StringRegExp($data, $search, 2)
    
    ConsoleWrite('$chatBase = 0x'&rev($matches[1])&@CRLF)
    ConsoleWrite('$lastChatIndex = 0x'&rev($matches[2])&@CRLF)

EndFunc


Func rev($string)
    Local $all
    For $i = StringLen($string) + 1 To 1 Step -2
        $all = $all & StringMid($string, $i, 2)
    Next
    While StringLeft($all, 1) = '0'
        $all = StringTrimLeft($all, 1)
    WEnd
    Return $all
EndFunc
Simple test code in C# (be sure to compile with /unsafe)
Form1.cs

Form1.Designer.cs

And for convenience, here's the whole solution

EDIT: [Only registered and activated users can see links. Click Here To Register...]
04/15/2011 12:23 aminlv#2
wow guys u r indeed something else :O
04/15/2011 15:51 Interest07#3
Very nicely done :)

I have to say my code for reading chat messages is a lot more chaotic (and hasn't been updated for quite a few versions as it never really left the erm 'debugging' stages). Here's a screeny of it in the process of debugging that I digged up :D (For giggles, the code is less than exemplary lol)

[Only registered and activated users can see links. Click Here To Register...]

I do read structs in per struct instead of seperate values, although I believe I do it differently, with the same general principle of course. I don't have a function for the nested pointers like you do, I might do that some time as it could make certain code a bit clearer. Prolly a good idea :)

Love the guide, it's always good to help people get to the values they need themselves if possible. I'm glad you liked my send packet thread and C# > AutoIt ehehehe. It doesn't hurt to understand AutoIt though, as it appears very popular among a lot of (beginning) coders.

Keep up the good work!
04/15/2011 19:44 Smurfin#4
nice, could you please translate the example to autoit, it's the only scripting app that I have a little knowledge of. Aside from its flaw, autoit can be learned easier even for a beginner who's starting from zero, like me :p

this chat struct might help to be used as a trigger for auto escaping script in nirvana's minotaur boss room by detecting it's early shout, I think nv's minotaur is the hardest boss to solo, this chat reader should be able to help a bit. I am stuck in killing this one boss :mad:
04/15/2011 21:56 Interest07#5
Quote:
Originally Posted by Smurfin View Post
nice, could you please translate the example to autoit, it's the only scripting app that I have a little knowledge of. Aside from its flaw, autoit can be learned easier even for a beginner who's starting from zero, like me :p

this chat struct might help to be used as a trigger for auto escaping script in nirvana's minotaur boss room by detecting it's early shout, I think nv's minotaur is the hardest boss to solo, this chat reader should be able to help a bit. I am stuck in killing this one boss :mad:
baseChatPointer = [BASE_CHAT_ADDRESS]
chatmessage[i] = [[baseChatPointer + 0x8 + i * 0x1C] + 0x0]

That's all you really need for what you want :)
04/16/2011 00:40 dumbfck#6
Hehe thanks Interest. I was about to do some AutoIt research, but I think you explained enough ^^
And I see you did some work with the colouring.... I've done a little myself, working on an external chat window. Not releasing it all yet as it's not finished but it's kinda nice so far.
- Displays chat window outside of game
- Has MSN style toaster popups on receiving messages (configurable for each type of message - Mostly useful for PMs and stuff while working on stuff with PW minimised but can be set to popup on any type of message.
- Text is displayed in same colours as in game (with a few exceptions =P)
- Links are clickable
- Halfway sorted out showing smilies on it (manually animating them too ;) )
- Item links not done yet
-Worked out some stuff for sending chat messages - Long way to go though
- Have some offsets for reading chat messages further back than those that are displayed in game (will post some info on this soon =] )

Keeping it to myself just for the time being, but will release it when finished ;)
Can't give everything away straight away huh? ^^
I'm open to special requests though if anybody wants to collaborate on the project - I'm happy to share the work-in-progress so long as the requests aren't "MAKE ME GM HACK CHAT?!?1!" or "GIF ME OFFSETS PLISS".

*Edit: @Interest - Don't suppose you have any useful info for sending chat messages? Seems the 'generic' handler requires about 50 parameters lol. I've been looking at handling each type of message separately (i.e., local, faction, squad, world).

Cheers, dumbfck

*Another edit: Oh - And I'd prefer not to give AutoIt examples for everything.... But I've been doing a little research and might be able to give some very basic info for it lol. AutoIt just seems like the wrong tool for most jobs, as far as I can see. C# is free too!

Question - Are any of the AutoIt debuggers any good? I'm guessing I'll probably have to do some coding in AutoIt at some point but echoing variables sucks!
04/16/2011 04:53 Smurfin#7
thanks for the info Interest07 and dmbfck :handsdown:
the pw-'msn' is cool :p , it can even display damage info, very convenient to observe it in other window and not in the game since it could flood the whole chat, I usually put it in [trading] tab.
04/16/2011 07:58 Interest07#8
Ohh, that does look really neat ;)

i did dig out all the smileys and turned em into (animated) .gif if you need those. I've never really looked into sending chat as I don't run any bots myself, but you might wanna check out the function responsible for sending chat packets? It's a different one from the general game actions. Not sure if that would be the easiest function, but it just might be :)

I can see where it would be useful if you're gonna implement some msn style chat system. That would actually be neat for regular play situations as well :p

By the way, if you look around in that bit of code where you got the addresses, you'll find some legacy code for handling messages the old way. They changed it at some point, not that it's useful or anything, but it's kinda funny that they never bothered to delete the old code and just left it in to cause ehm, confusion.
04/16/2011 12:10 omarranimado#9
fiinaly it found his way to english board :)

17.09.2010, 19:58
[Only registered and activated users can see links. Click Here To Register...]

[Only registered and activated users can see links. Click Here To Register...]

nice text to find offest myself, thx for it.

edit:
btw. i use chatlog in my farmbot.
i see prophet bot use timer, maybe he ad function to wait for system msg while farm a mat.
if msg apear :"blabla 2 pig iron" bot know, farm was sucessfull and get next mat.

also nice to see how much pieces from a mat is allready farmed:
pig iron: 211
tiger herb: 241
...
...
...

ah excuse my english...russian text no help here for u :(
04/16/2011 19:51 dumbfck#10
@Interest - Thanks, I have the animated smilies too somewhere, but it seems like a royal pain in the arse to get an animated gif into a richtextbox control with transparency too, so at the moment I'm using the Tao.DevIl.dll library to read the dds files directly, then extract the 'frames' for each smilie from those, then animate them manually using a tick timer. You probably know about the text file in the same pack as the smilies that has the delay timings for each one ;)
So far it's looking good but I've been sidetracked onto other things lately lol.
I've used a similar technique to display inventory items too hehe:
[Only registered and activated users can see links. Click Here To Register...]
Not particularly useful, but I like to fiddle with things ^^
Some items don't show properly yet either, I'll probably figure out why one day.

As for the send chat stuff, I traced back from send and indeed, it does use a different function from sendPackets, but as far as I can tell, the generic chat sending function has a TON of parameters and I couldn't be arsed to figure them all out... Well I probably wouldn't be able to. If you have any other info on this, I'd be most greatful ;)

@omarranimado - That looks like a nice little program - Not completely sure what it does as I don't understand Russian :P
As for the Prophets, I think they use action structs to determine when a mat has been farmed - Probably the cleanest way.

Quote:
Originally Posted by omarranimado View Post
also nice to see how much pieces from a mat is allready farmed:
pig iron: 211
tiger herb: 241
...
Was this a question / request? Sorry, I didn't quite understand :confused:
04/17/2011 07:16 Interest07#11
Hmmm, *looks at the refresh AH button* Does this mean you know how the AH gold selling bit is structured perhaps? :o I could use that (for my shopper) :D

Yeah I used the txt file + dds to extract the smileys hehe, some of them were nice for msn.

Wish I was handy with graphical stuff, that looks pretty cool. When I need images I usually steal em straight from pwdatabase... I'm guessing you rip them from the .dds files?
04/17/2011 08:32 omarranimado#12
the program makes a chat log, like the name say.

Quote:
Was this a question / request? Sorry, I didn't quite understand
no, just a description for what reading chat text can be.

collected mats are random...sometime 1, sometime 2 or 3 mats collected.
just for info in farmbot some can read the amount of collected mat from system chat.
so bot info can have the counted amount of all sorted mats.

not really a important function, but looks nice and in my farmbot u can say "collect 100 pieces of xyz mat" so bot stopped if amount is reached or fly to other mats level position.

prophets code has timer to wait some seconds while mat is collected.
action struct is using to get/walk to a mat.
sometime he start collecting a mat, while collecting he run to other mat...since timer reach end before mat is collected.
u can test this on mats with long way to run to.

next is, if u start run to a mat...another user collect it while u run to it, bot stand some seconds next to it, waiting for end of timer.
using system chat text read, would be better way.
04/17/2011 09:39 Interest07#13
You can also check your inventory instead, for how many you've collected / whether it's increased. Not that chat log doesn't work fine as well :)
04/17/2011 12:00 mastaro#14
someone explain me... what i can do with that hack or what is it
04/17/2011 12:16 Interest07#15
Quote:
Originally Posted by mastaro View Post
someone explain me... what i can do with that hack or what is it
He just explained how you can read the ingame chat from memory. This might be useful for people that want to build some kind of whisper detection when botting, create some sort of msn like chat system, find out what resources you've harvested, or analyse trades from WC.