Show HP of the targeted mobs

07/22/2010 13:39 lolkop#16
well you should learn something about debugging and asm first.

using code injections to build up codecaves will make ur life a lot easier. tracing back dynamic stuff is just a waste of time.
you could simply step in the last pointer and get the adress directly with codecaves.
07/22/2010 16:54 No0oB#17
yeah lolkop that what i want to do ^^ cadecaves are rly helpful and the pointer and offset stuff i just do until i get my injections to work ^^
07/31/2010 14:01 Smurfin#18
Quote:
Originally Posted by lolkop View Post
well you should learn something about debugging and asm first.

using code injections to build up codecaves will make ur life a lot easier. tracing back dynamic stuff is just a waste of time.
you could simply step in the last pointer and get the adress directly with codecaves.
heya lolkop, I've been reading your posts here and there and find lots of useful infos. Thanks a lot :handsdown:

hope you could post example in autoit codes on how to auto target mob that can be attacked using normal attack (for an Archer or other physical class)

tks again.:handsdown:
07/31/2010 15:59 lolkop#19
well first you have to get a list of all mobs around you. to do that you gotta find the npclist function.

it looks like this:

now that we know how the client builds up the list of all npcs, we can do the same in our tool.
we could even let the script show us the offsets we need.

Code:
$path = "elementclient.exe"
$file = FileOpen($path, 16)
$data = FileRead($file, FileGetSize($path))
FileClose($file)
$npc_list = StringRegExp($data, '568B7424(.{2})8BC633D2F771(.{2})8B41(.{2})8B149085D274.{2}3972.{2}74.{2}8B1285D275.{2}33C05EC2.{4}8B4424.{2}85C074.{2}8B4A(.{2})', 1)
If IsArray($npc_list) Then ConsoleWrite('MobBase = ClientBase + 0x1C + 0x'&$npc_list[0]&' + 0x'&$npc_list[1]&' + 0x'&$npc_list[2]&' + x*4 + 0x'&$npc_list[3]&@CRLF)
will return us something like this (in PWI):
Quote:
MobBase = ClientBase + 0x1C + 0x08 + 0x24 + 0x18 + x*4 + 0x04
now that we've got the structure, we can build that code up in autoit.
Code:
$npc_base = memread(memread(memread(memread(memread(memread(memread($base) + 0x1C) + 0x8) + 0x24) + 0x18) + $x*0x4) + 0x4)
if we set a breakpoint on the variable line, we'll get the range we have to make $x loop through (should be 0-768 normaly). (loops should allways be done with "for ... next" in autoit)

well now that we've got a list of all npc_bases, we will have to figure out some offsets for that base. guess type, id, position, name, level and maybe some more would be helpfull for filtering/selecting the mobs.

my NpcListing function looks like this:
Code:
Func GetNpcList()
	Local $array[1][8], $pointer, $npc_base, $counter
	$pointer = memread(memread(memread(memread(memread($base) + 0x1C) + 0x8) + 0x24) + 0x18)
	For $x=0 To 768
		$npc_base = memread(memread($pointer + $x*0x4) + 0x4)
		If $npc_base<>0 Then
			ReDim $array[$counter+1][8]
			$array[$counter][0] = memread($npc_base, 'byte') ;NPC Type (NPC/MOB/PET)
			$array[$counter][1] = memread($npc_base + 0x11C) ;NPC ID
			$array[$counter][2] = memread(memread($npc_base + 0x254), 'wchar[30]') ;NPC Name
			$array[$counter][3] = memread($npc_base + 0x124) ;NPC Level
			$array[$counter][4] = memread($npc_base + 0x248) ;Special Info
			$array[$counter][5] = (memread($npc_base + 0x3C, 'float')+4000)/10 ;NPC x-position
			$array[$counter][6] = (memread($npc_base + 0x44, 'float')+5500)/10 ;NPC y-position
			$array[$counter][7] = memread($npc_base + 0x40, 'float')/10 ;NPC z-position
			$counter += 1
		EndIf
	Next
	Return $array
EndFunc
and it returns something like that:
[Only registered and activated users can see links. Click Here To Register...]

