Page 1 of 2 12 LastLast
Showing results 1 to 20 of 27

Thread: Maphack Tutorial Series

  1. #1
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default Maphack Tutorial Series

    Here is a series of tutorials that discusses how to make a maphack for starcraft version 1.15.2. Do not copy these tutorials, instead link to this location. If you have any questions or comments please feel free to PM me. Thanks, hellinsect.

  2. #2
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default CHAPTER 1

    CHAPTER 1

    Before we get started you will need the following items.

    Artmoney
    OllyDBG
    PowerStrip - to restore the resolution
    A brain – making a map hack is not a simple process
    A C++ complier - I use Microsoft Visual C++ 6
    Some basic C++ knowledge – passing perimeters into a function etc
    Some basic low level assembly knowledge

    One of the earlier tutorials written for a starcraft maphack about 15 patches back said, starcraft makes use of a DLL outside the executable module to store the data about what is visible on the map. The point is that the addresses of the array to what is visible and invisible to you and other players can change even between games, because starcraft frees up that memory when not in a game and then asks for space again and could very likely be given a different section of data in the RAM. But that’s ok because we are only looking for the function that access this data. We can’t change this data because starcraft uses this data to determine if a unit is allowed to attack other unit. For example, a blinded tank cannot attack a medic that is in its target range if the medic blinded it. If that tank were to suddenly attack the medic, that it couldn’t see, the player who owned the tank would be dropped from the game. In fact this data is compared to what every other player has. If any has been changed, the player who has it changed will be dropped.

    So we first need to find this data array. In order to do that we will need to create a custom map. After you have created a custom map, go into single player mode, so you can used the cheat. Give yourself some units so that you can move around. Now we’re not sure what we are looking for. For all we know this data array could contain all the information there is to know concerning the visibility of a certain spot. What player 1,2,3,4,5,6,7,8 can see and does player 1,2,3,4,5,6,7,8 have detection there. Searching for 0 and then 1 probably won’t work, and searching for a value that increased then decreased has a %50 percent chance of working. Not much to go off, but there is some good points. The data we are looking for is clustered together in an array. This way the starcraft functions don’t have to depend on complicated techniques to access this data. Now to save time we are only going to search for values that have changed. Now go into single player mode and start a game. Now Alt-Tab out to Artmoney and press search. And then search for unknown value. Now because you are in single player mode type in “black sheep wall” which will enable the “fog of war” cheat. Now go back to art money and filter with “value has changed”. Do this a few times until you have the addresses down to about 300,000

    Now you may be thinking how could I possibly go through that much memory? Well you can’t. We have to try something simpler. So get out of the game you are in. Then go to OllyDBG and under file select attach and attach the starcraft process. Then press play. After this go to view and select memory. Now you should see a list of all the memory sections that the starcraft application uses. Now right click anywhere on the list and select actualize.

    Now remake the single player game. After that go back to OllyDBG and select actualize again. Now all the memory sections that were just created or committed are in red. Now if you were to right click on one of the red memory modules you would see a list of options. Go down to copy and select address. With your brain or a hex calculator you can simply add the size to the base which will give you the end address of the memory section. The result you got and the base address is your search range. Now if you can figure out a fast way to search these memory sections, great! It’s too hard to explain a fast way to search them.

    Now go back to art money and start a new search. Use custom range and search away. When you find a large section of data that has changed, freeze them and go disable/enable the cheat. After going across several values that don’t do anything, when you freeze them, you will find a large section of data that when frozen continues to make large sections of the map visible. Note that these values are 1 byte values. You will also notice that this data is equal 255 when no units can see the location it represents, 0 when the cheat is enabled, 254 when you can see it, 253 when the computer can see it etc. Now you have values that you can use to instantly find this array whenever you want to in the future.

    Now that we have found this data array, now we need to get ready to set a break point on this data. So install PowerStrip or another application that can restore your resolution if you haven’t already done so. Next we want to find the code that accesses this array. First make sure that the address to this data array did not change; like if you start a new map the data might change to a new location. Anyways open up OllyDBG and attach it to starcraft blah blah blah. Anyways, in the CPU window, select the memory box/hex editor and right click and select go to. Go to the address that you just got from art money. If you can find out what location this memory address represents on the map. This way you can bring units to it. Now we need to find out what functions are writing and reading this data. So right click on it and select breakpoint and click on memory access. Now go back into the game. If you did everything right the screen should instantly freeze. Press Ctrl + Alt +S so PowerStrip restores your resolution. Now go to OllyDBG and it should be stopped at the section of code that accesses this data. Now it is important to write down the address of this function. After doing that press play and it should take you to the next section of code that accesses this data. After you have written three or four different addresses down, you need to go back to the first one you were at. You can to this by pressing the minus key. Anyways, go back to the first and NOP it out. This will stop it from tripping the breakpoint. After this go back and see what game functions are being messed up. Keep notes on what function access does what. Bring a unit to the spot. Look at the spot. Each time there is a break point NOP it out or JMP over it or something and keep taking notes until you find the functions that do the following….

    1 Checks to see if the map needs to be printed - gets ride of the darkness.
    2 Checks to see if the map needs to be printed on the mininmap. – gets ride of minimap darkness.

    3 Checks to see if units need to be printed on the screen. Only checks the location that the units are at - this is necessary for the maphack.
    4 Checks location see if it needs to print something on the minimap – necessary for the minimap hack

    Once you have found these functions. Study them. Here are the addresses to these functions.

    Here is a list of addresses I got using this method.

    00480BA0 - start of darkening command. Makes the map not visible
    00480B08 – start of lighting command. Makes the map visible
    0047FFE2 – Prints the whole map when NOPed// but not the units
    004A3903 – Makes the whole minimap clear when Noped//

    It took a lot more work but by following certain functions back I found these addresses

    004989F0 When NOPed all units are removed from map - does not drop
    004A4760 Start of function that prints units on minimap

    Maybe later on I will write Chapter 2.

  3. #3
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default CHAPTER 2

    CHAPTER 2

    Let’s set some things straight. By now you should know where the array is. You should have done this by searching for 0 when the cheat was enabled and 255 when the cheat was off.




    Here we found the address that represents the visibility of the map, and know where it is on the map so I can bring units to it. For me this address was 02CE03E8. Now unfreeze all the values and go to OllyDbg.



    As you can see this value is FF because I have frozen it in ArtMoney. The next step will be to go to the value we are looking for. So go to this address.

    The next step will be setting a breakpoint on the address that you found.



    Now go back into your game and it should instantly freeze. Press Ctrl+Alt+S to restore you resolution.


    Notice how the address in the CPU bar is the same as the one we set the breakpoint on. You will need to copy down every address so you can keep notes on them. Press play and OllyDBG should instantly bring you to another breakpoint and then another breakpoint.

    004A3903 MOV ECX,DWORD PTR DS:[ECX]
    0047FFE2 MOV ECX,DWORD PTR DS:[EDI]
    0049C339 TEST DWORD PTR DS:[EAX],EDX

    After these three breakpoints it should resume the game. Remove the breakpoint by right clicking and selecting remove memory breakpoint. Now it’s time to NOP out the code that accesses this data. Using the + and – key you can toggle back and forth between the last 3 breakpoint. NOP each one of them out and go into the game to see what happens.



    Anyways you can see that…

    004A3903 Prints map on MM if NOPed
    0047FFE2 Prints map on screen when NOPed
    0049C339 nothing

    Now that these 3 values have been NOPed they won’t interfere with what we want to do next which is to find more breakpoints.

    So keep doing what we just did, soon you should have a nice long list of breakpoints. It should look like this.

    0047D250 MOV EDI,DWORD PTR DS:[EDX]
    0049C1D2 TEST DWORD PTR DS:[ESI],EAX
    00480BA0 OR DWORD PTR DS:[EAX],0FF
    00480B08 AND DWORD PTR DS:[EAX],EDX
    00480543 MOV EDI,DWORD PTR DS:[EDX+ECX*4]
    0048054B MOV DWORD PTR DS:[ECX],EDI
    00480550 MOV ECX,DWORD PTR DS:[EDX+ECX*4]
    00480436 AND DWORD PTR DS:[ESI],EDX
    0048043B MOV EDX,DWORD PTR DS:[ECX+EDX*4]
    004804A8 AND DWORD PTR DS:[ECX+ESI*4],EBX
    004804B1 MOV ESI,DWORD PTR DS:[ECX+ESI*4]

    You should have to NOP all these out before you can look at the location etc. Now if you are sure you know where the location is at. Bring a unit to it now. It may take a while but as soon as the unit is at that location you should get a break point.

    Wait! That won’t work. Here’s why. The functions we are attacking belong to the computer and other players. They see if they if units can attack your units and other units that are on the map. They DON’T print units on the screen. Your units are always printed on the screen no matter what and might have no correlation to the visibility of the location. So we’re going to have to find the location that represents the visibility of on enemy unit. This can be done by searching for the values 253 and 0 if the computer is always player 2. Once we find these values, we need to freeze a large section of them with the cheat on. Now there should be some enemy units still on the map. Start unfreezing values until you find the one value that represents the location that the enemy unit is standing at. Now you need to start the process all over again. Set a break point on this new location. And start NOPing out the addresses that access the data.

    00402545 MOV EBX,DWORD PTR DS:[EDX]

    Jackpot we just caught the function that was checking to see if the unit needs to be printed on the screen. Here is the address of the code we found. Let’s move 0 into EBX. We can use a trick that is used to delete the values in registers which would be to XOR it.

    Ok lets XOR it out. To do this press the space bar. Then type in “XOR ebx,ebx”.

    And we can now see all the units on the map. Or at least starcraft never removes units from the map. You can also select units that don’t appear on the map.

    Now if we follow this function we will be able to find the function that prints units on the screen.

    Maybe later on I will write Chapter 3.
    Last edited by hellinsect : 07-03-2008 at 09:16 PM

  4. #4
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default CHAPTER 3

    CHAPTER 3

    By now I am sure you are thinking “How can we make the maphack? Who cares about following functions back? Just tell us how to make the map hack.” Well that’s not how you make a maphack. So we figured out that…

    00402545 MOV EBX,DWORD PTR DS:[EDX]

    …is the magic function that we need to follow back. The next step to making a working maphack is to follow this function back. This will give us the functions that print dots on the minimap, print units on the screen, let you select enemy units and might let you hear the units. I haven’t done any research into how starcraft game play sound works. Now go into a LAN game or an online game. Doesn’t have to be with anyone, we just don’t want the game to pause every time you Alt+Tab out. Now fire up OllyDBG and in the code window Ctrl+G to 402545.



    Look over this function. You can clearly see that this function doesn’t call any functions. This function also doesn’t write data to anywhere. This means that it is returning a value. We need to go to the mother function to see what it does with the value that was returned. To do that press Ctrl+A to analyze the code. Next go to the top of the function and right click. Select go to and then select call from 48753B.



    As you can see AL is being written into EBP-8. Then you can see EAX being XORed out a little ways down. If you NOP this command out enemy units aren’t printed on the screen anymore! Also note that AL is a 1-byte value.



    Let’s assume this function is updating the active unit data. We need to find where this active unit data is. To do this we will need to place a toggle point on this code by pressing F2. It should break instantly because you’re in an online game.



    Press play to view the next break point. Ass you can see 12FDF8 does not change. This means that 12FDF8 contains a temporary variable that’s being accessed a little ways down in the code. You can press F7 to follow the code down to the return to the function that called this function. As you can see the function that called the function we were at is too complicated to understand. We are going to have to set a breakpoint on this Temporary variable.



    If you have done you research you will know that temporary variables are stored on the stack. This is one of the few times we will ever need to use the stack window. Scroll up the stack window a little ways until you find 12FDF8 or whatever it happens to be on your computer.



    You can see that this temporary variable is already above ESP just waiting to get written over. This is good because we can instantly tell that this data will never be used again or it will be used very soon. So keep following the code down. And scan for any code that might be accessing this part of the stack. If you keep following it you will come to a section of code that jumps ESP right across it before pushing anything more onto the stack.



    If you set a breakpoint on this local variable you will realize that it is never accessed until the function cycle trashes the stack. It’s just good to know this. Anyways we can’t set a breakpoint on it and go into the game because we will only hit it once in about a thousand times.

    So let’s do some thinking. Maybe enemy units have not had to change printing status. Remember, your units are always printed and the computer hasn’t needed to change printing status with any of the units it has on the map. Maybe the compiler preserves local variables until the function that called the local variable returns. This makes sure the code isn’t buggy. If this is true then the test we saw way back was used to see that nothing needed to be changed.



    This compare statement checks to see if something needs to be changed. If so the jump is taken to the code that changes the visibility of the unit. Select the jump statement and press enter. This will take us to where the jump leads to. Set a toggle point on the code the jump function jumps to. Now go back into the game and move one of your units until you can see the computer’s unit. Just as you’re able to see the enemy unit the breakpoint is triggered. Now F7 down until the local variable is accessed.



    We caught it accessing this local variable. The funny thing is its pushing it as a perimeter of the next function. Let’s see what this function is all about.



    Right in the beginning it loads this data into DL. Now play the function down and you will see that it writes this data into an address.



    If you compare the address it writes to with other enemy units, as they appear, you will notice a small change in the address it writes to. This is good because we might have found the data array that stores data on each active unit. If you follow this function, when units are being removed, you will notice that the code just up from where we are at is used to make units disappear.

    0049719C MOV BYTE PTR DS:[EBX+C],DL // removes units
    004971BB MOV BYTE PTR DS:[EBX+C],DL // places units

    You can use OllyDBG to get the data address that represents the visibility of an enemy unit. You can test it in Artmoney if you like.

    Once you got it set a breakpoint on it and do what we did in chapter 2 and what we just did in chapter 3. Your goal will be to find the functions that…

    check to see if a dot needs to be printed on the minimap.
    check to see if the unit needs to be printed on the screen.

    There are other functions that check to see if the unit can be selected or if you can hear the sound it makes. If you ever want to select or hear enemy units, you can’t see, you must debug these functions as well.

    Let’s find these functions.

    I am going to set a break point on the address 0063FC8C. Right now this address represents a specific unit on the map. Make sure you know what enemy unit it represents.



    I am going to set a breakpoint on this location and work at getting a list of code that accesses this function. Again this might be a redundant process, but it’s all part of debugging starcraft. Move your unit towards this enemy unit so you can see it and then away so you can’t see it while you have the breakpoint set on the address that represents it, blah blah blah. Now if you have done everything correctly you should find the following addresses that have accessed this data.

    00497FB0 TEST BYTE PTR DS:[ESI+C],BL // prints unit skins on the screen
    004A44F5 MOVZX EAX,BYTE PTR DS:[EDX+C] // XORed enemy unit miminap
    00487543 CMP BYTE PTR DS:[EDX+C],AL
    004971BB MOV BYTE PTR DS:[EBX+C],DL // orders unit placement
    00487581 TEST BYTE PTR DS:[ECX+C],DL
    0048755C MOV AL,BYTE PTR DS:[EBX+C]
    0049790D MOV DL,BYTE PTR DS:[EAX+C]
    0049719C MOV BYTE PTR DS:[EBX+C],DL // orders unit removal
    0046F7EB MOV CL,BYTE PTR DS:[EDI+C] // clicking on enemy unit
    004C0598 TEST BYTE PTR DS:[ECX+C],AL // click unit
    0046F569 TEST BYTE PTR DS:[EDX+C],AL // click box

    You should have noticed the following code accesses are used to print units on the screen and minimap.

    00497FB0 TEST BYTE PTR DS:[ESI+C],BL // prints unit skins on the screen
    004A44F5 MOVZX EAX,BYTE PTR DS:[EDX+C] // XORed enemyunits miminap

    If we are going to make a working maphack we will have to patch the following functions.

    Maybe later on I will write Chapter 4.

  5. #5
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default CHAPTER 4

    CHAPTER 4

    We have made a lot of progress with our maphack. In tutorial 3 we figured out that the following code checks each unit before printing it on the screen, to see if its visible or not.

    00497FB0 TEST BYTE PTR DS:[ESI+C],BL // prints unit skins on the screen

    If you NOP out the jump statement that jumps over the function that prints units on the screen, you will be dropped form the game.



    You can see that it’s testing the data and jumping over the call if the unit is not printed.
    So select the call statement and press enter. Set a toggle point and follow the code down the function with F7.




    Right at the start of the function you will notice that ECX is being accessed, increased and then used as a multiplier of where ESI is written to. Then it is being stored back. So NOP out the code that this address is written to and no units appear on the map. Now we want to make sure this is the code we are looking for. You’re welcome to NOP this write command and see what happens. You can see that no units are printed on the screen. This data must represent the units that are being printed on the screen. So in the data window, go to 6C4A1C.



    YOU can see a long list of starcraft addresses. Remember that these addresses are taken off in reverse order. To the left you can see a bunch of data. And there is ECX in the red circle. I am guessing that it was declared in the source code right before this array was declared. Go to a custom map that doesn’t have so many units or you will be pressing the play button for several minutes because 50 stacked minerals is a lot of units to go over.

    I changed the appearance to make it easier to understand.




    Next we need to set a breakpoint on the first address in this array. If you press the play key a few times you will notice that starcraft dynamically reads data from the array by moving it around, taking it all off and writing it all back. We don’t want to mess up this dynamic process with NOPs. So instead just copy the code, and leave on X in the comment column so you won’t copy the code twice. If you did everything correctly you should get the following list.

    0042D4B7 |. 8934CD 1C4A6C00 MOV DWORD PTR DS:[ECX*8+6C4A1C],ESI
    0042D422 |. 8B3CC5 1C4A6C00 |MOV EDI,DWORD PTR DS:[EAX*8+6C4A1C]
    0042D43A |> 8934CD 1C4A6C00 MOV DWORD PTR DS:[ECX*8+6C4A1C],ESI
    0042D477 |. A1 244A6C00 |MOV EAX,DWORD PTR DS:[6C4A24]
    0042D48C |. 8915 244A6C00 |MOV DWORD PTR DS:[6C4A24],EDX
    0042D366 |. A1 244A6C00 MOV EAX,DWORD PTR DS:[6C4A24]
    0042D3C3 |. 891CCD 1C4A6C00 |MOV DWORD PTR DS:[ECX*8+6C4A1C],EBX
    0042D482 |. 8B14F5 1C4A6C00 |MOV EDX,DWORD PTR DS:[ESI*8+6C4A1C]
    0042D3DA |. 8914CD 1C4A6C00 MOV DWORD PTR DS:[ECX*8+6C4A1C],EDX

    Look up in the code a little ways and you can see all the X’s in the comment column. As you can see they are all part of 3 different functions.

    0042D422 access \\ function1
    0042D43A write \\ function1

    0042D477 access \\ function2
    0042D482 access \\ function2
    0042D48C write \\ function2

    0042D366 access \\ function3
    0042D3C3 write \\ function3
    0042D3DA write \\ function3

    0042D4B7 write \\ main function

    We are only concerned with code that is reading this array. Data that is writing to it doesn’t mean anything to us. Remove the breakpoint and start NOPing the code that reads this data. Note that you will have to XOR the access in function 3. When you XOR the read code in function 3 you will notice no more units appear on the screen. Now select the modified XOR statement and Alt-backspace it to restore it. Let’s look down the rest of this function to see what it does with this value.



    As you can see it’s right away storing the value in EAX. Then it writes it to the address in EDI. Let’s try NOPing out the code that writes to the address in EDI. This makes all the units disappear from the map. EDI is being increased by 4 each loop cycle. Lets see where this function was being called from. You can see that the function above stores data in EAX. Now go to the top of this function and right click. Select go to call from 4989E0. You will see the following code.



    Right after it returns it tests EAX to see if it is 0. If EAX is 0 then it jumps across the following function. If you place a toggle point on EAX you will find it sometimes contains an address and sometimes is zero. We can’t NOP it out because it contains zero when it needs to jump. Instead press the spacebar and make it an absolute jump. Change JE to JMP. Go back into the game and no units appear on the map. Now we have gotten a lot deeper into the code. I believe its time to test our code again online with other players. Make sure that the only thing you have changed is this one jump statement.

    004989E7 JE SHORT StarCraf.00498A0F // before
    004989E7 JMP SHORT StarCraf.00498A0F //after

    We just removed all the units from the screen without getting dropped. Now we are close to where we need to be. Now select the following call and press enter.



    The first thing we do is NOP out the following calls. You will notice that when you NOP out the one circled in red no units appear on the screen. Go into this function by selecting call and pressing enter.

    Again NOP out each of the two calls and see what happens. When you NOP out the second call no units appear on the screen.



    Now we have gone too far. Because this call can call different functions based on what ESI is. It’s probably some kind of complicated graphics call. So we need to back up to find out what is going on. The first step in doing this will be to figure out where the address way back in EAX came from. Not much we can do when its zero. So back up to the function that first set EAX.



    Select the code that is writing to EAX and set a toggle point on it. Once it breaks notice how EBX is the amount of units you can see. You will also notice that there are a few extra addresses in this array. Anyways you can see it doesn’t delete this data. These are probably junk addresses of units that are no longer printed the screen.

    Anyways let’s make a patch that will push all these addresses into EAX. As well as the data that’s not updated in the bottom of the array. This should make some enemy units appear on the map. Now let patch it to print units in reverse order.

    You will need to XOR out the command we found in chapter 3.

    0047FFE2 MOV ECX,DWORD PTR DS:[EDI] // before
    0047FFE2 XOR ECX,ECX // after

    Next you will need to change:


    To:


    Finally we will need to change:


    To:


    If you have studied this array you will realize it never deletes data off of it, it only writes over it. So when you go over to the enemy base and then leave, some enemy units remain on the screen. You can also see that units are being printed in the wrong order.



    With a little more research and debugging you could modify this code to print all the units you want to see on the map.

    Well the last thing I will cover in this Chapter will be how to make a DLL. Let’s make a DLL that will write this patch for us, that way we won’t have to use the debugger.

    So we will need to set memory access, insert this patch, and then restore the previous memory access.

    Here is the source code that will write this patch. I recommend reading and looking up the code you don’t understand. Anyways you can compile this source code in visual C++ 6 under a Dynamic Link Library project.

    Code:
       #include "stdafx.h"
                   
       DWORD WINAPI maphack(LPVOID lpParam); 
        
       DWORD WINAPI maphack(LPVOID lpParam)
       {
                   DWORD OldAccessRights;        
                   int OffsetA = 0x004989D9;
                   int *Offset1 = (int*)0x0042D4A4;
                   int *Offset2 = (int*)0x0042D4A7;
                   int *Offset3 = (int*)0x0047FFE2;
        
        
        
                   VirtualProtect((int*)OffsetA, 0x26, PAGE_EXECUTE_READWRITE, &OldAccessRights);
        
                   *(BYTE*)(OffsetA)     = 0xA1;
                   *(BYTE*)(OffsetA+0x1) = 0x00;
                   *(BYTE*)(OffsetA+0x2) = 0x23;
                   *(BYTE*)(OffsetA+0x3) = 0x6C;
                   *(BYTE*)(OffsetA+0x4) = 0x00;
                   *(BYTE*)(OffsetA+0x5) = 0xEB;
                   *(BYTE*)(OffsetA+0x6) = 0x09;
        
                   *(BYTE*)(OffsetA+0xC) = 0xEB;
                   *(BYTE*)(OffsetA+0xD) = 0xF2;
                   *(BYTE*)(OffsetA+0xE) = 0x90;
                   *(BYTE*)(OffsetA+0xF) = 0x90;
        
                   *(BYTE*)(OffsetA+0x21) = 0x40;
                   *(BYTE*)(OffsetA+0x22) = 0x90;
                   *(BYTE*)(OffsetA+0x23) = 0x90;
                   *(BYTE*)(OffsetA+0x24) = 0x90;
                   *(BYTE*)(OffsetA+0x25) = 0x90;
        
                   VirtualProtect((int*)OffsetA, 0x26, OldAccessRights, &OldAccessRights);
        
        
                   
                   VirtualProtect(Offset1, 4, PAGE_EXECUTE_READWRITE, &OldAccessRights);
                   *Offset1 = 0x10A3C033;
                   VirtualProtect(Offset1, 4, OldAccessRights, &OldAccessRights);
        
                   VirtualProtect(Offset2, 4, PAGE_EXECUTE_READWRITE, &OldAccessRights);
                   *Offset2 = 0x006C4A10;
                   VirtualProtect(Offset2, 4, OldAccessRights, &OldAccessRights);
        
                   VirtualProtect(Offset3, 4, PAGE_EXECUTE_READWRITE, &OldAccessRights);
                   *Offset3 = 0x158BC933;
                   VirtualProtect(Offset3, 4, OldAccessRights, &OldAccessRights);
        
                   return 0;
       }
        
       BOOL APIENTRY DllMain(HANDLE hModule, DWORD CurrentState, LPVOID lpReserved)
       {
                   if (CurrentState == DLL_PROCESS_ATTACH)
                   {
                               CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)maphack,NULL,NULL,NULL);       
                   }
                   else
                   {
                               return 1;
                   };
                   return 1;
       }
    Now this hack will…

    …print the map on the screen.
    …print units in the wrong order.
    …use the junk data in the array to print some enemy units.

    Maybe later on I will write Chapter 5.

  6. #6
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default CHAPTER 5

    CHAPTER 5

    We have all heard the saying “help your self”. In this tutorial we will make a DLL that can help it’s self to the data starcraft has.

    The first thing we have to do is disable starcraft’s ability to write data in the array that’s printed on the screen. It’s going to be our job to write to this array from now on. We can do this by NOPing out the following commands.

    0042D48A MOV DWORD PTR DS:[EDI],EAX

    Below is the C++ code that will NOP this command out.

    Code:
    VirtualProtect((int*)Offset1, 2, PAGE_EXECUTE_READWRITE, &OldAccessRights);
    *(BYTE*)(Offset1)   = 0x90;
    *(BYTE*)(Offset1+1) = 0x90;
    VirtualProtect((int*)Offset1, 2, OldAccessRights, &OldAccessRights);
    We want to make sure that the right data is in the array at the right time. We have to make a jump to our function right before the function that prints units on the screen. This will update everything right away at the right time. A simple hook should allow us to do this.

    The next step will be to inject a hook into this function. Remember, although it may take some focus; insert this hook so as to disturb the least amount of code possible. You may think some code is unnecessary and then suddenly starcraft crashes or you are dropped because its not there. Here is a simple hook that I created for starcraft.

    Code:
       #include "stdafx.h"
        
       DWORD WINAPI maphack();
       DWORD OldAccessRights;
       DWORD OffsetA = 0x4989D9;
       DWORD OffsetB = 0x42D48A;
       DWORD *OffsetC = (DWORD*)0x4989E7;
        
       void UpdateUnitArray()
       {
        
                   //C++ hack-code goes here
        
       }
       void __declspec(naked) PrintUnits()
       {
                   __asm
                   { 
                               pushfd
                               pushad
                   }
        
                   UpdateUnitArray();
        
                   __asm
                   {
                               popad
                               popfd 
                               test eax,eax
                               jmp OffsetC
                   }
       }
        
       void CallPatch(void *pDest,void *pSrc)
       {
                   VirtualProtect(pSrc, 16, PAGE_EXECUTE_READWRITE, &OldAccessRights);
                   *(BYTE*)((DWORD)pSrc)    = 0xE9;
                   *(DWORD*)((DWORD)pSrc+1) = (DWORD)pDest - (DWORD)pSrc - 5;
                   *(BYTE*)((DWORD)pSrc+0xC) = 0xEB;
                   *(BYTE*)((DWORD)pSrc+0xD) = 0xF2;
                   VirtualProtect(pSrc, 16, OldAccessRights, &OldAccessRights);
        
                   VirtualProtect((int*)OffsetB, 2, PAGE_EXECUTE_READWRITE, &OldAccessRights);
                   *(BYTE*)(OffsetB)   = 0x90;
                   *(BYTE*)(OffsetB+1) = 0x90;
                   VirtualProtect((int*)OffsetB, 2, OldAccessRights, &OldAccessRights);
       }
        
       DWORD WINAPI maphack()
       {
                   CallPatch(&PrintUnits,(PBYTE)OffsetA);
        
                               //loop-code for in-game hotkeys
        
                   return 0;
       }
        
       BOOL APIENTRY DllMain(HANDLE hModule, DWORD CurrentState, LPVOID lpReserved)
       {
                   if (CurrentState == DLL_PROCESS_ATTACH)
                   {
                   CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)maphack,NULL,NULL,NULL);       
                   }
                   else
                   {
                               return 1;
                   };
                   return 1;
       }
    I recommend that you study how this hook works. This hook allows us to write the rest of our maphack in C++. The next goal would be to write the code that does what the real functions do and a little extra.

    If you compile this code as a DLL and then inject it into starcraft starcraft will jump to our function, which is outside of starcraft’s main code. After you have injected this DLL into starcraft attach OllyDBG. Go to 4989D9. Notice how there is a jump statement to the code we created with our DLL. Now we have a platform from witch we can do a lot with C++.

    To list a few of our options we can…

    …declare our own arrays, integers and other data types.
    …write to these data types once we have declared them.
    …read data from starcraft.
    …over write the arrays and counters that starcraft doesn’t care about.
    …insert logic.

    I was wondering if everyone understands and can take it from here, or do I need to show people how to write C++ code into…

    void UpdateUnitArray()
    {
    //…here?
    }

    Maybe later on I will write Chapter 6.

  7. #7
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default

    CHAPTER 6

    We know that when we change code in certain places all the units are shown on the map. However we are dropped. We also know that starcraft doesn’t care about the data in the array that gets printed on the screen. I am not sure if anyone is still following me, but I will do my best to show people how to patch the functions so that all the units are printed on the screen.

    We will need to do all the tasks involved in generating the array that gets printed on the screen. There are several functions that serve together to complete this task. I would say you could write your own c++ code to do these tasks, however when you look at the code you created in a debugger you will realize that your code is performing the operations very inefficiently. You might have to work out a few bugs also, depending on how long you have been programming in C++. The point is we just want a working maphack. This tutorial will teach you how to be ASM source code rippers.

    If you have studied the functions that perform the tasks of printing the final unit array, you will realize that there are 7. You will also realize that they are all part of 2 different sub function groups. Now I would rather play things save and insert 2 hooks, one into each sub function group. This is incase one function is called way less then the other or vise versa. Remember these hooks are just inserted so that our function will do the tasks of the “real” functions at the same time.

    Below is the location and description of each function. They are divided into the 2 groups.

    Group 1:
    Code:
    4BD030 - intro functions which passes to arguments into 00497F70
    
    497F70 - checks each unit to see if it is visible or cloaked
    42D4B0 - stacks all the visible units in the right order in a huge array with data
    42D3F0 - helper function which helps 0042D4B0 with its job.
    Group 2:
    Code:
    4989E0 - calls 42D450 then calls the graphics function.
    42D450 - puts the units in the graphics array that the graphics function will use. 
    42D360 - helper function which helps 42D450 with its job.
    I recommend that you review each of these 7 functions and there descriptions.

    Let’s start with the function that is calling the first function we are going to patch. As you can see this function performs a few tasks before passing two arguments into the next function. We don’t really need to understand what its doing but we will need to have access to these arguments. Let’s go to the next function to see what it does with these arguments.



    Now we need to go to the function that this one calls. Select call and press enter.

    This function checks each unit to see if it is visible or cloaked.

    It always performs a standard function calling policy which is to move ESP into EBP. This means we add 4 because EBP was pushed. Another 4 because the function we are in was called and we have the location of these arguments. Look down the code a ways. You can see several accesses to these arguments. This means that as long as our code doesn’t use EBP there shouldn’t be any problems. So don’t use any C++ regular calls as they will change EBP. It’s time to insert a jump hook. I believe the ideal location would be at XOR EAX,EAX right after the push statements. Make a short jump to int3s between the functions where you have a long jump to the function in our DLL. Here is the code that should do that.

    Code:
    void CallPatch2(void *pDest,void *pSrc)
    {
    VirtualProtect(pSrc, 16, PAGE_EXECUTE_READWRITE, &OldAccessRights);
    *(BYTE*)((DWORD)pSrc)    = 0xE9;
    *(DWORD*)((DWORD)pSrc+1) = (DWORD)pDest - (DWORD)pSrc - 5;
    *(BYTE*)((DWORD)pSrc+0xE) = 0xEB;
    *(BYTE*)((DWORD)pSrc+0xF) = 0xF0;
    VirtualProtect(pSrc, 16, OldAccessRights, &OldAccessRights);
    }
    Of course you will need to call this function when you are ready to insert the hook.
    Code:
    CallPatch2(&ViewUnits,(PBYTE)OffsetD);
    Now that we have a hook inserted into this function its time to copy down all the assembly code from all the functions that we are patching into one text document. This is very important because any references to an address multiple times can be found by using the search function. When one of the functions writes something, see if any of the other functions read it. If not, that line of code can be removed as it is useless. Copy down the code in the six functions I listed up above. Remove all the addresses that were copied from the address column and hex dump column. When your done all you should have left is the assembly code. I know there is a faster way to extract assembly code, but this works. Now we are almost ready to patch this function in our own code. Let’s go over some basic ASM guidelines.

    You direct jumps to labels by using the following code.
    Code:
    JMP SHORT Jump1
       
    // ways down the code
       
    Jump1:
    You must write a “0x” in front of any hexadecimal numbers that are not 9 or less. We have to do this to all the numbers because all the numbers in the debugger are hex values.
    Code:
    MOVZX EAX,WORD PTR DS:[ESI+8] // 0x is not necessary
    MOVZX EDX,WORD PTR DS:[ESI+0x10] // 0x is necessary
    Here is some sample code that shows how to redirect code to your data. The first thing you must do is declare the data wherever you declare your data.
    Code:
    DWORD Var1 =0;
    DWORD VisibleUnitArray[20000]={0};
    Then you insert the name of your variable in place of the hexadecimal address.
    Code:
    MOV DWORD PTR DS:[0x6C4A14],0 // replace this code
    MOV Var1,0 // with this code
       
    MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EAX // directed to top of array
    MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EAX // directed to array top + 4
    Calls are very simple. You can call __declspec(naked) functions. Just return when your done and everything should work fine.
    Code:
    CALL ProcessActiveUnits
    // after you're finished with the call return the mother function
    RETN
    Go ahead and start inserting this code into your function.




    Notice the red box at the top of the function. You can see 4 commands which delete the 40 4-byte values in an array. Compare the address location with the code in the blue circles. Notice how this code seems to be deleting the bottom of the array? Well this is where it gets tricky.

    The code in the blue circles reads from 629670.
    The code in the red box deletes the data at 629C78.

    This leaves us with 600 hex locations before the part that gets deleted. We can conclude that we are looking at 2 different arrays. This function must be called several times while this 600h-byte long array contains different active units.

    Open up the file that contains the 7 functions we copied down. You will see that there is one section of code that writes to the 40h DWORD long array but then never accesses the data it wrote. You can see this code in the red box in the picture below. We can leave the code in the red boxes out when we copy this code to our functions. Let the real functions do what ever job that code does. We can also leave the code out that is in the blue box above.


    I boxed all the important read and write code in green boxes.

    Below is the function that is called by the one above.


    Finish copying all this code and insert the small changes that you need along the way. When you’re finished your code should look something like this.

    Code:
      #include "stdafx.h"
      DWORD WINAPI maphack();
       
      //patching function variables
      DWORD OldAccessRights;
      DWORD OffsetA = 0x4989D9;
      DWORD OffsetB = 0x42D48A;
      DWORD *OffsetC = (DWORD*)0x4989E7;
      DWORD OffsetD = 0x497F68;
      DWORD *OffsetE = (DWORD*)0x497F78;
      DWORD *OffsetF = (DWORD*)0x47FFE2;
       
      //replacement variables
      DWORD Var1 =0;
      DWORD VisibleUnitArray[20000]={0};
       
      void __declspec(naked) HelperFunction()
      {
      __asm
      {
      MOV ECX,Var1
      MOV EDX,DWORD PTR DS:[ECX*8+VisibleUnitArray]
      MOV EAX,ECX
      SHR EAX,1
      CMP ECX,1
      PUSH ESI
      MOV ESI,DWORD PTR DS:[ECX*8+VisibleUnitArray+4]
      JBE SHORT JumpB1
      PUSH EDI
      NOP
      JumpC2:
      MOV EDI,DWORD PTR DS:[EAX*8+VisibleUnitArray]
      CMP EDI,EDX
      JNB SHORT JumpB2
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EDI
      MOV EDI,DWORD PTR DS:[EAX*8+VisibleUnitArray+4]
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EDI
      MOV ECX,EAX
      SHR EAX,1
      CMP ECX,1
      JA SHORT JumpC2
      JumpB2:
      POP EDI
      JumpB1:
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],ESI
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EDX
      POP ESI
      RETN
      }
      }
       
      void __declspec(naked) ProcessActiveUnits()
      {
      __asm
      {
      MOV ECX,Var1
      INC ECX
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],ESI
      MOVZX EAX,BYTE PTR DS:[ESI+0xD]
      CMP EAX,4
      MOV Var1,ECX
      JA SHORT JumpA1
      MOVSX EDX,WORD PTR DS:[ESI+0x16]
      JMP SHORT JumpB1
      JumpA1:
      XOR EDX,EDX
      JumpB1:
      SHL EAX,0x0D
      OR EAX,EDX
      XOR EDX,EDX
      MOV DL,BYTE PTR DS:[ESI+0xE]
      SHL EAX,5
      AND EDX,0x10
      OR EAX,EDX
      MOVZX EDX,WORD PTR DS:[ESI+0x10]
      SHL EAX,9
      OR EAX,EDX
      CMP ECX,1
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EAX
      JBE SHORT JumpC1
      CALL HelperFunction
      JumpC1:
      RETN
      }
      }
       
      void __declspec(naked) CheckActiveUnits()
      {
      __asm
      {
      pushad
      MOV EAX,DWORD PTR DS:[0x6D0EFC]
      TEST EAX,EAX
      MOV Var1,0
      JNZ SHORT JumpA
      MOV EDI,DWORD PTR SS:[EBP+8]
      CMP EDI,DWORD PTR SS:[EBP+0xC]
      JA SHORT JumpB
      MOV BL,BYTE PTR DS:[0x57F094]
      JumpF:
      MOV ESI,DWORD PTR DS:[EDI*4+0x629670]
      TEST ESI,ESI
      JE SHORT JumpC
      JumpE:
      TEST BYTE PTR DS:[ESI+0xC],BL
      //JE SHORT JumpD
      CALL ProcessActiveUnits
      //JumpD:
      MOV ESI,DWORD PTR DS:[ESI+4]
      TEST ESI,ESI
      JNZ SHORT JumpE
      JumpC:
      MOV EAX,DWORD PTR SS:[EBP+0xC]
      INC EDI
      CMP EDI,EAX
      JBE SHORT JumpF
      JMP SHORT JumpB
      JumpA:
      MOV EAX,DWORD PTR SS:[EBP+8]
      CMP EAX,DWORD PTR SS:[EBP+0xC]
      MOV EDI,EAX
      JA SHORT JumpB
      MOV BL,BYTE PTR DS:[0x6D0F00]
      JumpK:
      MOV ESI,DWORD PTR DS:[EDI*4+0x629670]
      TEST ESI,ESI
      JE SHORT JumpG
      JumpJ:
      TEST BYTE PTR DS:[ESI+0xC],BL
      JNZ SHORT JumpH
      MOV EAX,DWORD PTR DS:[0x6D0F04]
      TEST EAX,EAX
      JE SHORT JumpI
      CMP BYTE PTR DS:[ESI+0xA],0x0B
      JNZ SHORT JumpI
      JumpH:
      CALL ProcessActiveUnits
      JumpI:
      MOV ESI,DWORD PTR DS:[ESI+4]
      TEST ESI,ESI
      JNZ SHORT JumpJ
      JumpG:
      MOV EAX,DWORD PTR SS:[EBP+0xC]
      INC EDI
      CMP EDI,EAX
      JBE SHORT JumpK
      JumpB:
      popad
      xor EAX,EAX
      jmp OffsetE
      }
      }
       
      void __declspec(naked) PrintUnitsHelperFunction()
      {
      __asm
      { 
      PUSH EBP
      MOV EBP,ESP
      SUB ESP,8
      MOV EAX,DWORD PTR DS:[VisibleUnitArray+0xC]
      PUSH ESI
      MOV ESI,DWORD PTR DS:[VisibleUnitArray+0x8]
      PUSH EDI
      MOV EDI,Var1
      MOV EDX,EDI
      MOV ECX,1
      SHR EDX,1
      CMP EDX,ECX
      MOV DWORD PTR SS:[EBP-4],EAX
      JB SHORT JumpA4
      PUSH EBX
      JumpE4:
      LEA EBX,DWORD PTR DS:[EBX]
      LEA EAX,DWORD PTR DS:[ECX+ECX]
      CMP EAX,EDI
      JNB SHORT JumpB4
      MOV EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray]
      CMP EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray+0x8]
      JNB SHORT JumpB4
      INC EAX
      JumpB4:
      MOV EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray]
      CMP ESI,EBX
      JNB SHORT JumpC4
      CMP EAX,EDX
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EBX
      MOV EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray+4]
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EBX
      MOV ECX,EAX
      JBE SHORT JumpE4
      JumpC4:
      POP EBX
      JumpA4:
      MOV EDX,DWORD PTR SS:[EBP-4]
      POP EDI
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],ESI
      MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EDX
      POP ESI
      MOV ESP,EBP
      POP EBP
      RETN
      }
      }
       
      void __declspec(naked) PrintUnits()
      {
      __asm
      { 
      PUSH ESI
      PUSH ESI
      MOV ESI,Var1
      TEST ESI,ESI
      JNZ JumpA3
      POP ESI
      POP ESI
      XOR EAX,EAX
      test eax,eax
      jmp OffsetC
      JumpA3:
      PUSH EBX
      LEA EBX,DWORD PTR DS:[ESI-1]
      PUSH EDI
      MOV DWORD PTR DS:[0x6C4A10],EBX
      MOV EDI,0x6C2300
      NOP
      JumpB3:
      MOV ECX,DWORD PTR DS:[ESI*8+VisibleUnitArray]
      MOV EAX,DWORD PTR DS:[VisibleUnitArray+0xC]
      MOV DWORD PTR DS:[VisibleUnitArray+0x8],ECX
      MOV EDX,DWORD PTR DS:[ESI*8+VisibleUnitArray+4]
      DEC ESI
      MOV DWORD PTR DS:[EDI],EAX
      MOV DWORD PTR DS:[VisibleUnitArray+0xC],EDX
      MOV Var1,ESI
      CALL PrintUnitsHelperFunction
      ADD EDI,4
      TEST ESI,ESI
      JNZ SHORT JumpB3
      MOV EAX,DWORD PTR DS:[EBX*4+0x6C2300]
      POP EDI
      POP EBX
      POP ESI
      POP ESI
      test eax,eax
      jmp OffsetC
      }
      }
       
      void CallPatch1(void *pDest,void *pSrc)
      {
      VirtualProtect(pSrc, 16, PAGE_EXECUTE_READWRITE, &OldAccessRights);
      *(BYTE*)((DWORD)pSrc)    = 0xE9;
      *(DWORD*)((DWORD)pSrc+1) = (DWORD)pDest - (DWORD)pSrc - 5;
      *(BYTE*)((DWORD)pSrc+0xC) = 0xEB;
      *(BYTE*)((DWORD)pSrc+0xD) = 0xF2;
      VirtualProtect(pSrc, 16, OldAccessRights, &OldAccessRights);
       
      VirtualProtect((int*)OffsetB, 2, PAGE_EXECUTE_READWRITE, &OldAccessRights);
      *(BYTE*)(OffsetB)   = 0x90;
      *(BYTE*)(OffsetB+1) = 0x90;
      VirtualProtect((int*)OffsetB, 2, OldAccessRights, &OldAccessRights);
       
      VirtualProtect(OffsetF, 4, PAGE_EXECUTE_READWRITE, &OldAccessRights);
      *OffsetF = 0x158BC933;
      VirtualProtect(OffsetF, 4, OldAccessRights, &OldAccessRights);
      }
       
      void CallPatch2(void *pDest,void *pSrc)
      {
      VirtualProtect(pSrc, 16, PAGE_EXECUTE_READWRITE, &OldAccessRights);
      *(BYTE*)((DWORD)pSrc)    = 0xE9;
      *(DWORD*)((DWORD)pSrc+1) = (DWORD)pDest - (DWORD)pSrc - 5;
      *(BYTE*)((DWORD)pSrc+0xE) = 0xEB;
      *(BYTE*)((DWORD)pSrc+0xF) = 0xF0;
      VirtualProtect(pSrc, 16, OldAccessRights, &OldAccessRights);
      }
       
       
       
      DWORD WINAPI maphack()
      {
      CallPatch1(&PrintUnits,(PBYTE)OffsetA);
      CallPatch2(&CheckActiveUnits,(PBYTE)OffsetD);
       
      //loop-code for in-game hotkeys
       
      return 0;
      }
       
      BOOL APIENTRY DllMain(HANDLE hModule, DWORD CurrentState, LPVOID lpReserved)
      {
      if (CurrentState == DLL_PROCESS_ATTACH)
      {
      CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)maphack,NULL,NULL,NULL);       
      }
      else
      {
      return 1;
      };
      return 1;
      }
    Well these tutorials thoroughly covered the art of code caving. I hope they will help people who are just starting out hacking. Please let me know if you have any suggestions or ideas that would make these tutorials better. Also please point out any areas that might be unclear, as I don’t have all day to write tutorials.

    Maybe later on I will write Chapter 7.

    P.S.
    This will be the last chapter unless a lot of people show they are interested in another chapter.
    Last edited by hellinsect : 07-06-2008 at 08:49 PM

  8. #8

    Default

    Can you please write another chapter for this tutorial?? I just finished the last chapter, but I am not sure what to do next, another chapter would be greatly appreciated
    Quote Originally Posted by 3guys1dolphin.com View Post
    wtf do i do with a .rar file? im not dling other programs to use this godamn

  9. #9
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default

    I was thinking of rewriting this tutorial and adding more chapters on the advanced methods of clicking enemy units.

  10. #10

    Default

    Quote Originally Posted by hellinsect View Post
    I was thinking of rewriting this tutorial and adding more chapters on the advanced methods of clicking enemy units.
    I would appreciate that

  11. #11
    Ace #1 Poon Tycoon Senior Member
    Retired Staff Member
    Gold Member

    Enlightened
    test-acc's Avatar
    Join Date
    Sep 2004
    Location
    Europe!
    Posts
    2,638

    Default

    This thread is not getting the love it deserves.

    Very nice informative guide, it's very hard to find a maphack tutorial.

  12. #12

    Default

    Quote Originally Posted by [email protected] View Post
    I would appreciate that
    ^
    Quote Originally Posted by 3guys1dolphin.com View Post
    wtf do i do with a .rar file? im not dling other programs to use this godamn

  13. #13
    custom user title Senior Member

    Crusader
    applesauce's Avatar
    Join Date
    Jun 2004
    Posts
    3,433

    Default

    Maybe make it into a video tutorial like lena's tuts4you?

  14. #14
    Maverick Renegade Senior Member

    Crusader
    Megaz's Avatar
    Join Date
    Oct 2005
    Posts
    3,673

    Default

    wow can't believed I missed this. Very nice guide, any further revisions and additions would be awesome. +r

  15. #15

    Default

    thanks for this keep up the good work!

  16. #16

    Default

    What do I do with these 3 .dll files, that I downloaded from OllyDbg v1.10 ?

  17. #17
    Banned

    Advocate

    Join Date
    Dec 2007
    Posts
    325

    Default

    Place them in your olly folder.

  18. #18
    =) Senior Member
    Developer

    Supreme Being
    K? Pŕo?ćtiόnŹ's Avatar
    Join Date
    Oct 2004
    Posts
    11,794

    Default

    Too bad I cant delete that =-\.
    Quote Originally Posted by Voice Of Korhal View Post
    Let us hope so, if that Reverse Engineering crap actually works, I'll be amazed.

  19. #19

    Default

    Nice neat tut I will try in when I have some free time =)

  20. #20

    Default

    I am sutck in chapter 2. I found two addreses (works fine when noped) and now i am in a loop and i get the same address anytime. Don't know what to do. Please help

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. [WarCraft III] Gattahack 2 DotA Maphack for 1.21b
    By gattacalimited in forum Old User Downloads
    Replies: 54
    Last Post: 12-29-2008, 09:53 PM
  2. Maphack Tutorial CHAPTER 1
    By hellinsect in forum Reverse Engineering
    Replies: 9
    Last Post: 06-27-2008, 01:12 PM
  3. Lets create simple MapHack, forum - tutorial
    By Ashur in forum Starcraft/Brood War
    Replies: 42
    Last Post: 09-06-2005, 06:46 AM
  4. Make Maphack tutorial? Where?
    By cheezy_monkey in forum Starcraft/Brood War
    Replies: 17
    Last Post: 08-30-2005, 12:30 PM
  5. Maphack Tutorial
    By Trans_Am77 in forum Starcraft/Brood War
    Replies: 7
    Last Post: 04-22-2005, 06:27 PM

Posting Rules

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