Comment faire un cheat (WEH-like)

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Leplayze

Frite...euse (jeu de mot)
V
Ancien staff
Dec 4, 2009
12,649
5
1,303
30
www.youtube.com
merci a bouh2 pour ce tuto

Créer un Cheat

Bonjour,

Voici le tutoriel tant attendu par certain, je vais vous expliquer comment exploiter la structure de WoW et ainsi faire un "mini WEH".

Ce sera à vous de créer votre cheat à partir des adresses et offset déjà donné ;)

I. Le Playerbase

Le Playerbase est l'adresse dites de "base" du joueur. C'est une adresse qui désigne l'endroit ou est stocké toutes les informations sur le joueur (que l'on joue).
On ajoute un offset à l'adresse obtenu pour trouver la donnée que l'on veux (vitesse de déplacement, positions ...)
Cette adresse est dynamique, elle change à chaque lancement et à chaque chargement dans WoW, on doit donc la trouver en lisant des pointeurs spécifiques.

Le schéma du playerbase est :

Code:
Playerbase = [[StaticAdress]+0x30]+0x28
Note : StaticAdress est disponible dans le post des Pointer&Offset. Cette adresse est la même à chaque lancement de WoW mais change à chaque Mise à jour. Il faut donc la modifier dans ce cas là.

Ce qui donne en faites :