now that u've got a list of all available mobs and special infos, you could calculate the distance between player and mobs, and selected the closest one. (you can even filter them, by name or filter out mag resistant (for wizzards) mobs or whatever you like to do with those infos =))

if you need a basic list of special info types i've found so far, you could check my open source [Only registered and activated users can see links. Click Here To Register...]

well the most important part is still missing. now i've got those mob ids, but how can i use them to select the mob?
to do that i've used the selection function from the client.
Code:
;~ select
;~ 0046061D     A1 6C3E9F00       MOV EAX,DWORD PTR DS:[9F3E6C]            ; |eax <- [base]
;~ 00460622     57                PUSH EDI                                 ; |Arg1 = Mob-ID
;~ 00460623  |. 8B48 20           MOV ECX,DWORD PTR DS:[EAX+20]            ; |ecx <- [[base]+0x20]
;~ 00460626  |. 81C1 EC000000     ADD ECX,0EC                              ; |ecx += 0xEC
;~ 0046062C  |. E8 8F961800       CALL elementc.005E9CC0                   ; \call select_call
thats the code in the PWI client. may be a little diferent in your client, but i've allready posted a tool above which gets the base and select_call adress.

to use it we will simply allocate some memory in the element client, for our tool, add the select function to it and run it. after that we'll delete the code from the client, to make some space for more functions we could use. (we could also leave the select function in the client, so we wouldn't have to rebuild it all the time, but it would be harder to handle multiclients that way)

so here's the function i'm using:
Code:
Func SelectMob($id)
	Local $pRemoteThread, $vBuffer, $loop, $result, $OPcode
	; --- save the position of the allocated memory ---
	$pRemoteMem = DllCall($kernel32, 'int', 'VirtualAllocEx', 'int', $mid, 'ptr', 0, 'int', 0x46, 'int', 0x1000, 'int', 0x40)
	; --- build up the asm code ---
	; 0046061D  A1 6C3E9F00       MOV EAX,DWORD PTR DS:[9F3E6C]
	; 00460622  57                PUSH EDI                        <---- EDI Contains Mob-ID
	; 00460623  8B48 20           MOV ECX,DWORD PTR DS:[EAX+20]
	; 00460626  81C1 EC000000     ADD ECX,0EC
	; 0046062C  E8 8F961800       CALL elementc.005E9CC0
	$OPcode &= '60'																; pushad
	$OPcode &= 'A1'&_hex($base)													; mov eax, [base]
	$OPcode &= '68'&_hex($id)													; push mob-id
	$OPcode &= '8B4820'															; mov ecx, [eax+0x20]
	$OPcode &= '81C1'&_hex(0xEC)												; add ecx, 0xEC
	$OPcode &= 'E8'&_hex($select_call-$pRemoteMem[0]-5-StringLen($OPcode)/2)	; call select_call
	$OPcode &= '61'																; popad
	$OPcode &= 'C3'																; retn
	; --- enter the asm code to to a dllstruct, which can be used with WriteProcessMemory ---
	$vBuffer = DllStructCreate('byte[' & StringLen($OPcode) / 2 & ']')
	For $loop = 1 To DllStructGetSize($vBuffer)
		DllStructSetData($vBuffer, 1, Dec(StringMid($OPcode, ($loop - 1) * 2 + 1, 2)), $loop)
	Next
	; --- now letz write the code from our dllstruct ---
	DllCall($kernel32, 'int', 'WriteProcessMemory', 'int', $mid, 'int', $pRemoteMem[0], 'int', DllStructGetPtr($vBuffer), 'int', DllStructGetSize($vBuffer), 'int', 0)
	; --- now we run the asm code we've just written ---
	$hRemoteThread = DllCall($kernel32, 'int', 'CreateRemoteThread', 'int', $mid, 'int', 0, 'int', 0, 'int', $pRemoteMem[0], 'ptr', 0, 'int', 0, 'int', 0)
	; --- wait till the thread did his job ---
	Do
		$result = DllCall('kernel32.dll', 'int', 'WaitForSingleObject', 'int', $hRemoteThread[0], 'int', 50)
	Until $result[0] <> 258
	; --- close everything we've opened ---
	DllCall($kernel32, 'int', 'CloseHandle', 'int', $hRemoteThread[0])
	DllCall($kernel32, 'ptr', 'VirtualFreeEx', 'hwnd', $mid, 'int', $pRemoteMem[0], 'int', 0, 'int', 0x8000)
	Return True
