Что нового

[Royal Quest] Различные способы чтения значений из памяти, на примере

nowost

Знающий
Сообщения
178
Репутация
17
Доброго времени суток, уважаемые дамы и господа. Тут было приведено несколько способов считывания значения из памяти но совсем запутался
Итак игра Royal Quest
Считываю значения жизни персонажа ( оно у меня найдено вот в таком виде rqmain.exe+0x005DFF54)
вот таким способом работает все отлично
Код:
#include "NomadMemory.au3"
SetPrivilege("SeDebugPrivilege", 1)
global $sModule = "rqmain.exe"
global $ProcessID = WinGetProcess("Royal Quest")
SetPrivilege("SeDebugPrivilege", 1)
global $DllInformation = _MemoryOpen($ProcessID)
global $baseADDR = _MemoryModuleGetBaseAddress($ProcessID, $sModule)Func _HP()
   $Base =$baseADDR+0x005DFF54
local $temp = _MemoryRead($Base, $DllInformation, 'ptr') ;Тут и далее читаем как 'ptr', так как они указывают не на финальное значение а на промежуточный адрес который мы должны увидеть как Hex
local $temp2 = _MemoryRead($temp + dec('4'), $DllInformation, 'ptr')
local $temp3 = _MemoryRead($temp2 + dec('510'), $DllInformation, 'ptr')
local $temp4 = _MemoryRead($temp3 + dec('67c'), $DllInformation, 'ptr')
Local $temp5 = _MemoryRead($temp4 + dec('6b4'), $DllInformation, 'ptr')
Local $temp6 = _MemoryRead($temp5 + dec('758'), $DllInformation, 'float')
MsgBox(0,"$HP",$temp6)
EndFunc
;_Energy()
 _HP()

идем дальше пробую считать через DataOp
Код:
#include "NomadMemory.au3"
SetPrivilege("SeDebugPrivilege", 1)
global $sModule = "rqmain.exe"
global $ProcessID = WinGetProcess("Royal Quest")
SetPrivilege("SeDebugPrivilege", 1)
global $DllInformation = _MemoryOpen($ProcessID)
global $baseADDR = _MemoryModuleGetBaseAddress($ProcessID, $sModule)
Func DataOp($Param1, $Param2="no param", $Param3="no param", $ToDo="Read", $Data=0)

Global $Base, $Temp, $MemTemp, $DataType, $Offset[5]=["nop", "nop", "nop", "nop","nop"]

