i know that this topic is kinda old, but since i've found a way for myself to get all objects listed, i'd like to show, how i found them...
first of all i have to say, that i was looking for a way to list all items. i didn't know that i would find a list of all objects this way.
to start getting all items listed, i took the grab function...
in the zszc client it looks like this:
Code:
007440B0 /$ 83EC 20 SUB ESP,20
007440B3 |. A1 440EAA00 MOV EAX,DWORD PTR DS:[AA0E44]
007440B8 |. D905 70C09C00 FLD DWORD PTR DS:[9CC070]
007440BE |. 8B88 8C000000 MOV ECX,DWORD PTR DS:[EAX+8C]
007440C4 |. D91C24 FSTP DWORD PTR SS:[ESP]
007440C7 |. 8B90 90000000 MOV EDX,DWORD PTR DS:[EAX+90]
007440CD |. 8B80 94000000 MOV EAX,DWORD PTR DS:[EAX+94]
007440D3 |. 8325 2490A800 >AND DWORD PTR DS:[A89024],FFFFFFFE
007440DA |. 894424 10 MOV DWORD PTR SS:[ESP+10],EAX
007440DE |. A1 1890A800 MOV EAX,DWORD PTR DS:[A89018]
007440E3 |. 57 PUSH EDI
007440E4 |. 33FF XOR EDI,EDI
007440E6 |. 85C0 TEST EAX,EAX
007440E8 |. 894C24 0C MOV DWORD PTR SS:[ESP+C],ECX
007440EC |. 895424 10 MOV DWORD PTR SS:[ESP+10],EDX
007440F0 |. A3 2090A800 MOV DWORD PTR DS:[A89020],EAX
007440F5 |. 0F84 E0000000 JE sro_clie.007441DB
007440FB |. 56 PUSH ESI
007440FC |. 8D6424 00 LEA ESP,DWORD PTR SS:[ESP]
00744100 |> 8DB0 34FFFFFF /LEA ESI,DWORD PTR DS:[EAX-CC]
00744106 |. 85F6 |TEST ESI,ESI
00744108 |. 0F84 AA000000 |JE sro_clie.007441B8
0074410E |. 68 7834AA00 |PUSH sro_clie.00AA3478
00744113 |. 8BCE |MOV ECX,ESI
00744115 |. E8 B6921D00 |CALL sro_clie.0091D3D0
0074411A |. 84C0 |TEST AL,AL
0074411C |. 0F84 91000000 |JE sro_clie.007441B3
00744122 |. 83BE F4010000 >|CMP DWORD PTR DS:[ESI+1F4],0
00744129 |. 0F85 84000000 |JNZ sro_clie.007441B3
0074412F |. D986 8C000000 |FLD DWORD PTR DS:[ESI+8C]
00744135 |. D86424 10 |FSUB DWORD PTR SS:[ESP+10]
00744139 |. D95C24 1C |FSTP DWORD PTR SS:[ESP+1C]
0074413D |. D986 90000000 |FLD DWORD PTR DS:[ESI+90]
00744143 |. D86424 14 |FSUB DWORD PTR SS:[ESP+14]
00744147 |. D95C24 20 |FSTP DWORD PTR SS:[ESP+20]
0074414B |. D986 94000000 |FLD DWORD PTR DS:[ESI+94]
00744151 |. D86424 18 |FSUB DWORD PTR SS:[ESP+18]
00744155 |. D95C24 24 |FSTP DWORD PTR SS:[ESP+24]
00744159 |. D94424 20 |FLD DWORD PTR SS:[ESP+20]
0074415D |. D94424 1C |FLD DWORD PTR SS:[ESP+1C]
00744161 |. D94424 24 |FLD DWORD PTR SS:[ESP+24]
00744165 |. D9C1 |FLD ST(1)
00744167 |. DECA |FMULP ST(2),ST
00744169 |. D9C2 |FLD ST(2)
0074416B |. DECB |FMULP ST(3),ST
0074416D |. D9C9 |FXCH ST(1)
0074416F |. DEC2 |FADDP ST(2),ST
00744171 |. DCC8 |FMUL ST,ST
00744173 |. DEC1 |FADDP ST(1),ST
00744175 |. D95C24 0C |FSTP DWORD PTR SS:[ESP+C]
00744179 |. D94424 0C |FLD DWORD PTR SS:[ESP+C]
0074417D |. E8 EE301A00 |CALL sro_clie.008E7270
00744182 |. D95C24 0C |FSTP DWORD PTR SS:[ESP+C]
00744186 |. D94424 0C |FLD DWORD PTR SS:[ESP+C]
0074418A |. D95C24 0C |FSTP DWORD PTR SS:[ESP+C]
0074418E |. D94424 0C |FLD DWORD PTR SS:[ESP+C]
00744192 |. D94424 08 |FLD DWORD PTR SS:[ESP+8]
00744196 |. D8D9 |FCOMP ST(1)
00744198 |. DFE0 |FSTSW AX
0074419A |. F6C4 41 |TEST AH,41
0074419D |. 75 12 |JNZ SHORT sro_clie.007441B1
0074419F |. 8BB6 E8000000 |MOV ESI,DWORD PTR DS:[ESI+E8]
007441A5 |. 85F6 |TEST ESI,ESI
007441A7 |. 74 08 |JE SHORT sro_clie.007441B1
007441A9 |. D95C24 08 |FSTP DWORD PTR SS:[ESP+8]
007441AD |. 8BFE |MOV EDI,ESI
007441AF |. EB 02 |JMP SHORT sro_clie.007441B3
007441B1 |> DDD8 |FSTP ST
007441B3 |> A1 2090A800 |MOV EAX,DWORD PTR DS:[A89020]
007441B8 |> F605 2490A800 >|TEST BYTE PTR DS:[A89024],1
007441BF |. 74 09 |JE SHORT sro_clie.007441CA
007441C1 |. 8325 2490A800 >|AND DWORD PTR DS:[A89024],FFFFFFFE
007441C8 |. EB 08 |JMP SHORT sro_clie.007441D2
007441CA |> 8B40 0C |MOV EAX,DWORD PTR DS:[EAX+C]
007441CD |. A3 2090A800 |MOV DWORD PTR DS:[A89020],EAX
007441D2 |> 85C0 |TEST EAX,EAX
007441D4 |.^0F85 26FFFFFF \JNZ sro_clie.00744100
007441DA |. 5E POP ESI
007441DB |> 8BC7 MOV EAX,EDI
007441DD |. 5F POP EDI
007441DE |. 83C4 20 ADD ESP,20
007441E1 \. C3 RETN
as we know, the grab function should loop through all loots in the ground, and select the one with the lowest distance to us.
so to start this, we will directly step into the loop, olly shows us.
Code:
00744100 |> 8DB0 34FFFFFF /LEA ESI,DWORD PTR DS:[EAX-CC]
00744106 |. 85F6 |TEST ESI,ESI
00744108 |. 0F84 AA000000 |JE sro_clie.007441B8
..........................................................................................
007441CA |> 8B40 0C |MOV EAX,DWORD PTR DS:[EAX+C]
007441CD |. A3 2090A800 |MOV DWORD PTR DS:[A89020],EAX
007441D2 |> 85C0 |TEST EAX,EAX
007441D4 |.^0F85 26FFFFFF \JNZ sro_clie.00744100
i've removed some lines, to keep it short.
as we see, EAX - 0xCC gets loaded into ESI. now we should take a look above the loop, to see, where EAX gets set.
a few lines above the loop, we find this line:
Code:
007440DE |. A1 1890A800 MOV EAX,DWORD PTR DS:[A89018]
now we'll take a look at the end of the grap function, to see what gets returned. the returned register should be the id of the item, with the lowest distance to our char. if we found the output, we'll trace it back to see where it gets read from the memory:
Code:
0074419F |. 8BB6 E8000000 |MOV ESI,DWORD PTR DS:[ESI+E8]
007441AD |. 8BFE |MOV EDI,ESI
007441DB |> 8BC7 MOV EAX,EDI
so the id of the item should be stored in [ESI+0xE8]
when this was done, i've build a simple autoit tool, to list up what i've found out so far:
Code:
$pid = WinGetProcess('[CLASS:CLIENT]')
$mid = OpenProcess($pid)
$EAX = ReadProcessMemory($mid, 0xA89018)
Do
$ESI = $EAX - 0xCC
$id = ReadProcessMemory($mid, $ESI + 0xE8)
ConsoleWrite('ID: '&Hex($id)&@CRLF)
$EAX = ReadProcessMemory($mid, $EAX+0xC)
Until $EAX = 0
CloseHandle($mid)
as i ran the tool, i've noticed, that the tool did list way to many ids. when i took a deeper look at the ids, i've noticed, that mobs players and npcs also got listed.
since the pickup function should only list items, it had to detect items in the loop. so i went back into the loop.
the first thing thats done in the loop, looks like this:
Code:
00744113 |. 8BCE |MOV ECX,ESI
00744115 |. E8 B6921D00 |CALL sro_clie.0091D3D0
0074411A |. 84C0 |TEST AL,AL
0074411C |. 0F84 91000000 |JE sro_clie.007441B3
it looks like a function gets called. in case of a fail, the grab-function skips that object.
if we follow the call, we will find something like this:
Code:
0091D3DD |. 8B11 MOV EDX,DWORD PTR DS:[ECX]
0091D3E0 |. 8B02 MOV EAX,DWORD PTR DS:[EDX]
so now we could assume, that eax stores our current object type.
adding this part to our source, will show us, if it realy works like that:
Code:
$pid = WinGetProcess('[CLASS:CLIENT]')
$mid = OpenProcess($pid)
$EAX = ReadProcessMemory($mid, 0xA89018)
Do
$ESI = $EAX - 0xCC
$type = ReadProcessMemory($mid, ReadProcessMemory($mid, $ESI))
$id = ReadProcessMemory($mid, $ESI + 0xE8)
ConsoleWrite('Type: '&Hex($type)&@CRLF)
ConsoleWrite('ID: '&Hex($id)&@CRLF)
$EAX = ReadProcessMemory($mid, $EAX+0xC)
Until $EAX = 0
CloseHandle($mid)
now we can log all kinds of objects, in our range.
i've spend some more time in analyzing the code around ESI and i've found some more, quite interesting stuff.
in the end my function for zszc looked like this:
Code:
Func recognize_objects($pid)
Local $type_mob = 0x739910, $type_item = 0x7442D0, $type_player = 0x740BE0, $type_me = 0x73F8B0, $type_npc = 0x73A8A0, $type_teleport = 0x747340
Local $mid, $object, $base, $name, $type, $id, $x, $y, $my_x, $my_y, $static_id, $distance, $last_distance = 0xFFFFFF
$mid = OpenProcess($pid)
$object = ReadProcessMemory($mid, 0xA89018)
Do
$base = $object - 0xCC
If ReadProcessMemory($mid, $base + 0x118) > 16 Then
$name = ReadProcessMemory($mid, ReadProcessMemory($mid, $base + 0x104), "char[200]")
Else
$name = ReadProcessMemory($mid, $base + 0x104, "char[200]")
EndIf
$type = ReadProcessMemory($mid, ReadProcessMemory($mid, $base))
$static_id = ReadProcessMemory($mid, $base + 0x184)
$id = ReadProcessMemory($mid, $base + 0xE8)
$x = BitRotate(Execute(ReadProcessMemory($mid, $base + 0x78, "byte[1]")) * 3 - 0x195, 6) - Int(ReadProcessMemory($mid, $base + 0x7C, "float") / (-10))
$y = BitRotate(Execute(ReadProcessMemory($mid, $base + 0x79, "byte[1]")) * 3 - 0x114, 6) - Int(ReadProcessMemory($mid, $base + 0x84, "float") / (-10))
$distance = Sqrt(Abs($my_x - $x) ^ 2 + Abs($my_y - $y) ^ 2)
Switch $type
Case $type_me
$my_x = $x ; if we found ourself as object, we save our position to
$my_y = $y ; calculate the distance between us and the other objects
Case $type_mob
ConsoleWrite('Mob Name: '&$name&'('&$static_id&')'&' found!'&@CRLF)
ConsoleWrite(' ID to Select: '&$id&@CRLF)
ConsoleWrite(' Position: '&$x&','&$y&@CRLF)
ConsoleWrite(' Distance to us: '&Round($distance, 2)&@CRLF)
Case $type_item
ConsoleWrite('Item Name: '&$name&'('&$static_id&')'&' found!'&@CRLF)
ConsoleWrite(' ID to Select: '&$id&@CRLF)
ConsoleWrite(' Position: '&$x&','&$y&@CRLF)
ConsoleWrite(' Distance to us: '&Round($distance, 2)&@CRLF)
Case $type_player
ConsoleWrite('Player Name: '&$name&'('&$static_id&')'&' found!'&@CRLF)
ConsoleWrite(' ID to Select: '&$id&@CRLF)
ConsoleWrite(' Position: '&$x&','&$y&@CRLF)
ConsoleWrite(' Distance to us: '&Round($distance, 2)&@CRLF)
Case $type_npc
ConsoleWrite('NPC Name: '&$name&'('&$static_id&')'&' found!'&@CRLF)
ConsoleWrite(' ID to Select: '&$id&@CRLF)
ConsoleWrite(' Position: '&$x&','&$y&@CRLF)
ConsoleWrite(' Distance to us: '&Round($distance, 2)&@CRLF)
Case $type_teleport
ConsoleWrite('Teleport Name: '&$name&'('&$static_id&')'&' found!'&@CRLF)
ConsoleWrite(' ID to Select: '&$id&@CRLF)
ConsoleWrite(' Position: '&$x&','&$y&@CRLF)
ConsoleWrite(' Distance to us: '&Round($distance, 2)&@CRLF)
EndSwitch
$object = ReadProcessMemory($mid, $object + 0xC)
Until $object <= 0
CloseHandle($mid)
EndFunc
the output looked like this:
[Only registered and activated users can see links. Click Here To Register...]
later i've found out, that its even possible to read all informations about the items other players wear, from the code stored around ESI. but since i was not interested in those informations, i did not add them to the source.