Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 85

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6
[Tutorial] Zezenia Level Spy
Page 1 of 3 123 LastLast
Results 1 to 10 of 21

Thread: [Tutorial] Zezenia Level Spy

  1. #1

    [Tutorial] Zezenia Level Spy

    This is a tutorial for how I made a level spy for the game Zezenia.

    It basically patches the memory and creates a jump to a code cave in order to store the level spy address in another code cave then jumps back to the original code. This way I can just read the address where I stored the level spy address.

    You can find the source code here for reference:
    http://code.google.com/p/evremonde/s...a290levelspy.c

    This tutorial uses Cheat Engine:
    http://www.cheatengine.org/

    I logged in to Zezenia and opened Cheat Engine and selected Zezenia.exe from the list of processes.



    I walked to the depot and found the stairs on the first floor. I assumed from this spot my z-axis was 7, the same default z-axis of 7 in Tibia. I assumed by going up the stairs, my z-axis would change to 6. If I went underground, it would change to 8. So in order to spy upstairs, I had to change the z-axis. To find the z-axis address, I just walked up and down the stairs while scanning for 6 and 7 between floors.

    In Cheat Engine, type 7 into the value box and click First Scan.



    Then, walk up the stairs and then type 6 into the value box and click Next Scan.



    Then, walk down the stairs and then type 7 into the value box and click Next Scan.

    I repeated this process until I narrowed it down to just a few addresses.
    Then I had to determine which address is the level spy z-axis address by adding the addresses to the bottom list and then while on z-axis 7, I tried changing the values in the addresses to 6 until my client spied up one level. The minimap z-axis and player z-axis also seemed to be in this range so I had to choose the one that spied up one level to be right.



    I think this address is a pointer that changes everytime you open Zezenia, so I made a code cave that would store this address in a specific location.

    The address I got was 06F47704. (This addresses changes everytime, will be different for you!)

    Right-click on the address and choose "Find out what accesses this address". Next I walked up and down the stairs again to let the address get accessed.



    A window should pop up with this information in it:
    004b7016 - 8b 42 08 - mov eax,[edx+08]

    This is moving whatever is in edx+8 to eax. Click on the instruction and then click "More Information" and the "Extra Info" window will show up.

    My window said the value of the pointer needed to find this address is probably 06F476FC. Also, it showed that EDX=06F476FC and EAX=7. The 7 is being moved to eax from 06F476FC + 8, and 06F476FC + 8 = 06F47704, and 06F47704 is the level spy address I found earlier.



    Click on the instruction again and then click "Show disassembler"



    Now I needed to store the value of edx from this instruction:
    004b7016 - 8b 42 08 - mov eax,[edx+08]

    Because edx+8 held the level spy address. So I needed to jump from that instruction to a code cave, store the edx value in another code cave, then jump back to the original code. Then I would just read the value of the level spy address by reading the address of the address where I stored edx.

    Click "Scan for code caves" under the "Tools" menu.

    I got a lot of code caves on the list, and I chose to use the first two:
    00400019 -> jump here, store edx in the other code cave, then jump back to original code
    0040010F -> edx stored here in this code cave



    Now to create a jump to the code cave. Right-click on the 004b7016 instruction and click "Create jump and initialize Code-Cave".



    In the "Create Code-Cave" window type in 00400019 for the address and click OK. Then type in 17 and click OK. (Defaults to 40 but I found out later I only needed 17 bytes after making the code cave jump and counting how many bytes of space it used!)



    The instruction will now look like this:

    004B7016 - E9 FE 8F F4 FF - jmp 00400019
    004B701B - 90 - nop

    It is a patch of 6 bytes in size! It jumps to the first code cave.





    Now right-click on the instruction and click "Go to address" and type in 00400019 and click OK.




    You will arrive at 00400019 and the mov eax,[edx+08] instruction will now be here because of the jump patch.



    Now I needed to store edx in the other code cave.

    Now right-click on the 0040001F instruction that is after the other two instructions, and click "Assemble".

    In the assembler window type in:
    mov [0040010F],edx

    This will store edx at that code cave address for easy access. But it only stores edx, not edx+08, so I had to remember to add +8 when I read the address in my code!



    The assembler window will look like this after the code cave patch.
    It is a patch of 17 bytes in size!



    (I had to restart computer so at this point I have reloaded Zezenia and gone through the steps again, but the dma level spy address is different as expected!)

    At this point, the patching is done and is working it's magic. I go to add address manually and add the code cave address 0040010F and it is now holding the level spy z-axis address!



    The level spy z-axis address is shown as 4 bytes 117960724 decimal which is 707F014 hex.

    Now I add the missing +8 from edx+08 and it is the level spy z-axis address:
    707F014 + 8 = 0707F01C




    Now after doing all that mumbo jumbo, we know what bytes to write to memory in order to use this address in a program to level spy.

    0x00400019 0x8B 0x42 0x08 0x89 0x41 0x08 0x89 0x15 0x0F 0x01 0x40 0x00 0xE9 0xF1 0x6F 0x0B 0x00
    0x004B7016 0xE9 0xFE 0x8F 0xF4 0xFF 0x90
    0x0040010F address here + 8 = level spy z-axis address

    Here are the important parts of the code that make it work:

    Code:
    /* memory addresses */
    
    // level spy
    #define LEVELSPY_CAVE   0x00400019 // the first code cave, stores to edx
    #define LEVELSPY_HOLDER 0x0040010F // the second code cave, holds edx
    #define LEVELSPY_JUMP   0x004B7016 // instruction with edx that we jump from
    
    /* constants */
    
    // level spy
    
    // store the value of edx in the second code cave
    BYTE LEVELSPY_CAVE_PATCH[17] =
    {
        0x8B, 0x42, 0x08,                   // mov eax,[edx+08]
        0x89, 0x41, 0x08,                   // mov [ecx+08],eax
        0x89, 0x15, 0x0F, 0x01, 0x40, 0x00, // mov [0040010f],edx
        0xE9, 0xF1, 0x6F, 0x0B, 0x00        // jmp 004b701b
    };
    
    // jump to the first code cave
    BYTE LEVELSPY_JUMP_PATCH[6] =
    {
        0xE9, 0xFE, 0x8F, 0xF4, 0xFF, // jmp 00400019
        0x90                          // nop
    };
    
    // values for which floor to spy on, top to bottom, above to underground
    const int LEVELSPY_MIN = 0;
    const int LEVELSPY_MAX = 14;
    this part of the code writes the byte patches to memory.
    you have to use VirtualProtectEx with PAGE_EXECUTE_READWRITE or Zezenia will crash!
    Code:
    // initialize level spy
    void doLevelSpyInitialize()
    {
        DWORD oldProtection;
        DWORD newProtection;
    
        // level spy cave
        VirtualProtectEx(getGameProcessHandle(), (LPVOID)LEVELSPY_CAVE, sizeof(LEVELSPY_CAVE_PATCH), PAGE_EXECUTE_READWRITE, &oldProtection);
        WriteProcessMemory(getGameProcessHandle(), (LPVOID)LEVELSPY_CAVE, &LEVELSPY_CAVE_PATCH, sizeof(LEVELSPY_CAVE_PATCH), 0);
        //VirtualProtectEx(getGameProcessHandle(), (LPVOID)LEVELSPY_CAVE, sizeof(LEVELSPY_CAVE_PATCH), oldProtection, &newProtection);
    
        // level spy jump
        VirtualProtectEx(getGameProcessHandle(), (LPVOID)LEVELSPY_JUMP, sizeof(LEVELSPY_JUMP_PATCH), PAGE_EXECUTE_READWRITE, &oldProtection);
        WriteProcessMemory(getGameProcessHandle(), (LPVOID)LEVELSPY_JUMP, &LEVELSPY_JUMP_PATCH, sizeof(LEVELSPY_JUMP_PATCH), 0);
        //VirtualProtectEx(getGameProcessHandle(), (LPVOID)LEVELSPY_JUMP, sizeof(LEVELSPY_JUMP_PATCH), oldProtection, &newProtection);
    }
    this part of the codes reads whatever current level you are spying on and increases it by one. take note of the +8 because of edx+08!
    Code:
    // level spy up
    void doLevelSpyUp()
    {
        // get level spy address
        int levelSpyAddress = readBytes(LEVELSPY_HOLDER, 4) + 8;
    
        // get current level
        int currentLevel = readBytes(levelSpyAddress, 1);
    
        // get spy level
        int spyLevel = 0;
        if (currentLevel <= LEVELSPY_MIN)
            spyLevel = LEVELSPY_MAX; // loop back to start
        else
            spyLevel = currentLevel - 1; // decrease spy level
    
        // level spy up
        writeBytes(levelSpyAddress, spyLevel, 1);
    }
    Zezenia doesn't seem to have a classname and the titlename is always changing so I couldn't use FindWindow to get the process handle. I had to use EnumProcesses and EnumProcessModules to find Zezenia.exe

    Enumerating All Processes
    http://msdn.microsoft.com/en-us/libr...23(VS.85).aspx

    Well, I hope this tutorial has been helpful and gives you an idea of how it works and was made!

  2. #2
    Senior Member
    Join Date
    Oct 2008
    Posts
    208

    [Tutorial] Zezenia Level Spy

    Omg Rly Nice Tutorial!!

    Make A Cavebot!!! >.<


    Edit:
    Happy Birthday!!!!!!!!!!!!

  3. #3

    [Tutorial] Zezenia Level Spy

    Thanks, ALOT. This is really good.
    Also helps me with other cheats I was hanging on, for different games.

  4. #4

    [Tutorial] Zezenia Level Spy

    Wow, amazing

    Good job

  5. #5
    Junior Member
    Join Date
    Mar 2007
    Posts
    6

    [Tutorial] Zezenia Level Spy

    Nice work.

  6. #6
    Senior Member
    Join Date
    Mar 2007
    Posts
    766

    [Tutorial] Zezenia Level Spy

    Very nice game you have there K-Zodron, was it solo coded? I only see you as a programer on the website

  7. #7
    Senior Member
    Join Date
    Mar 2007
    Posts
    1,323

    [Tutorial] Zezenia Level Spy

    Wonderful!

    Didn't know one can mess around with code caves in cheat engine!

  8. #8

    [Tutorial] Zezenia Level Spy

    Quote Originally Posted by OsQu
    Wonderful!

    Didn't know one can mess around with code caves in cheat engine!
    Yeah cheat engine is actually pretty powerful. You can even run assembly scripts with it. and bind them to a hotkey. Cheatengine takes care of the dirty hotkey work for you.

  9. #9
    Junior Member
    Join Date
    Mar 2007
    Posts
    6

    [Tutorial] Zezenia Level Spy

    Quote Originally Posted by jeremic
    Very nice game you have there K-Zodron, was it solo coded? I only see you as a programer on the website
    Thanks. Yeah, I'm the only programmer in the team.

  10. #10

    [Tutorial] Zezenia Level Spy

    @K-Zodron: I like the way that you dinamically creates the data structures in the game. Its not like in Tibia, a fixed simple address for a given variable.

    @Evremonde: great tutorial dude :icon10:

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •