Mob and Item Listings

08/01/2010 02:51 lolkop#1
well since there have been many questsions about this before, i'll give some example codes, of how to list mobs and select them, and how to list items and pick them up.

these functions are a great start for a bot =)

we'll start with the listing functions:
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

Func GetItemList()
	Local $array[1][6], $pointer, $item_base, $counter
	$pointer = memread(memread(memread(memread(memread($base) + 0x1C) + 0x8) + 0x28) + 0x18)
	For $i=0 To 768
		$item_base = memread(memread($pointer + $i*4) + 0x4)
		If $item_base<>0 Then
			ReDim $array[$counter+1][6]
			$array[$counter][0] = memread($item_base + 0x110)  ;Item-SN
			$array[$counter][1] = memread($item_base + 0x10C)  ;Item-ID
			$array[$counter][2] = memread(memread($item_base + 0x164), 'wchar[30]')  ;Item-Name
			$array[$counter][3] = (memread($item_base + 0x3C, 'float')+4000)/10  ;Item x-position
			$array[$counter][4] = (memread($item_base + 0x44, 'float')+5500)/10  ;Item y-position
			$array[$counter][5] = memread($item_base + 0x40, 'float')/10  ;Item z-position
			$counter += 1
		EndIf
	Next
	Return $array
EndFunc

Func GetPlayerList()
	Local $array[1][5], $pointer, $player_base, $counter
	$pointer = memread(memread(memread(memread(memread($base) + 0x1C) + 0x8) + 0x20) + 0x18)
	For $x=0 To 768
		$player_base = memread(memread($pointer + $x*0x4) + 0x4)
		If $player_base<>0 Then
			ReDim $array[$counter+1][5]
			$array[$counter][0] = memread(memread($player_base + 0x610), 'wchar[30]') ;Name
			$array[$counter][1] = $class_info[memread($player_base + 0x618)] ;class
			$array[$counter][2] = (memread($player_base + 0x3C, 'float')+4000)/10 ;x
			$array[$counter][3] = (memread($player_base + 0x44, 'float')+5500)/10 ;y
			$array[$counter][4] = memread($player_base + 0x40, 'float')/10 ;z
			$counter += 1
		EndIf
	Next
	Return $array
EndFunc
both functions will return arrays with informations about the listed stuff. these informations should be enough to build up a good item/mob filter.

now we have to use the select and pick function from the client, to select/pick the specified ids.

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 PickItem($sn, $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 ---
	;~ 004707F8  |. 8B15 6C3E9F00  MOV EDX,DWORD PTR DS:[9F3E6C]            ;  edx <- [base]
	;~ 004707FE  |. 50             PUSH EAX                                 ; /Item-SN
	;~ 004707FF  |. 51             PUSH ECX                                 ; |Item- ID
	;~ 00470800  |. 8B4A 20        MOV ECX,DWORD PTR DS:[EDX+20]            ; |
	;~ 00470803  |. 81C1 EC000000  ADD ECX,0EC                              ; |
	;~ 00470809  |. E8 42941700    CALL elementc.005E9C50                   ; \elementc.005E9C50
	$OPcode &= '60'                                                           ; pushad
	$OPcode &= '8B15'&_hex($base)                                             ; mov edx, [base]
	$OPcode &= '68'&_hex($sn)                                                 ; push item-sn
	$OPcode &= '68'&_hex($id)                                                 ; push item-id
	$OPcode &= '8B4A20'                                                       ; mov ecx, [edx+0x20]
	$OPcode &= '81C1'&_hex(0xEC)                                              ; add ecx, 0xEC
	$OPcode &= 'E8'&_hex($pick_call-$pRemoteMem[0]-5-StringLen($OPcode)/2)  ; call pick_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
well i've written my own memory functions, and a function to turn integers into reversed hexstrings, usable for the cpu (needed in asm functions)

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

Func memread($adress, $type = 'dword')
	Local $struct = DllStructCreate($type)
	DllCall($kernel32, 'int', 'ReadProcessMemory', 'int', $mid, 'int', $adress, 'ptr', DllStructGetPtr($struct), 'int', DllStructGetSize($struct), 'int', '')
	Return DllStructGetData($struct, 1)
EndFunc

Func memclose($mid)
	DllCall($kernel32, 'int', 'CloseHandle', 'int', $mid)
EndFunc

Func _hex($Value)
	Local $tmp1, $tmp2, $i 
	$tmp1 = StringRight("0000000" & Hex($Value), 8) 
	For $i = 0 To StringLen($tmp1) / 2 - 1 
		$tmp2 = $tmp2 & StringMid($tmp1, StringLen($tmp1) - 1 - 2 * $i, 2)
	Next
	Return $tmp2
EndFunc
there's just one more thing to say. the item listing lists all normal items, plus the harvest stuff. the pickup function is only made to pickup normal items. there's another function in the client for harvest stuff, but i'm not realy able to use it yet :s

as soon as i'm able to use it, i'll post it here.

well for those of you who need an example of usage for my functions:
Code:
#include <array.au3>
Global $kernel32 = DllOpen('kernel32.dll')
Global Const $base = 0x9F3E6C, $select_call = 0x5E9CC0, $pick_call = 0x5E9C50
Global $class_info[8] = ['Blademaster', 'Wizzard', 'Psychic', 'Venomancer', 'Barbarian', 'Assassin', 'Archer', 'Cleric']
Global $special_info[10] = ['None', 'Increased Movement', 'Unknown Special', 'Increased Defence', 'Increased Mag Resistance', 'Increased Attack', 'Increased Magical Attack', 'Sacrificial Assault', 'Increased Life', 'Weak']
Global $pid = ProcessExists('elementclient.exe')
Global $mid = memopen($pid)

$npcs = GetNpcList()
_ArrayDisplay($npcs)

$items = GetItemList()
_ArrayDisplay($items)

$players = GetPlayerList()
_ArrayDisplay($players)

memclose($mid)
DllClose($kernel32)
as you can see $kernel32, $pid, $mid, $base, $select_call and $pick_call ain't defined in my functions, so you have to do that or pre-define them as global constants, which is more efficient :P
08/01/2010 06:55 Zepelin02#2
I'm new in AutoIt and I do not know if I understood correctly, such feature would she select one of NPC and select the objects for sale? O
I tried for a while to find a way to do it with imageSearch but without result: s
08/01/2010 11:48 lolkop#3
as the title sais, this is for mob and item listings.

so you could build up a list of all mobs around you, with lvl, name, ..., you can select and kill the mob

list all items, pick up the items

select next mob to kill it
pickup new drops ....

guess u've got the system


the good thing about this is, that you can filter mobs and items. you can choose, which items the bot should pick up, and which mobs the bot should select.
08/01/2010 12:14 chakjii#4
great work buddy :P
now you only need the solution how to pick up the plants and rocks etc :)
08/01/2010 13:30 lolkop#5
i've added a function to list all players around you. (may get used for inviting them into partys)
08/01/2010 14:44 Smurfin#6
are all those memory addresses in the functions above different for every PW server ? or only base address, because for example, in zevorc's bot the offsets for monsters name, level, etc are the same and only some values need to be adjusted like player's hp/maxhp/base address.
08/01/2010 15:16 lolkop#7
the client base is different in each client. and the calls do also have to be updated for ur version. thats why i've posted the odbg code snipets.