EndFunc
now that we're able to list, filter and select mobs, we need to kill the selected mobs.
to do that, we can use simple keypressing, or find the skill function in the client.

the skillfunction looks like this:
Code:
;~ Skill
;~ 00463B2A  |. 50             PUSH EAX                                 ; /Arg4 = Skill-ID
;~ 00463B2B  |. 8B42 08        MOV EAX,DWORD PTR DS:[EDX+8]             ; |[EDX+8] constains Skill-SN
;~ 00463B2E  |. 6A 01          PUSH 1                                   ; |Arg3 = 00000001
;~ 00463B30  |. 51             PUSH ECX                                 ; |Arg2 = 00000000
;~ 00463B31  |. 8B0D 6C3E9F00  MOV ECX,DWORD PTR DS:[9F3E6C]            ; |elementc.009F44F0
;~ 00463B37  |. 50             PUSH EAX                                 ; |Arg1 = Skill-SN
;~ 00463B38  |. 8B49 20        MOV ECX,DWORD PTR DS:[ECX+20]            ; |ecx = [[base] + 0x20]
;~ 00463B3B  |. 81C1 EC000000  ADD ECX,0EC                              ; |ecx += 20
;~ 00463B41  |. E8 EA621800    CALL elementc.005E9E30                   ; \elementc.005E9E30
we can simply use it in the same way we've used the select function.
the Skill SNs are stored in the skillstr.txt

well since this is not a how-do-i-code-a-bot-which-ruins-the-game thread, i will not explain how to list all skills and get the needed skill ids.

same can be done for looting btw.
08/01/2010 13:15 Smurfin#20
thank you very much for sharing, lolkop. I'm still new at programming though and might get stuck later when doing it (I usually do [Only registered and activated users can see links. Click Here To Register...]), please don't get bored if I ask further about it later [Only registered and activated users can see links. Click Here To Register...]

-edit-
I just tried your stats.au3, but it didn't show the correct char infos for PW Indo.
Do I need to change all offsets in stats.au3 to match those for PW Indo, or can I just change $base and $exp_base and the rests will automatically follow ?
08/02/2010 08:15 Smurfin#21
[Only registered and activated users can see links. Click Here To Register...]

lolkop, may I ask the source code for the program to list all mobs above ? Do you use koda form designer for autoit or else ?

I tried running this code from your post
Code:
$path = "d:\000. Online Games\Perfect World Indonesia\element\elementclient.exe"
$file = FileOpen($path, 16)
$data = FileRead($file, FileGetSize($path))
FileClose($file)
$npc_list = StringRegExp($data, '568B7424(.{2})8BC633D2F771(.{2})8B41(.{2})8B149085D274.{2}3972.{2}74.{2}8B1285D275.{2}33C05EC2.{4}8B4424.{2}85C074.{2}8B4A(.{2})', 1)
If IsArray($npc_list) Then ConsoleWrite('MobBase = ClientBase + 0x1C + 0x'&$npc_list[0]&' + 0x'&$npc_list[1]&' + 0x'&$npc_list[2]&' + x*4 + 0x'&$npc_list[3]&@CRLF)
and get this in return, MobBase = ClientBase + 0x1C + 0x08 + 0x24 + 0x18 + x*4 + 0x04

so I guess the pointers for mobs are the same for PWI and Indo, I'm still new in autoit and I rly need a working source code to begin with, because the last targetting method was so simple by just passing mob id to target offset, which doesn't work anymore.
08/02/2010 12:48 lolkop#22
use the select function from my mob/item listings post:
[Only registered and activated users can see links. Click Here To Register...]

i've posted a tool there to get the base and select_call adress. you don't need to change anything with the function itself.
08/03/2010 09:04 Smurfin#23
lolkop, I tried to use your SelectMob() Function, and put my char ID but it gave me an error like below, what did I miss ?