PHP:
    $PlayerBase = _MemoryRead((_MemoryRead((_MemoryRead(0x#######, $Processus, "ptr") + 0x30), $Processus, "ptr") + 0x28), $Processus, "ptr")
Bien sûr il faut remplacer ####### par l'adresse statique selon la version

Il faut ensuite ajouter un offset qui correspond à la donnée que l'on veut (voir sujet sur les Pointer&Offset).

Exemple avec 0x7D0 (Coordonnés X du personnage)

PHP:
    $PlayerBase = _MemoryRead((_MemoryRead((_MemoryRead(0x#######, $Processus, "ptr") + 0x30), $Processus, "ptr") + 0x28), $Processus, "ptr")

$PosX = _MemoryRead($PlayerBase + 0x7D0, $Processus, 'float')
Et pareil pour la modification

PHP:
    $PlayerBase = _MemoryRead((_MemoryRead((_MemoryRead(0x#######, $Processus, "ptr") + 0x30), $Processus, "ptr") + 0x28), $Processus, "ptr")

$PosX = _MemoryRead($PlayerBase + 0x7D0, $Processus, 'float')
_MemoryWrite($PlayerBase + 0x7D0, $Processus,$PosX + 10, 'float')
Note : La notation "ptr" indique une valeur pointeur, celle-ci n'est pas obligatoire on peut théoriquement la remplacer par "int" ou "dword" mais évite toute erreur.
L'AutoIt contrairement à d'autre langage comme le C/C++ accepte sans problème cette différence.


Il arrive en lisant la mémoire (ex : pos du perso) que vous ayez un résultat de ce genre : "3.03434E4", cela signifie que la valeur n'est pas float donc que ce n'est pas la bonne adresse ou que celle ci ai changer (ex : lors d'un chargement)

Il faut donc rechargez la playerbase de cette façon :

PHP:
HotKeySet("{F4}","Reload");reload appelé lorsque la touche F4 est pressé

... ; chargement de wow

    $PlayerBase = _MemoryRead((_MemoryRead((_MemoryRead(0x#######, $Processus, "ptr") + 0x30), $Processus, "ptr") + 0x28), $Processus, "ptr")

$PosX = _MemoryRead($PlayerBase + 0x7D0, $Processus, 'float') ;valeur non significative et improbable

Func Reload() ;fonction appelé par exemple par un raccourci
    $PlayerBase = _MemoryRead((_MemoryRead((_MemoryRead(0x#######, $Processus, "ptr") + 0x30), $Processus, "ptr") + 0x28), $Processus, "ptr")
EndFunc
On peut aussi envisager de recharger WoW si on l'avait quitter, mais ce sera à vous de le faire xD

II. L'object Manager

L'Object manager est une fonction qui permet de renvoyer tout les objets que WoW a chargé (PNJ, Joueur, GO, Items, Cadavres et sacs). Cette fonction que l'on doit créer doit être une boucle qui renvoie des informations sur un objet de la même façon que le playerbase en ajoutant un offset à l'adresse obtenu.

J'expliquerais quels sont ces offsets par la suite.

Tout d'abords on doit trouver l'adresse base de l'Object manager qui est dynamique :

Code:
[Client Connexion]+CurMgrOff = Object Manager Base
Note : Client connexion est une adresse statique qui est toujours la même au lancement de WoW au contraire de l'Object Manager Base qui lui change à chaque chargement.

A partir de là les objets seront à la suite, le premier sera :

Code:
Object Manager Base + 0xAC = Premier Objet
Et le prochain sera :

Code:
Premier Objet + 0x3C = Objet suivant
Puis

Code:
Objet suivant + 0x3C = Objet suivant
Etc ...

Note : C'est à ces adresse obtenus que l'on ajoute un offset.

On va donc faire une boucle qui les fasse tous et qui en sort quand le résultat est 0 ou n'est pas pair et à chaque fois on incrémentera l'adresse base de l'object actuel de 0x3C

Note : Pour savoir si un nombre est pair on dois faire une division par 2 et voir si sont reste est égale à 0. Il est existe un opérateur qui donne le reste d'un division : le modulo ( signé % en C/C++, C#, Java et autres). En autoit c'est une fonction, la fonction Mod(dividende, diviseur).
Mod(4,3) donne 1 car il y a 1 fois 3 dans 4 et il reste 1. Bon je ne vais pas revenir sur la division, mieux vaut le savoir ;)


Voici à quoi notre boucle ressemble :

PHP:
#include <NomadMemory.au3> ;obligatoire

;On déclare toutes les adresses et offset
;Le fait de mettre Const empêche une modifications des donnés
;Cela évite des erreurs bêtes et permet d'etre plus clair
Global Const $staticClientConnection = 0x011CB310
Global Const $offFirstObject = 0xAC, $offNextObject = 0x3C
Global Const $offObjectManager = 0x28A4

;On déclare les variables
Local $CurrentObject
Local $LocalGuid
Global $ObjectManagerBase

;Ne pas oublier d'ouvre le processus de wow

LoadAdresses() ;on initiale l'ojectmanager
$CurrentObject = _MemoryRead($ObjectManagerBase + $offFirstObject, $Processus, 'int') ;On lit le premiere objet
While ($CurrentObject <> 0) And (Mod($CurrentObject, 2) == 0) ;si différent de 0 ou si pair on continu la boucle
    
    ;-----------------------
    ;On ajoutera le code ici
    ;-------------------------
    
    $CurrentObject = _MemoryRead($CurrentObject + $offNextObject, $Processus, 'int') ;On lit l'objet suivant
WEnd

Func LoadAdresses()
    $ObjectManagerBase = _MemoryRead(_MemoryRead($staticClientConnection, $Processus, 'int') + $offObjectManager, $Processus, 'int')
EndFunc
Note : J'ai fait en sortes de faire le code le plus propre possible, je vous conseille fortement de faire de même. (Adresse au début du code, espacer le code, faire des fonctions pour bien délimiter...)

Chaque objet à un type, il y a 7 types :
1 - Objets dans votre sac (Items)
2 - Conteneurs
3 - Unités (Monstre & PNJ)
4 - Joueurs
5 - GameObjects
6 - DynamicObjects (Sorts & équipements)
7 - Cadavres

Pour différencier les types d'objets on utilise l'offset 0x14 qui correspond au type

Voici comment on pourrais organisé ça :

PHP:
Global Const $offTypeObject = 0x14

While ($CurrentObject <> 0) And (Mod($CurrentObject, 2) == 0) ;si différent de 0 ou si pair on continu la boucle
    
    Switch (_MemoryRead($CurrentObject + $offTypeObject, $Processus, 'int')
        case 1
            ;Item
        case 2
            ;Conteneur
        case 3
            ;Unité
        case 4
            ;Joueur
        case 5
            ;GameObject
        case 6
            ;Sort ou équipement
        case 7
            ;Cadavre
    EndSwitch
    
    $CurrentObject = _MemoryRead($CurrentObject + $offNextObject, $Processus, 'int') ;On lit l'objet suivant
WEnd
Note : Le switch empêche de faire des "if" inutiles, de plus ça évite de lire 7 fois la mémoire au lieu d'une ce qui est considérable pour l'autoit

On va d'abords s'intéresser aux type joueur et unités qui sont les plus simples

On va juste lire la position de chaque
Les offsets sont simples ce sont les mêmes que ceux du joueur local (playerbase) soit 0x7D0, 0x7D4 et 0x7D8 pour la 3.0.3 - 3.0.9

On va organiser un maximum le code, une seul fonction suffit. En retournant un tableau on évite de déclarer trop de variables inutiles

PHP:
Global Const $offTypeObject = 0x14
Global Const $offPosX = 0x7D0
Global Const $offPosY = 0x7D4
Global Const $offPosZ = 0x7D8
Global Const $offRot = 0x7DC


local $ObjectPosition[4]
While ($CurrentObject <> 0) And (Mod($CurrentObject, 2) == 0) ;si différent de 0 ou si pair on continu la boucle
    
    Switch (_MemoryRead($CurrentObject + $offTypeObject, $Processus, 'int'))
        case 1
            ;Item
        case 2
            ;Conteneur
        case 3
            ;
            $ObjectPosition = GetObjectPos($CurrentObject, 3) ;donne la pos de l'unité
        case 4
            ;JoueurUnité
            $ObjectPosition = GetObjectPos($CurrentObject, 4) ;donne la pos du joueur
        case 5
            ;GameObject
        case 6
            ;Sort ou équipement
        case 7
            ;Cadavre
    EndSwitch
    
    $CurrentObject = _MemoryRead($CurrentObject + $offNextObject, $Processus, 'int') ;On lit l'objet suivant
WEnd

Func GetObjectPos($Object, $Type)
local $returnPos[4]

    Switch ($Type)
        Case 1 ;On retourne 0 car les items et conteneur n'ont pas de pos
            $returnPos[0] = 0
            $returnPos[1] = 0
            $returnPos[2] = 0
            $returnPos[3] = 0
        case 2
            $returnPos[0] = 0
            $returnPos[1] = 0
            $returnPos[2] = 0
            $returnPos[3] = 0
        Case 3 ;Si c'est une unité ou un joueur...
            $returnPos[0] = _MemoryRead($Object + $offPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offRot, $Processus, 'float') ;Rotation
        case 4
            $returnPos[0] = _MemoryRead($Object + $offPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offRot, $Processus, 'float') ;Rotation
        case 5
            ;On va voir plus tard
        case 6
            ;On va vois plus tard
        case 7
            ;on va voir plus tard
    EndSwitch
    
    Return $returnPos ;on retourne le résultat sous forme de tableau
EndFunc
Mais il faut bien l'avouer avec ça on fait pas grand chose
Alors on va pousser un peu et utiliser les "champs de descriptions" (DescriptorFields)
Voici la liste complète de ceux-là : Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris! (Dumper by Kynox)

Il faut avouer que cette liste est bien intrigante et incompréhensible

Nous allons par exemple trouver la position des GameObject


Il y a 2 offset à ajouter à l'objet :
-DescriptorFieldsOffsets (qui correspond à 0x08)
-L'offset que l'on désire (ici 0x10, 0x11, 0x12) multiplier par 4

Pourquoi multiplier par 4 ? Car le dumper donne juste l'ordre des offset, étant coder sur 4 octets il faut multiplier par 4 pour avoir le bonne offset

Note : Il me semble que le dumper de Cypher donne l'offset exact, déjà avec les valeurs multipliées, il est bon de vérifier ;)

Voici donc ce que l'on obtient :

Code:
[CurrentObjet +0x8]+0x10*4 = Position X du gameobject
Soit :

PHP:
_MemoryRead(_MemoryRead($CurrentObject + 0x8, $Processus, 'int') + 0x10 *4, $Processus, 'float')
On peux donc modifier notre fonction :
Code:
Global Const $offDescriptorFields = 0x8

Global Const $GAMEOBJECT_POS_X = 0x10
Global Const $GAMEOBJECT_POS_Y = 0x11
Global Const $GAMEOBJECT_POS_Z = 0x12
Global Const $GAMEOBJECT_FACING = 0x13

Global Const $DYNAMICOBJECT_POS_X = 0xB
Global Const $DYNAMICOBJECT_POS_Y = 0xC
Global Const $DYNAMICOBJECT_POS_Z = 0xD
Global Const $DYNAMICOBJECT_FACING = 0xE 

Global Const $CORPSE_FIELD_FACING = 0xA
Global Const $CORPSE_FIELD_POS_X = 0xB
Global Const $CORPSE_FIELD_POS_Y = 0xC
Global Const $CORPSE_FIELD_POS_Z = 0xD
PHP:
Func GetObjectPos($Object, $Type)
local $returnPos[4]

    Switch ($Type)
        Case 1 ;On retourne 0 car les items et conteneur n'ont pas de pos
            $returnPos[0] = 0
            $returnPos[1] = 0
            $returnPos[2] = 0
            $returnPos[3] = 0
        case 2
            $returnPos[0] = 0
            $returnPos[1] = 0
            $returnPos[2] = 0
            $returnPos[3] = 0
        Case 3 ;Si c'est une unité ou un joueur...
            $returnPos[0] = _MemoryRead($Object + $offPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offRot, $Processus, 'float') ;Rotation
        case 4
            $returnPos[0] = _MemoryRead($Object + $offPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offRot, $Processus, 'float') ;Rotation
        case 5 ;GameObject
            $returnPos[0] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_POS_X *4, $Processus, 'float')
            $returnPos[1] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_POS_Y *4, $Processus, 'float')
            $returnPos[2] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_POS_Z *4, $Processus, 'float')
            $returnPos[3] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_FACING *4, $Processus, 'float')
        case 6 ;Sort
            $returnPos[0] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_POS_X *4, $Processus, 'float')
            $returnPos[1] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_POS_Y *4, $Processus, 'float')
            $returnPos[2] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_POS_Z *4, $Processus, 'float')
            $returnPos[3] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_FACING *4, $Processus, 'float')
        case 7 ;cadavre
            $returnPos[0] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_POS_X *4, $Processus, 'float')
            $returnPos[1] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_POS_Y *4, $Processus, 'float')
            $returnPos[2] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_POS_Z *4, $Processus, 'float')
            $returnPos[3] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_FACING *4, $Processus, 'float')

    EndSwitch
    
    Return $returnPos ;on retourne le résultat sous forme de tableau
EndFunc
Et voilà notre fonction qui donne la pos d'un objet est complète, à vous de faire d'autre fonction du même genre.

Note : Je vous conseille d'ajouter l'include (Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!) au début du script. Ça évite des lignes pour rien.

Note : Attention la version 3.1.0 à beaucoup changé, pour avoir la position des GameObject ce n'est plus [CurrentObject + 0x8] GAME_OBJECT_POS_X * 4 mais CurrentObject + 0xE8 (E8, EC, F0) voir code ci-dessous

Maintenant, dernière complication, on va lire le nom de l'objet. Le moyen le plus (mais pas pour nous) et d'utiliser l'injection de code pour appeler la fonction (VMT) GetNameByObject()
Nous ne sommes pas encore à ce stade, on va se contenter de lire la mémoire

On va d'abords lire le nom d'un joueur, c'est le plus dure. En effet car il faut faire une fonction pour lire le nom à partir du GUID (Nombre unique donné par le serveur pour chaque object = Global Unique ID)
Je vous épargne les explications incompréhensible, voici le code :

PHP:
Func GetPlayerNameByGuid($guid)
    Local $mask, $base, $offset, $current, $shortGUID, $testGUID
    
    $mask = _MemoryRead($nameStorePtr + $nameMaskOffset, $Processus, 'int')
    $base = _MemoryRead($nameStorePtr + $nameBaseOffset, $Processus, 'int')
    
    $shortGUID = BitAnd($guid, 0xffffffff)
    if ($mask = 0xffffffff) Then Return ""
    $offset = 12 * BitAND($mask, $shortGUID)
    
    $current = _MemoryRead($base + $offset + 8, $Processus, 'int')
    $offset    = _MemoryRead($base + $offset, $Processus, 'int')
    
    if (BitAND($current, 0x1) == 0x1) then Return ""
    $testGUID = _MemoryRead($current, $Processus, 'int')
    
    while ($testGUID <> $shortGUID)
        $current = _MemoryRead($current + $offset + 4, $Processus, 'int')
        
        if (BitAND($current, 0x1) = 0x1) then Return ""
        $testGUID = _MemoryRead($current, $Processus, 'int')
    WEnd
    Return _MemoryRead($current + $nameStringOffset, $Processus, 'char[20]')
EndFunc
Note : Pour lire une chaîne de caractères on utilise le symbole "char[#]" en remplaçant # par le nombre de caractères à lire. Ici on met 20 car on sait que le nombre d'un joueur ne fait pas plus de 20 caractères.

L'offset du Guid de l'objet est 0x30
On appelle la fonction de cette manière :

PHP:
GetPlayerNameByGuid(_MemoryRead($CurrentObjet + 0x30, $Processus, 'int'))
Maintenant lire le nom des GameObject et des PNJ est relativement simple :

Unit Name :
[[Object + 0x970] + 0x3C]

GameObject Name :
[[Object + 0x1FA] + 0x78]

Donc notre fonction finale donne :

PHP:
Func GetObjectName($Object, $Type)
    Switch ($Type)
        Case 3;unité
            Return _String_To_StringUTF8(_MemoryRead(_MemoryRead(_MemoryRead($CurrentObject + $offUnitName1, $Processus, 'int') + $offUnitName2, $Processus, 'int'), $Processus, 'char[128]'))
        Case 4;joueur
            Return _String_To_StringUTF8(GetPlayerNameByGuid(_MemoryRead($Object + $offGuid, $Processus, 'int')))
        Case 5;gameobject
            Return _String_To_StringUTF8(_MemoryRead(_MemoryRead(_MemoryRead($CurrentObject + $offGameObjectName1, $Processus, 'int') + $offGameObjectName2, $Processus, 'int'), $Processus, 'char[128]'))
    EndSwitch
    Return ""
EndFunc   ;==>GetObjectName

Func _String_To_StringUTF8($String) ;Convertit une chaîne de charactère en chaîne UTF8
    Return BinaryToString(StringToBinary($String, 1), 4)
EndFunc
Note : J'ai ajouté la fonction _String_To_StringUTF8($string) elle permet de convertir les caractères ASCII en UTF8 ainsi pouvoir afficher les caractères spéciaux (é, à, ê, ô...) sinon vous aurez des @/, €( etc...

Donc enfin voici le code complet qui affiche les résultat dans une ListView qui est en faite un tableau(avec de la couleur !)

PHP:
#include "DescriptorDump.au3" ;Dump de Kynox convertit en AutoIt
#include <NomadMemory.au3>
;Include pour la GUI
#include <GUIConstantsEx.au3>
#include <GUIConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>

;On déclare toutes les adresses et offset
;Le fait de mettre Const empêche une modifications des donnés
;Cela évite des erreurs bêtes et permet d'etre plus clair
Global Const $staticClientConnection = 0x01132F60 ;3.0.9 : 0x011CB310
Global Const $offFirstObject = 0xAC, $offNextObject = 0x3C ;3.0.9 : 0xAC ;3.0.9 : 0x3C
Global Const $offLocalGuid = 0xC0 ;Guid du joueur ;3.0.9 : 0xC0
Global Const $offObjectManager = 0x2C24 ;3.0.9 : 0x28A4


;On déclare les variables
Local $CurrentObject
Local $ObjectPosition[4]
Local $LocalGuid
Global $ObjectManagerBase

Global $Processus

Global Const $offTypeObject = 0x14 ;3.0.9 : 0x14
Global Const $offGuid = 0x30 ;3.0.9 : 0x30
Global Const $offPosX = 0x798 ;3.0.9 : 0x7D0
Global Const $offPosY = 0x79C ;3.0.9 : 0x7D4
Global Const $offPosZ = 0x7A0 ;3.0.9 : 0x7D8
Global Const $offRot = 0x7A8 ;3.0.9 : 0x7DC
Global Const $offDescriptorFields = 0x8 ;3.0.9 : 0x8

Global Const $offGOPosX = 0xE8 ;3.0.9 : NOT
Global Const $offGOPosY = 0xEC ;3.0.9 : NOT
Global Const $offGOPosZ = 0xF0 ;3.0.9 : NOT
Global Const $offGORot = 0xF4 ;3.0.9 : NOT

Global Const $offUnitName1 = 0x968 ;3.0.9 : 0x970
Global Const $offUnitName2 = 0x54 ;3.0.9 : 0x03C
Global Const $offGameObjectName1 = 0x1A4 ;3.0.9 : 0x1F4
Global Const $offGameObjectName2 = 0x88 ;3.0.9 : 0x078

Global Const $nameStorePtr = 0x01137CE0 + 0x8;Nom du joueur dans la base de données  ;3.0.9 : 0x011AF470 + 0x8
Global Const $nameMaskOffset = 0x024;offset qui correspond au mask pour trouver le nom dans la liste de noms  ;3.0.9 : 0x024
Global Const $nameBaseOffset = 0x01c;offset qui correspond au début de la liste de nom  ;3.0.9 : 0x01c
Global Const $nameStringOffset = 0x020;offset qui correspond à la chaine de charactere dans la structure de nom  ;3.0.9 :0x020

;On déclare la gui en mémoire
$FormMain = GUICreate("Résultats...", 517, 308, 193, 125)
$LabelResult = GUICtrlCreateLabel("Résultat du dump :", 180, 8, 120, 17)
$List = GUICtrlCreateListView("", 8, 32, 497, 265, BitOR($WS_BORDER, $WS_HSCROLL, $WS_VSCROLL, 0xD), 0x200)
_GUICtrlListView_AddColumn($List, "Nom", 100)
_GUICtrlListView_AddColumn($List, "PosX", 100)
_GUICtrlListView_AddColumn($List, "PosY", 100)
_GUICtrlListView_AddColumn($List, "PosZ", 100)
_GUICtrlListView_AddColumn($List, "Rotation", 100)


SETPRIVILEGE("SeDebugPrivilege", 1) ;pour mettre le mode debug et pour pouvoir lire la mémoire (1 pour lactiver 0 pour le désactiver)

$Dll = DllOpen("user32.dll")

While 1
    If ProcessExists("wow.exe") Then ;si il trouve le processus wow.exe on passe à la suite
        $Processus = _MemoryOpen(WinGetProcess("World of Warcraft"))
        ExitLoop
    EndIf
WEnd

GUISetState(@SW_SHOW) ;On affiche la fenêtre

LoadAdresses() ;on initiale l'ojectmanager

$CurrentObject = _MemoryRead($ObjectManagerBase + $offFirstObject, $Processus, 'int') ;on trouve le premier objet

Local $i
While ($CurrentObject <> 0) And (Mod($CurrentObject, 2) == 0) ;si différent de 0 ou si pair on continu la boucle

    Switch (_MemoryRead($CurrentObject + $offTypeObject, $Processus, 'int')) ;selon le type de l'objet
        Case 1
            $i += 1 ;on incrémente $i pour chaque objet trouvé
        Case 2
            $i += 1
        Case 3
            ;Unité
            $ObjectPosition = GetObjectPos($CurrentObject, 3) ;donne la pos de l'unité
            GUICtrlCreateListViewItem(GetObjectName($CurrentObject, 3) & "|" & $ObjectPosition[0] & "|" & $ObjectPosition[1] & "|" & $ObjectPosition[2] & "|" & $ObjectPosition[3], $List)
            GUICtrlSetBkColor(-1, 0x60ff0000) ;Fond rouge
            $i += 1
        Case 4
            ;Joueur
            $ObjectPosition = GetObjectPos($CurrentObject, 4) ;donne la pos du joueur
            GUICtrlCreateListViewItem(GetObjectName($CurrentObject, 4) & "|" & $ObjectPosition[0] & "|" & $ObjectPosition[1] & "|" & $ObjectPosition[2] & "|" & $ObjectPosition[3], $List)
            If (_MemoryRead($CurrentObject + $offGuid, $Processus, 'int') = $LocalGuid) Then ;si le guid est égale à celui du joueur
                GUICtrlSetBkColor(-1, 0x6000ffff) ;Fond Turquoise
            Else ;sinon
                GUICtrlSetBkColor(-1, 0x6000ff00) ;Fond vert
            EndIf
            $i += 1

        Case 5
            ;GameObject
            $ObjectPosition = GetObjectPos($CurrentObject, 5) ;donne la pos du GameObject
            GUICtrlCreateListViewItem(GetObjectName($CurrentObject, 5) & "|" & $ObjectPosition[0] & "|" & $ObjectPosition[1] & "|" & $ObjectPosition[2] & "|" & $ObjectPosition[3], $List)
            GUICtrlSetBkColor(-1, 0x600000ff) ;Fond bleu
            $i += 1

        Case 6
            ;Sort ou équipement
            $i += 1
        Case 7
            ;Cadavre
            $i += 1
    EndSwitch

    $CurrentObject = _MemoryRead($CurrentObject + $offNextObject, $Processus, 'int') ;On lit l'objet suivant
WEnd
GUICtrlSetData($LabelResult, GUICtrlRead($LabelResult) & $i)

While 1 ;boucle infini pour attendre la fermeture de la fenerre
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch
WEnd

Func GetObjectPos($Object, $Type)
    Local $returnPos[4]

    Switch ($Type)
        Case 1 ;On retourne 0 car les items et conteneur n'ont pas de pos
            $returnPos[0] = 0
            $returnPos[1] = 0
            $returnPos[2] = 0
            $returnPos[3] = 0
        Case 2
            $returnPos[0] = 0
            $returnPos[1] = 0
            $returnPos[2] = 0
            $returnPos[3] = 0
        Case 3 ;Si c'est une unité ou un joueur...
            $returnPos[0] = _MemoryRead($Object + $offPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offRot, $Processus, 'float') ;Rotation
        Case 4
            $returnPos[0] = _MemoryRead($Object + $offPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offRot, $Processus, 'float') ;Rotation
        Case 5 ;GameObject
;~             WOW 3.0.9-
;~             $returnPos[0] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_POS_X * 4, $Processus, 'float')
;~             $returnPos[1] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_POS_Y * 4, $Processus, 'float')
;~             $returnPos[2] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_POS_Z * 4, $Processus, 'float')
;~             $returnPos[3] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $GAMEOBJECT_FACING * 4, $Processus, 'float')
;~             WOW 3.1.0+
            $returnPos[0] = _MemoryRead($Object + $offGOPosX, $Processus, 'float') ;Pos X
            $returnPos[1] = _MemoryRead($Object + $offGOPosY, $Processus, 'float') ;Pos Y
            $returnPos[2] = _MemoryRead($Object + $offGOPosZ, $Processus, 'float') ;Pos Z
            $returnPos[3] = _MemoryRead($Object + $offGORot, $Processus, 'float') ;Rotation
        Case 6 ;Sort
;~             WOW 3.0.9-
;~             $returnPos[0] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_POS_X * 4, $Processus, 'float')
;~             $returnPos[1] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_POS_Y * 4, $Processus, 'float')
;~             $returnPos[2] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_POS_Z * 4, $Processus, 'float')
;~             $returnPos[3] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $DYNAMICOBJECT_FACING * 4, $Processus, 'float')
        Case 7 ;cadavre
;~             WOW 3.0.9-
;~             $returnPos[0] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_POS_X * 4, $Processus, 'float')
;~             $returnPos[1] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_POS_Y * 4, $Processus, 'float')
;~             $returnPos[2] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_POS_Z * 4, $Processus, 'float')
;~             $returnPos[3] = _MemoryRead(_MemoryRead($CurrentObject + $offDescriptorFields, $Processus, 'int') + $CORPSE_FIELD_FACING * 4, $Processus, 'float')

    EndSwitch

    Return $returnPos ;on retourne le résultat sous forme de tableau
EndFunc   ;==>GetObjectPos

Func GetObjectName($Object, $Type)
    Switch ($Type)
        Case 3;unité
            Return _String_To_StringUTF8(_MemoryRead(_MemoryRead(_MemoryRead($CurrentObject + $offUnitName1, $Processus, 'int') + $offUnitName2, $Processus, 'int'), $Processus, 'char[128]'))
        Case 4;joueur
            Return _String_To_StringUTF8(GetPlayerNameByGuid(_MemoryRead($Object + $offGuid, $Processus, 'int')))
        Case 5;gameobject
            Return _String_To_StringUTF8(_MemoryRead(_MemoryRead(_MemoryRead($CurrentObject + $offGameObjectName1, $Processus, 'int') + $offGameObjectName2, $Processus, 'int'), $Processus, 'char[128]'))
    EndSwitch
    Return ""
EndFunc   ;==>GetObjectName


Func GetPlayerNameByGuid($guid)
    Local $mask, $base, $offset, $current, $shortGUID, $testGUID

    $mask = _MemoryRead($nameStorePtr + $nameMaskOffset, $Processus, 'int')
    $base = _MemoryRead($nameStorePtr + $nameBaseOffset, $Processus, 'int')


    $shortGUID = BitAND($guid, 0xffffffff)
    If ($mask = 0xffffffff) Then Return ""
    $offset = 12 * BitAND($mask, $shortGUID)

    $current = _MemoryRead($base + $offset + 8, $Processus, 'int')
    $offset = _MemoryRead($base + $offset, $Processus, 'int')

    If (BitAND($current, 0x1) == 0x1) Then Return ""
    $testGUID = _MemoryRead($current, $Processus, 'int')

    While ($testGUID <> $shortGUID)
        $current = _MemoryRead($current + $offset + 4, $Processus, 'int')

        If (BitAND($current, 0x1) = 0x1) Then Return ""
        $testGUID = _MemoryRead($current, $Processus, 'int')
    WEnd
    Return _MemoryRead($current + $nameStringOffset, $Processus, 'char[20]')
EndFunc   ;==>GetPlayerNameByGuid


Func LoadAdresses()
    $ObjectManagerBase = _MemoryRead(_MemoryRead($staticClientConnection, $Processus, 'ptr') + $offObjectManager, $Processus, 'int') ;trouve l'objectmanagerbase
    $LocalGuid = _MemoryRead($ObjectManagerBase + $offLocalGuid, $Processus, 'int') ;trouve le guid du joueur
EndFunc   ;==>LoadAdresses

Func _String_To_StringUTF8($String) ;Convertit une chaîne de charactère en chaîne UTF8
    Return BinaryToString(StringToBinary($String, 1), 4)
EndFunc   ;==>_String_To_StringUTF8
Je l'ai commenté autant que j'ai pu et ajouté les changements pour la 3.1.1

Voilà la partie sur l'ObjectManager est fini, c'est un très gros bout mais c'est très important, je vous conseille de le relire plusieurs fois et de modifier le code que j'ai donner pour comprendre comment ça fonctionne

fin
 

drave

Membre
Dec 21, 2009
40
0
571
:salut:
Ton tuto est super mais il a quelque chose que je ne comprend pas : je n'ai pas la fonction _readmemory ni _writememory je suppose donc que c'est un UDF ??mais ou le telecharger ??:svp:
 

tobor

Nouveau membre
Dec 21, 2009
1
0
561
43
wow 3.3 et Playerbase

Bonjour,

je suis en train de créer un utilitaire pour wow, en autoit et autohotkey.

ton tuto est très clair, mais pour la version 3.3 de wow , j'aurais les questions suivantes :

Playerbase = [[StaticAdress]+0x30]+0x28 , dans ton tuto,

Quelle est la valeur de StaticAdress pour la version 3.3 ?
ou comment puis je la retrouver ?

le +0x30 est il toujours valable pour la v 3.3 ?
idem pour le +0x28 ?

Evidement, les infos concernent la recherche de x, y, z et rotation du player courant.

je suppose que le problème à déjas été traité mais je suis bredouille dans ma recherche.

aurais tu une info susceptible de m'aider ?

cordialement,
Tobor
 

shark

Ivalice - Icecrown
V
Dec 19, 2009
675
0
581
29
Mais grâce à cela vous pouvez donc créer un WEH qui sera compatible avec les nouvelles versions de WOW non ? Pourquoi Deathsoft met tant de temps à proposer un WEH compatible avec les nouvelles versions si cela parait si simple ?
Merci et désolé ^^
 

dorian33

Membre
Mar 30, 2010
22
0
566
44
Pour ton tutoriel faut un minimum de programmation tu pourrais le dire.... Mais sinon excellent !!
 

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
Si tu veux crée des cheat, essai déjà de bien te débrouiller avec la mémoires, les pointeur, et Cheat-Engine...
Crée un cheat, ce n'est pas un petit truc vite fait bien fait aussi simple.


Bonne chance quand même Bye !
 

Dyazz

Haskell &amp;amp;amp;amp;amp;amp; a mp; amp; amp;
V
Dec 28, 2009
618
0
922
Crée un cheat est plus dur que crée un jeu (ce que je suis en train de faire)
 

ol31240

Membre actif
Jan 21, 2010
134
0
742
Un jeu ou un cheat :smile:
Après oui c'est sûr qu'un peu de programmation ne fera pas de mal pour comprendre un peu mieux ce tuto, qui est super (j'ai pas lu tout ce pavé texte)