If $ToDo <> "Read" And $ToDo <> "Write" Then MsgBox(0,"ошибка","неправельный параметр")
     ;Определяем массив в который можно записать до 4 массивов. Сразу же присваиваем всем ячейкам какое-нибудь значение отличное от офсета.
    ;$Base - сюда скрипт записывает необходимый базовый адрес для текущего запроса
    ;$MemTemp - тут скрипт обрабатывает данные получаемые из памяти необходимые для текущего запроса
    ;$DataType - сюда скрипт записывает тип данных необходимый для текущего запроса
    ;$ToDo - что мы хотим делать по данному адресу
    ;$Data - если мы хотим произвести запись по адресу, мы должны указать что мы хоти туда записать.
    ;При обращении в эту функцию, она сперва переопределяет все значения на необходимые скрипту в данный момент и далее отправляет эти данные на обработку
    Select
        Case $Param1 = "Char" ;наша структура работы с персонажем Обращение: DataOp("Char", ...
            ;$DataType = "float" ;тип данных
            $Base =$baseADDR+0x005DFF54
			$DataType = "float"
            Select
                Case $Param2 = "Cur HP" ;жизни персонажа. Обращение: DataOp("Char", "Cur HP")
                        
						$Offset[1] = '4'
                        $Offset[2] = '510'
						$Offset[3] = '67c'
						$Offset[4] = '6b4'
						$Offset[5] = '758'
						
                Case $Param2 = "Max MP" ;макс жизни персонажа. Обращение: DataOp("Char", "Max HP")
                        $Offset[1] = '4'
                        $Offset[2] = '494'
                        $Offset[3] = '324'
                        
                    EndSelect
                 EndSelect
            
    ;Тут происходит обработка данных пришедших сверхку
    $MemTemp = (_MemoryRead($Base, $DllInformation)) ;первый запрос в память, полученный результат уже будет обрабатываться в цикле
    For $i = 2 To UBound($Offset, 1)-1 Step 1 ;i начинается с двух потому что было решено оставить [0] ячейку пустой, мб в будущем пригодится. В обращениях же к памяти обращения идут в ячейку [$i-1]
        If String($Offset[$i]) = "nop" Then ;Смотрим значение текущей ячейки. Если оно не содержит в себе оффсет
            If $ToDo = "Read" Then $MemTemp =  _MemoryRead($MemTemp+Dec($Offset[$i-1]), $DllInformation, $DataType) ;Если $ToDo = Read - читаем память. Значит нам пора формировать последний запрос используя данные хранящиеся в пред идущей ячейке [$i-1], на этом этапе нам необходимо указать тип данных которые мы желаем получить. Задаются в переменной $DataType
            If $ToDo = "Write" Then $MemTemp =  _MemoryWrite($MemTemp+Dec($Offset[$i-1]), $DllInformation, $Data, $DataType) ;Если $ToDo = Write - пишем память. Значит нам пора формировать последний запрос используя данные хранящиеся в пред идущей ячейке [$i-1], на этом этапе нам необходимо указать тип данных которые мы желаем записать. Задаются в переменной $DataType
            ExitLoop ;Отправив последний запрос, выходим из цикла. Нам больше нечего искать.
        Else ;Если значение в текущей ячейке содержит в себе оффсет, значит и пред идущая ячейка содержит в себе оффсет.
            $MemTemp =(_MemoryRead($MemTemp+Dec($Offset[$i-1]), $DllInformation)) ;Формируем запрос используя оффсет хранящийся в пред идущей от текущей ячейке [$i-1], чтобы попасть на следующий уровень памяти.
        EndIf
    Next
    Return $MemTemp ;Возвращаем полученные данные.
 EndFunc
 
 $test = DataOp("Char", "Cur HP")
MsgBox(0,"$test", $test)

в таком варианте ругается, а если поменять на
Код:
$Offset[6]=["nop", "nop", "nop", "nop","nop","nop"]


не ругается но значения неверные выдает :stars:

и еще один вариант который показал Белф это через _MemoryPointerRead
Код:
#include "NomadMemory.au3"
SetPrivilege("SeDebugPrivilege", 1)
global $sModule = "rqmain.exe"
global $ProcessID = WinGetProcess("Royal Quest")
SetPrivilege("SeDebugPrivilege", 1)
global $DllInformation = _MemoryOpen($ProcessID)
global $baseADDR = _MemoryModuleGetBaseAddress($ProcessID, $sModule)
$Base =$baseADDR+0x005DFF54
Global $CurrHP_cur_offset[6] = [0, 758, 1716, 1660, 510, 4]
$test = _MemoryPointerRead($Base, $DllInformation,  $CurrHP_cur_offset, "float")
MsgBox(0,"$HP_Cur",$test[1])

кода мало выглядит классно но значение неверное приводит
вот это
Код:
Global $CurrHP_cur_offset[6] = [0, 758, 1716, 1660, 510, 4]

в каком виде только не записывал и в hex и в dec и в обратном порядке и в прямом
хоть убейся но выдает 0 или любое другое число но не значение жзней :stars:

прошу вас помощи разобраться с этими функциями. всем заранее спасибо :beer:
 

lirikmel

Продвинутый
Сообщения
226
Репутация
84
В случае dataOp
Код:
$DataType = "dword" ;тип данных
во втором ноль не нужен
 
Автор
N

nowost

Знающий
Сообщения
178
Репутация
17
float или dword не повлияло. всеравно результат некорректный выдаёт :stars:
а во втором случае, Бельф писал, что вроде как 0 первый всегда нужен, но темнеменнее с нулём или без нуля выдаёт всеравно ноль :'(
 

lirikmel

Продвинутый
Сообщения
226
Репутация
84
да как так :stars: , проверяй

вот это недельной давности код для бота RQ

Код:
Func DataOp($Param1, $Param2="no param", $Param3="no param", $ToDo="Read", $Data=0)

Global $Base, $Temp, $MemTemp, $DataType, $Offset[5]=["nop", "nop", "nop", "nop", "nop"]

If $ToDo <> "Read" And $ToDo <> "Write" Then MsgBox(0,"ошибка","неправельный параметр")
	 ;Определяем массив в который можно записать до 4 массивов. Сразу же присваиваем всем ячейкам какое-нибудь значение отличное от офсета.
	;$Base - сюда скрипт записывает необходимый базовый адрес для текущего запроса
	;$MemTemp - тут скрипт обрабатывает данные получаемые из памяти необходимые для текущего запроса
	;$DataType - сюда скрипт записывает тип данных необходимый для текущего запроса
	;$ToDo - что мы хотим делать по данному адресу
	;$Data - если мы хотим произвести запись по адресу, мы должны указать что мы хоти туда записать.
	;При обращении в эту функцию, она сперва переопределяет все значения на необходимые скрипту в данный момент и далее отправляет эти данные на обработку
	Select
        Case $Param1 = "Char" ;наша структура работы с персонажем Обращение: DataOp("Char", ...
			$DataType = "dword" ;тип данных
			$Base =$baseADDR+0x005DFF54
			Select
				Case $Param2 = "Cur HP" ;жизни персонажа. Обращение: DataOp("Char", "Cur HP")
						$Offset[1] = '4'
						$Offset[2] = '1BC'
				Case $Param2 = "Max MP" ;макс жизни персонажа. Обращение: DataOp("Char", "Max HP")
					    $Offset[1] = '4'
						$Offset[2] = '190'
						$Offset[3] = '168'
				Case $Param2 = "Cur MP" ;мана персонажа. Обращение: DataOp("Char", "Cur MP")
					$Offset[1] = '4'
						$Offset[2] = '190'
						$Offset[3] = '16c'
				Case $Param2 = "Max HP" ;мана персонажа. Обращение: DataOp("Char", "Max MP")
					$Offset[1] = '4'
						$Offset[2] = '174'

				Case $Param2 = "Pos" ;Обращение: DataOp("Char", "Pos", ...
                      $Base =$baseADDR+0x005DFF58
					 $DataType = "float"
					Select

						Case $Param3 = "X" ;Обращение: DataOp("Char", "Pos", "X")
							$Offset[1] = '188'
						    $Offset[2] = '34'
						Case $Param3 = "Y" ;Обращение: DataOp("Char", "Pos", "Y")
                            $Offset[1] = '188'
                            $Offset[2] = '38'
						Case $Param3 = "Z" ;Обращение: DataOp("Char", "Pos", "Z")
							$Offset[1] = '188'
                            $Offset[2] = '3c'
;~

						Case $Param3 = "R" ;Обращение: DataOp("Char", "Pos", "R Base") Работаем с ячейкой отвечающей за ротацию чара
							$Offset[1] = '188'
                            $Offset[2] = '24'
						Case $Param3 = "All" ;Обращение: DataOp("Char", "Pos", "All")
							Local $rScan[4] = ["X", "Y", "Z", "R"] ;Создаем временный массив в который заносим то что будет сканироваться и в каком порядке оно будет сканироваться
							Local $rTemp[4] ;Создаем временный массив в который будем записывать результаты сканов
							For $i = 0 To UBound($rTemp, 1)-1 Step 1
								$rTemp[$i] = DataOp("Char", "Pos", $rScan[$i]) ;Сканируем
							Next
							Return $rTemp ;Возвращаем массив
						Case Else
							SetError(3)
							;Сообщение об ошибке может быть закомменчено или наоборот, в зависимости от того чего мы хотим от скрипта.
;~ 							ErrorMsg('DataOp("'&$Param1&'", "'&$Param2&'", WTF?...', 'Ошибка вызова: команды DataOp("'&$Param1&'", "'&$Param2&'", "'&$Param3&'") не существует.')
					EndSelect
				Case Else
					SetError(2)
					;Сообщение об ошибке может быть закомменчено или наоборот, в зависимости от того чего мы хотим от скрипта.
;~ 					ErrorMsg('DataOp("'&$Param1&'", WTF?...', 'Ошибка вызова: команды DataOp("'&$Param1&'", "'&$Param2&'") не существует.')
			EndSelect
		Case $Param1 = "Target"
			$DataType = "dword" ;тип данных
			  Select
                 Case $Param2 = "CursorInfo" ;ж Обращение: DataOp("Target", "CursorInfo")
			          $Base = $baseADDR+0x004C7D74
                $MemTemp =_MemoryRead($Base, $DllInformation)
                   Return $MemTemp
                 Case $Param2 = "targetCheck" ;ж Обращение: DataOp("Target", "targetCheck")
			          $Base =$baseADDR+0x005D4B64
                           $Offset[1] = '4'
                            $Offset[2] = '190'
                               $Offset[3] = 'E4'
                     Case Else
					  SetError(2)
					    ;Сообщение об ошибке может быть закомменчено или наоборот, в зависимости от того чего мы хотим от скрипта.
;~ 					     ErrorMsg('DataOp("'&$Param1&'", WTF?...', 'Ошибка вызова: команды DataOp("'&$Param1&'", "'&$Param2&'") не существует.')
			EndSelect
		Case Else
			SetError(1)
			;Сообщение об ошибке может быть закомменчено или наоборот, в зависимости от того чего мы хотим от скрипта.
;~ 			ErrorMsg('DataOp(WTF?...', 'Ошибка вызова: команды DataOp("'&$Param1&'") не существует.')
	EndSelect
	;Тут происходит обработка данных пришедших сверхку
	$MemTemp = (_MemoryRead($Base, $DllInformation)) ;первый запрос в память, полученный результат уже будет обрабатываться в цикле
	For $i = 2 To UBound($Offset, 1)-1 Step 1 ;i начинается с двух потому что было решено оставить [0] ячейку пустой, мб в будущем пригодится. В обращениях же к памяти обращения идут в ячейку [$i-1]
		If String($Offset[$i]) = "nop" Then ;Смотрим значение текущей ячейки. Если оно не содержит в себе оффсет
			If $ToDo = "Read" Then $MemTemp =  _MemoryRead($MemTemp+Dec($Offset[$i-1]), $DllInformation, $DataType) ;Если $ToDo = Read - читаем память. Значит нам пора формировать последний запрос используя данные хранящиеся в пред идущей ячейке [$i-1], на этом этапе нам необходимо указать тип данных которые мы желаем получить. Задаются в переменной $DataType
			If $ToDo = "Write" Then $MemTemp =  _MemoryWrite($MemTemp+Dec($Offset[$i-1]), $DllInformation, $Data, $DataType) ;Если $ToDo = Write - пишем память. Значит нам пора формировать последний запрос используя данные хранящиеся в пред идущей ячейке [$i-1], на этом этапе нам необходимо указать тип данных которые мы желаем записать. Задаются в переменной $DataType
			ExitLoop ;Отправив последний запрос, выходим из цикла. Нам больше нечего искать.
		Else ;Если значение в текущей ячейке содержит в себе оффсет, значит и пред идущая ячейка содержит в себе оффсет.
			$MemTemp =(_MemoryRead($MemTemp+Dec($Offset[$i-1]), $DllInformation)) ;Формируем запрос используя оффсет хранящийся в пред идущей от текущей ячейке [$i-1], чтобы попасть на следующий уровень памяти.
		EndIf
	Next
	Return $MemTemp ;Возвращаем полученные данные.
EndFunc


для таблицы CE во вложении
 
Автор
N

nowost

Знающий
Сообщения
178
Репутация
17
OffTopic:
щас сервера поднимут попробую



Добавлено:
Сообщение автоматически объединено:

в общем показывает все по нулям, в таблице CE не показывает значения также, возможно указатели изменились



Добавлено:
Сообщение автоматически объединено:

после патча похоже изменились адреса мои тоже не отображает щас буду поновой искать :whistle:
 
Автор
N

nowost

Знающий
Сообщения
178
Репутация
17
немного понекропощу с вашего позволения, возможно комуто поможет.
снова столкнулся с данной функцией
Код:
Func DataOp($Param1, $Param2="no param", $Param3="no param", $ToDo="Read", $Data=0)


в общем сам нашел ответ на свой вопрос :laugh:
во первых я не учел:
Код:
Dec($Offset[$i-1])

и вовторых не учел:
Код:
If $ToDo = "Read"


ответ на свой вопрос нашел сам помечаю тему решенной :IL_AutoIt_1:
 
Верх