Code:
>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "G:\AutoIT\lolkop\selectmob tes.au3"    
G:\AutoIT\lolkop\selectmob tes.au3 (12) : ==> Unknown function name.:
$OPcode &= 'A1'&_hex($base)
$OPcode &= 'A1'&^ ERROR
>Exit code: 1    Time: 0.209
here is the full code I ran, I just want to simply try the selectmob function to select a given char ID, hoping that my char will then properly target that specified npc id. It's basically only contains your SelectMob and MemOpen function, and run selectmob to make my char target another char with this ID -> 0x18AE50. I also have adjusted the value for $base, $select_call and $pick_call to the correct values for my client version.

Code:
Func SelectMob($id)
 Local $pRemoteThread, $vBuffer, $loop, $result, $OPcode
 ; --- save the position of the allocated memory ---
 $pRemoteMem = DllCall($kernel32, 'int', 'VirtualAllocEx', 'int', $mid, 'ptr', 0, 'int', 0x46, 'int', 0x1000, 'int', 0x40)
 ; --- build up the asm code ---
 ; 0046061D  A1 6C3E9F00       MOV EAX,DWORD PTR DS:[9F3E6C]
 ; 00460622  57                PUSH EDI                        <---- EDI Contains Mob-ID
 ; 00460623  8B48 20           MOV ECX,DWORD PTR DS:[EAX+20]
 ; 00460626  81C1 EC000000     ADD ECX,0EC
 ; 0046062C  E8 8F961800       CALL elementc.005E9CC0
 $OPcode &= '60'                ; pushad
 $OPcode &= 'A1'&_hex($base)             ; mov eax, [base]
 $OPcode &= '68'&_hex($id)             ; push mob-id
 $OPcode &= '8B4820'               ; mov ecx, [eax+0x20]
 $OPcode &= '81C1'&_hex(0xEC)            ; add ecx, 0xEC
 $OPcode &= 'E8'&_hex($select_call-$pRemoteMem[0]-5-StringLen($OPcode)/2) ; call select_call
 $OPcode &= '61'                ; popad
 $OPcode &= 'C3'                ; retn
 ; --- enter the asm code to to a dllstruct, which can be used with WriteProcessMemory ---
 $vBuffer = DllStructCreate('byte[' & StringLen($OPcode) / 2 & ']')
 For $loop = 1 To DllStructGetSize($vBuffer)
  DllStructSetData($vBuffer, 1, Dec(StringMid($OPcode, ($loop - 1) * 2 + 1, 2)), $loop)
 Next
 ; --- now letz write the code from our dllstruct ---
 DllCall($kernel32, 'int', 'WriteProcessMemory', 'int', $mid, 'int', $pRemoteMem[0], 'int', DllStructGetPtr($vBuffer), 'int', DllStructGetSize($vBuffer), 'int', 0)
 ; --- now we run the asm code we've just written ---
 $hRemoteThread = DllCall($kernel32, 'int', 'CreateRemoteThread', 'int', $mid, 'int', 0, 'int', 0, 'int', $pRemoteMem[0], 'ptr', 0, 'int', 0, 'int', 0)
 ; --- wait till the thread did his job ---
 Do
  $result = DllCall('kernel32.dll', 'int', 'WaitForSingleObject', 'int', $hRemoteThread[0], 'int', 50)
 Until $result[0] <> 258
 ; --- close everything we've opened ---
 DllCall($kernel32, 'int', 'CloseHandle', 'int', $hRemoteThread[0])
 DllCall($kernel32, 'ptr', 'VirtualFreeEx', 'hwnd', $mid, 'int', $pRemoteMem[0], 'int', 0, 'int', 0x8000)
 Return True
EndFunc

Func memopen($pid)
	Local $mid = DllCall($kernel32, 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 1, 'int', $pid)
	Return $mid[0]
EndFunc


#include <array.au3>
Global $kernel32 = DllOpen('kernel32.dll')
Global Const $base = 0x98ADDC, $select_call = 0x5B7B70, $pick_call = 0x5B7B00
Global $pid = ProcessExists('elementclient.exe')
Global $mid = memopen($pid)

$id= 0x18AE50
SelectMob($id)