Results 1 to 1 of 1
  1. #1
    Dwar
    Dwar is offline
    Veteran Dwar's Avatar
    Join Date
    2010 Mar
    Posts
    2,222
    Thanks Thanks Given 
    211
    Thanks Thanks Received 
    2,230
    Thanked in
    292 Posts
    Rep Power
    10

    [MASM] Creating a Simple Hack

    Creating a Simple Hack with MASM
    In this tutorial we will cover basic syntax, how to read and write to memory, and how to use a function of the game. The target game in this tutorial is Stacraft with the latest (1.15.2) patch. I will go about doing this by posting the code in small blocks and then telling you what happens line by line.

    Pre-Reading Warning
    When doing line counts I -do- count blank lines, so be sure to keep an eye on that if you get confused as to what I'm talking about. Also, this is a fairly long read, so if you're not interested in programming your own hacks, it will probably be a big waste of time.

    Prerequisites: The MASM Compiler


    Part One

    The Basics
    First off, create a new text file, name it whatever you like. Open it with notepad. Add the following code:
    Code:
     .386
    .model Flat, StdCall
    OPTION CASEMAP :NONE
    
    include masm32includewindows.inc
    include masm32includemasm32.inc
    include masm32includeuser32.inc
    include masm32includekernel32.inc
    include masm32includedebug.inc
    includelib masm32libmasm32.lib
    includelib masm32libuser32.lib
    includelib masm32libkernel32.lib
    includelib masm32libdebug.lib
    
    include Memory.asm
    Line #1: Declares that the DLL is going to use the i386 (x86) architecture.
    Line #2: Use StdCall when calling things.
    Line #3: Make everything in the project case-sensitive.
    Lines #5-9: Including these libraries gives us access to the generic windows APIs.
    Lines #10-13: Including these makes it so that we can link our .obj file to a .dll
    Line #15: Memory.asm will include the majority of our code, but it's nice to have it separate from this file.

    These declarations are put in every project that you ever make (of course maybe with more things added or some things changed or taken away.)


    Unknown Variable Declarations
    Code:
     Data?
    ThreadID dd ?[/ syntax]
    Line #1: Declares that this is the section for the variables that aren’t initialized with a value.
    Line #2: ThreadID is the name of our variable that will hold the ID of our new thread that we will create, but since we don’t know the idea yet it’s marked by a ‘?’
    
    The Code [syntax].Code DllEntryPoint proc hInstDLL:DWORD, reason:DWORD, unused:DWORD mov eax, reason .if eax == DLL_PROCESS_ATTACH invoke CreateThread, NULL, 0, addr DLLProc, 0, 0, addr ThreadID .endif ret DllEntryPoint endp End DllEntryPoint
    Line #1: Declares that this is the beginning of the code section
    Line #3: ‘DLLEntryPoint’ is the function that injectors call after they have written the DLL to the memory
    Line #5: We move the reason that the DLL has been loaded into the EAX register
    Line #6: If EAX (the reason the DLL was loaded) is because it has attached then…
    Line #7: We create a new thread. The first function to be called in this thread is ‘DLLProc’ (a proc which we will be putting in Memory.asm)
    Line #10: Declares the end of the ‘DLLEntryPoint’ proc
    Line #11: Declares the end of the entry point of our DLL


    Part Two – Memory.asm

    Variable Declarations
    Code:
     .Data
    szHackOn db "Zerg Underling Limit Hack - ", 07h, "On", 0
    szHackOff db "Zerg Underling Limit Hack - ", 04h, "Off", 0
    blHackStatus db 0
    xxHackAddr dd 004888FAh
    BWFXN_PrintText dd 0048CE60h
    JmpByte db 0EBh
    JeByte db 074h
    Line #1: This declares section for the variables that we do already know the values to
    Lines #2-3: The 'sz' prefix to the variable name indicates to everyone who reads the source (it doesn't matter to MASM whether or not you have it) that this is a string.
    Line #4: The 'bl' prefix indicates that it's meant to be used as a boolean (true or false.) Initially the hack is off, so we have it set to 0 (false.)
    Line #5: This holds the address that I'm going to patch.
    Line #6: This is the address of the function in the game that prints a specified text to the screen. We will be using this to let the user know if the hack is on or off.
    Line #7: An unconditional jump (jmp) in hex is shown as 'EB'
    Line #8: A jump if equal to jump (je) in hex is shown as '74'

    Note:
    • Please notice the null terminator at the end of all strings (the 0.) Always include that on the end of any string.
    • Please notice the difference between the 'db' and the 'dd'. 'db' is used for smaller things, such as strings and booleans; 'dd' is used for larger things, such as memory addresses.
    • Please notice the 'h' at the end of the addresses. This signals to MASM that it is a hex value, which is very very important.



    Unknown Variable Declarations
    Code:
     .Data?
    HndHook dd ?[/ syntax]
    Line #1: Discussed in part 1
    Line #2: This was also discussed in part one, but I just wanted to note what we're going to be using this variable for. This variable is going to hold the handle to the hook on our keyboard.
    
    Initializing Our Hook As noted at the end of part one, after the DLL is injected, the function 'DLLProc' would be started under a new thread, so here's that code now. [syntax]DLLProc proc invoke FindWindow, CTEXT ("SWarClass"), 0 invoke GetWindowThreadProcessId, eax, 0 invoke SetWindowsHookEx, WH_KEYBOARD, addr HotKeys, NULL, eax mov HndHook, eax invoke Sleep,-1 DLLProc endp
    Line #1: This declares the proc named 'DLLProc'
    Line #3: This gets the hWnd of the StarCraft window based on its class name ("SWarClass"). As with every other windows API I have used so far, the result of it is stored in the register 'eax' (will be used in Line #4.)
    Line #4: This gets the pID of Starcraft based on the hWnd of its window (stored in eax, as earlier noted.) The output pID is put into the eax register.
    Line #6: This creates a hook on the keyboard using the pID that was in eax. So now any time anything is pressed on the keyboard, it will go to our 'HotKeys' function which I will discuss next.
    Line #7: This moves the handle of our hook which was stored in eax into our variable HndHook for later access.
    Line #9: This makes the thread sleep for an infinite time. Without this, the thread would die and our hack wouldn't work.
    Line #11: Signals that the proc 'DLLProc' is done with.


    The Actual Hack Code
    This is the largest piece of code in this tutorial, but in my opinion, the most simple.
    Code:
     HotKeys proc nCode:DWORD, wParam:DWORD, lParam:DWORD			
    
    	.if nCode != HC_ACTION								
    		jmp HotKeys_End
    	.endif
    
    	mov ebx, lParam
    	or ebx, 00FFFFFFh
    	.if ebx == 0C0FFFFFFh										
    		jmp HotKeys_End
    	.endif
    
    	.if wParam == VK_F7
    		
    		.if blHackStatus==0
    
    			mov blHackStatus, 1
    			invoke SCTxtOut, addr szHackOn, -1
                      	invoke WriteMem, HackAddr, addr JmpByte, 1
    
    		.else
    
    			mov blHackStatus, 0
    			invoke SCTxtOut, addr szHackOff, -1
                      	invoke WriteMem, HackAddr, addr JeByte, 1
    
        		.endif
    
           .endif
    
    HotKeys_End:
    
    	invoke CallNextHookEx, HndHook, nCode, wParam, lParam		
    	ret
    
    HotKeys endp
    Line #1: Declares the HotKeys proc
    Lines #3-5: If nothing is being pressed, go to HotKeys_End
    Lines #7-11: If the key being pressed is going up instead of down, go to HotKeys_End
    Line #13: If the key being pressed is F7...
    Line #15: If our hack is off...
    Line #17: Change the hack status boolean to on
    Line #18: Call the 'SCTxtOut' function to alert the user that the hack is on (the code for this function will be shown later.)
    Line #19: Call the WriteMem function to write the unconditional jump to the address of the hack to replace the conditional jump. The 1 at the end of the line indicates how many bytes to be written, and in this case it's one. (The code for this function will be shown later.)
    Line #21: If our hack is on...
    Line #23: Change the hack status boolean to off
    Line #24: Call the 'SCTxtOut' function to alert the user that the hack is off
    Line #25: Call the WriteMem function to write the conditional jump to the address of the hack to replace the unconditional jump. The 1 at the end of the line has already been discussed.
    Line #31: Simply a label that could be jmp'd to (as shown earlier in this piece of code.)
    Line #33: This resets our hook on the keyboard using the handle that we stored in HndHook earlier.

    Note: The 'addr' string that some of you may have noticed refers to 'the address of <input>'


    The SCTextOut Function
    Code:
     SCTxtOut proc txt:DWORD, code:DWORD
    	
          pushad
          mov eax, code
          push txt
          call dword ptr [BWFXN_PrintText]
          popad
          ret
    
    TxtOut endp
    Line #1: Declares the function with the custom arguments 'txt' and 'code'. 'txt' is the actual text to be printed to the screen and 'code' is the format code. In the previous piece of code, we called it with the '-1' for the code argument, which will format it to the center of the screen.
    Line #3: Push all of the registers on to the stack so we don't mess up the other code that had previously been going on.
    Line #4: Move the format code into eax, because that's where Starcraft's function will look for it at (this is found out through reversing with Olly or similar.)
    Line #5: Push our text onto the stack so that Starcraft will read that too.
    Line #6: Call the actual function in Starcraft.
    Line #7: Restore the registers that we earlier pushed into the stack for safe keeping


    The WriteMem Function
    Code:
     WriteMem proc	MemOffset:DWORD, DataPtr:DWORD, dataLen:DWORD
    
    	LOCAL OldProt:DWORD
    	pushad
    	invoke VirtualProtect, MemOffset, dataLen, PAGE_EXECUTE_READWRITE, addr OldProt
    	invoke RtlMoveMemory, MemOffset, DataPtr, dataLen
    	invoke VirtualProtect, MemOffset, dataLen, OldProt, addr OldProt
    	popad
    	ret
    
    WriteMem endp
    Line #1: Declare the WriteMem function with our custom arguments. MemOffset is the memory address that we want to write to. DataPtr is the pointer to the data that we're going to write. dataLen is the length (in bytes) of the data that we're going to write.
    Line #3: Set up the variable 'OldProt' which will store the old memory access privileges.
    Line #5: These changes the privileges on the memory that we want to change so that we can (if we couldn't before.)
    Line #6: Copy the memory from DataPtr to MemOffset for the length of dataLen.
    Line #7: Restore old memory access privileges.

    Congrats, you finished the tutorial.
    by dr0p
    Please, post your questions on forum, not by PM or mail

    I spend my time, so please pay a little bit of your time to keep world in equilibrium

Posting Permissions

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