since i've never seen the other clients, i can't say if there are other changes needed.
08/01/2010 15:27 Zepelin02#8
it would be possible to have an example pls? I do not know what to change in your script.
A report with this?

[Only registered and activated users can see links. Click Here To Register...]
08/01/2010 15:38 lolkop#9
this code should return the base and call adresses:
Code:
$path = "elementclient.exe"
$file = FileOpen($path, 16)
$data = FileRead($file, FileGetSize($path))
FileClose($file)
$select = StringRegExp($data, '(A1(.{8})578B482081C1EC000000E8(.{8}))', 1)
$call_pos = StringInStr($data, $select[0])/2 + 0x40000E
ConsoleWrite('$base = '&rev($select[1])&@CRLF)
ConsoleWrite('$select_call = 0x'&Hex(('0x'&rev($select[2])) + $call_pos + 5)&@CRLF)
$pick = StringRegExp($data, '(8B15(.{8})50518B4A2081C1EC000000E8(.{8}))', 1)
$call_pos = StringInStr($data, $pick[0])/2 + 0x400010
ConsoleWrite('$pick_call = 0x'&Hex(('0x'&rev($pick[2])) + $call_pos + 5)&@CRLF)

Func rev($string)
	Local $all
	For $i = StringLen($string) + 1 To 1 Step -2
		$all = $all & StringMid($string, $i, 2)
	Next
	Return $all
EndFunc
08/02/2010 19:06 Brows#10
Do you have a Code for the "follow player" function? I couldn't find it til now :(
(I think, I need some more tuts to use ollydbg xD)
08/03/2010 01:03 chuckleeyahoo.com#11
dude that is some nice shit

i remember using a bot u made for silkroad long ass time ago
08/03/2010 07:35 Smurfin#12
I managed to get this by running your codes above, it still doesn't display correct mob names though, I've adjusted the value for base, select_call, and Pick_call using the tool you posted above. The second window shows other things with correct names. I run the codes at outside Archosaur City west gate

What are the descriptions for the column groups Col0 and Col4, from what I see Col1=NPC ID, Col2= Mob Names, Col3=Level , Col5=X, Col6=Y, Col7=Height,

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

[Only registered and activated users can see links. Click Here To Register...]
08/10/2010 13:41 Smurfin#13
lolkop, could you pls post an autoit function to kill mob using the asm code you posted earlier ?
oh, and where can I find skillstr.txt ? I've searched all txt files in PW installation folder and couldn't find it

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
08/29/2010 21:41 Smurfin#14
nvm the above posts.

does anyone know how to Refresh _arraydisplay in autoit so it'll run the function every like 3 seconds and renew whatever resources are nearby and put them to display in the table ? just for the $items.
$items = GetItemList()
_ArrayDisplay($items)
08/30/2010 04:06 chakjii#15
Quote:
Originally Posted by Smurfin View Post
nvm the above posts.

does anyone know how to Refresh _arraydisplay in autoit so it'll run the function every like 3 seconds and renew whatever resources are nearby and put them to display in the table ? just for the $items.
$items = GetItemList()
_ArrayDisplay($items)


lol funny i just made a tool like that xD

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