Wir schreiben einen Bot für MMORPG mit Assembler und Draenei. Teil 4

  • Tutorial
Hallo% username%! Schreiben wir also unseren Bot weiter. In früheren Artikeln haben wir gelernt, wie man die Adresse der abgefangenen Funktion für DirectX 9 und 11 findet, beliebigen Assembler-Code im Hauptstream des Spiels ausführt, ihn vor verschiedenen Schutzmethoden verbirgt und Informationen über die Welt um ihn herum erhält. Mit anderen Worten, wir können informierte Aktionen im Spiel ausführen. Und für den Anfang schlage ich vor, zu lernen, wie man sich bewegt!

Haftungsausschluss: Der Autor ist nicht verantwortlich für Ihre Verwendung der in diesem Artikel gewonnenen Erkenntnisse oder für Schäden, die durch deren Verwendung entstehen. Alle hier gemachten Angaben dienen nur zu Bildungszwecken. Speziell für Unternehmen, die MMORPG entwickeln, um mit Bots umzugehen. Und natürlich ist der Autor des Artikels kein Bot-Fahrer, kein Betrüger, und er war es auch nie.




Für diejenigen, die frühere Artikel verpasst haben, hier der Inhalt, und die alles gelesen haben, fahren Sie fort:
Inhalt

  1. Teil 0 - Finden eines Code-Einfügepunkts
  2. Teil 1 - Implementierung und Ausführung von Code von Drittanbietern
  3. Teil 2 - Verstecke den Code vor neugierigen Blicken
  4. Teil 3 - Unter den Augen von World of Warcraft 5.4.x (Strukturen)
  5. Teil 4 - Unter den Augen von World of Warcraft 5.4.x (In Bewegung)
  6. Teil 5 - Unter den Augen von World of Warcraft 5.4.x (Custom Fireball)

Es kam vor, dass die Interaktion mit dem Spielobjekt und die Bewegung durch Klicken in World of Warcraft mit einem Mausklick möglich ist. Wir werden aber keine Klicks simulieren, durch WinApi werden wir es kühler machen. Wir werden die Stelle abfangen, an der der Klick bereits vom Spiel verarbeitet wurde, wie ein Klick auf den Bildschirm, und er wird bereits von den Bildschirmkoordinaten zu den Koordinaten der Spielwelt übertragen. Zuerst erhalten wir die Adressen einiger Funktionen, die wir wirklich benötigen. Dies ist mit Hilfe unseres geliebten IDA-Debuggers ganz einfach:
    public enum FunctionWow
    {
        ClntObjMgrGetActivePlayer = 0x39B615,
        ClntObjMgrGetActivePlayerObj = 0x4FC6,
        FrameScript_ExecuteBuffer = 0x4fd12,
        Spell_C_HandleTerrainClick = 0x38f129,
        FrameScript__GetLocalizedText = 0x414267,
        IsOutdoors = 0x414b53,
        UnitCanAttack = 0x41ad3c,
        CGUnit_C__InitializeTrackingState = 0x41fb57,
        CGWorldFrame__Intersect = 0x5eef7b,
        CGUnit_C__Interact = 0x8D01D0,
    }
    public enum ClickToMove
    {
        CTM = 0x420543,
        CTM_PUSH = 0xD0EEBC,
        CTM_X = 0xD0EF2C,
        CTM_Y = CTM_X+4,
        CTM_Z = CTM_Y+4,
    }

Deklarieren Sie die WorldClick-Klasse:
public enum ClickType
{
    FaceTarget = 0x1,
    Face = 0x2,
    StopThrowsException = 0x3,
    Move = 0x4,
    NpcInteract = 0x5,
    Loot = 0x6,
    ObjInteract = 0x7,
    FaceOther = 0x8,
    Skin = 0x9,
    AttackPosition = 0xa,
    AttackGuid = 0xb,
    ConstantFace = 0xc,
    None = 0xd,
    Attack = 0x10,
    Idle = 0x13,
}
public static class WorldClick
{
    public static void ClickTo(float x, float y, float z, ulong guid, ClickType action, float precision)
    {
        if (Mathf.Abs(x) < 0.1 && Mathf.Abs(y) < 0.1 && (Mathf.Abs(z) < 0.1 && (long)guid == 0L))
            return;
        //память для 3х координат
        var positionAddress = Memory.Process.AllocateMemory(3 * sizeof(float));
        //guid типа ulong в 8 байт
        var guidAddress = Memory.Process.AllocateMemory(sizeof(ulong));
        //значение точности, до которой продолжать движение, я беру 0.5f
        var precisionAddress = Memory.Process.AllocateMemory(sizeof(float));
        if (positionAddress <= 0U || guidAddress <= 0U || precisionAddress <= 0U)
            return;
        Memory.Process.Write(guidAddress, guid);
        Memory.Process.Write(precisionAddress, precision);
        Memory.Process.Write(positionAddress, x);
        Memory.Process.Write(positionAddress + IntPtr.Size, y);
        Memory.Process.Write(positionAddress + IntPtr.Size * 2, z);
        var asm = new[]
        {
        "call " + Memory.Process.GetAbsolute(FunctionWow.ClntObjMgrGetActivePlayer ),
         //Проверка на наличие активного игрока
        "test eax, eax",
        "je @out",
         //Получаем указатель на объект - понадобится ниже
        "call " + Memory.Process.GetAbsolute(FunctionWow.ClntObjMgrGetActivePlayerObjAddress),
        "test eax, eax",
        "je @out",
        "mov edx, [" + precisionAddress + "]",
        "push edx",
        "push " + positionAddress,
        "push " + guidAddress,
        "push " + (int)action,
        "mov ecx, eax",
        //Вызываем ClickToMove()
        "call " + Memory.Process.GetAbsolute((int)ClickToMove.CTM),
        "@out:",
        "retn"
        };
        Memory.Hook.InjectAndExecute(asm);
        Memory.Process.FreeMemory(positionAddress);
        Memory.Process.FreeMemory(guidAddress);
        Memory.Process.FreeMemory(precisionAddress);
    }
    public static ClickType GetClickTypePush()
    {
        return (ClickToMoveType)Memory.Process.Read((int)ClickToMove.CTM_PUSH, true);
    }
    public static Vector3 GetClickPosition()
    {
        return new Vector3(
                Memory.Process.Read((int)ClickToMove.CTM_X, true),
                Memory.Process.Read((int)ClickToMove.CTM_Y, true),
                Memory.Process.Read((int)ClickToMove.CTM_Z, true));
    }
}

Nun, das war's, jetzt können Sie durch die Weiten von Azeroth rennen mit:
WorldClick.ClickTo(x,y,z, 0, ClickType.Move, 0.5f);

Das ist alles für heute. Sie haben viele interessante und praktische Dinge gelernt. Sie können es auf einem Piraten überprüfen, und wenn Sie sicher sind, den Code zu verschleiern, können Sie es sogar auf dem offiziellen Server mit einem Starteintrag ausführen, um es nicht zu riskieren. Schließlich haben Blizzard-Mitarbeiter plötzlich auch Habr gelesen.

Jetzt auch beliebt: