Announcement

Collapse
No announcement yet.

Basic Assembly Tutorial By DABhand

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Basic Assembly Tutorial By DABhand

    The Basics

    Opcodes
    =====

    Ok whats opcodes? An opcode is an instruction the processor can understand. For example

    SUB and ADD and DIV

    The sub instructions subtracts two numbers together. Most opcodes have operands

    SUB destination,source like the following

    SUB eax, ecx

    SUB has 2 operands. In the case of a subtraction, a source and a destination. It subtracts the source value to the
    destination value and then stores the result in the destination. Operands can be of different types: registers,
    memory locations, immediate values.

    So basically that instruction is this, say for example eax contained 20 and ecx contained 10

    eax = eax - ecx
    eax = 20 - 10
    eax = 10

    Easy that bit huh

    Registers
    ======

    Ahhh here is the main force of asm, Registers contain values and information which is used in a program to keep
    track of things, and when new to ASM it does look messy but the system is practically efficient. It is honestly

    Lets take a look at the main Register used, its eax. Say it contains the value FFEEDDCCh (the h means hexidecimal)
    when working later with softice u will see hex values alot so get used to it now

    Ok Ill show how the registers are constructed

    EAX FFEEDDCC
    AX DDCC
    AH DD
    AL CC

    ax, ah, al are part of eax. EAX is a 32-bit register (available only on 386+), ax contains the lower 16 bits (2 bytes)
    of eax, ah contains the high byte of ax, and al contains the low byte of ax. So ax is 16 bit, al and ah are 8 bit.
    So, in the example above, these are the values of the registers:

    eax = FFEEDDCC (32-bit)
    ax = DDCC (16-bit)
    ah = DD (8-bit)
    al = CC (8-bit)

    Understand? I know its alot to take in, but thats how registers work Heres some more examples of opcodes and the
    registers used...

    mov eax, 002130DF mov loads a value into a register
    mov cl, ah move the high byte of ax (30h) into cl
    sub cl, 10 substract 10 (dec.) from the value in cl
    mov al, cl and store it in the lowest byte of eax.

    So at start..

    eax = 002130DF

    at end

    eax = 00213026

    Did you follow what happened? I hope so, cause im trying to make this as easy as I can

    Ok lets discuss the types of registers, there is 4 types used mainly (there is others but will tell about them later)

    General Purpose Registers
    =================

    These 32-bit (and their 16bit and 8bit sub registers) registers can be used for anything, but their main purpose is
    shown after them.

    eax (ax/ah/al) Accumulator
    ebx (bx/bh/bl) Base
    ecx (cx/ch/cl) Counter
    edx (dx/dh/dl) Data

    As said these are hardly used nowadays for their main purpose and is used to ferry around information within programs
    and games (such as scores, health value etc)

    Segment Registers
    ============

    Segment registers define the segment of memory that is used. You'll probably won't need them with win32asm, because
    windows has a flat memory system. In dos, memory is divided into segments of 64kb, so if you want to define a memory
    address, you specify a segment, and an offset (like 0172:0500 (segmentffset)). In windows, segments have sizes
    of 4gig, so you won't need segments in win. Segments are always 16-bit registers.

    CS code segment
    DS data segment
    SS stack segment
    ES extra segment
    FS (only 286+) general purpose segment
    GS (only 386+) general purpose segment

    Pointer Registers
    ===========

    Actually, you can use pointer registers as general purpose registers (except for eip), as long as you preserve their
    original values. Pointer registers are called pointer registers because their often used for storing memory addresses.
    Some opcodes (and also movb,scasb,etc.) use them.

    esi (si) Source index
    edi (di) Destination index
    eip (ip) Instruction pointer

    EIP (or IP in 16-bit programs) contains a pointer to the instruction the processor is about to execute. So you can't
    use eip as general purpose registers.

    Stack Registers
    ==========

    There are 2 stack registers: esp & ebp. ESP holds the current stack position in memory (more about this in one of the
    next tutorials). EBP is used in functions as pointer to the local variables.

    esp (sp) Stack pointer
    ebp (bp) Base pointer

    MEMORY
    =====

    How is the memory used within ASM and the layout of it? Well hopefully this will answer some questions. Bear in mind
    there is more advanced things than what is explained here, but hell you lot arent advanced, so start from the basics

    Lets look at the different types..

    DOS
    ===

    In 16-bit programs like for DOS (and Win 3.1), memory was divided in segments. These segments have sizes of 64kb.
    To access memory, a segment pointer and an offset pointer are needed. The segment pointer indicates which segment
    (section of 64kb) to use, the offset pointer indicates the place in the segment itself.

    Take a look at this


    ----------------------------MEMORY--------------------------------
    |SEGMENT 1 (64kb)|SEGMENT 2 (64kb)|SEGMENT 3 (64kb)|etc...........|


    Hope that shows well

    Note that the following explanation is for 16-bit programs, more on 32-bit later (but don't skip this part, it is
    important to understand 32-bits).

    The table above is the total memory, divided in segments of 64kb. There's a maximum of 65536 segments. Now take one
    of the segments:


    -------------------SEGMENT 1(64kb)----------------------
    |Offset 1|Offset 2|Offset 3|Offset 4|Offset 5|etc.......|


    To point to a location in a segment, offsets are used. An offset is a location inside the segment. There's a maximum of
    65536 offsets per segment. The notation of an address in memory is:

    SEGMENT:OFFSET

    For example:

    0145:42A2 (all hex numbers remember )

    This means: segment 145, offset 42A2. To see what is at that address, you first go to segment 145, and then to offset
    42A2 in that segment.

    Hopefully you remembered to read about those Segment Registers a while ago on this thread.

    CS - Code segment
    DS - Data Segment
    SS - Stack Segment
    ES - Extra Segment
    FS - General Purpose
    GS - General Purpose <<< Them remember

    The names explain their function: code segment (CS) contains the number of the section where the current code that is
    being executed is. Data segment for the current segment to get data from. Stack indicates the stack segment
    (more on the stacks later), ES, FS, GS are general purpose registers and can be used for any segment (not in win32 though).

    Pointer registers most of the time hold an offset, but general purpose registers (ax, bx, cx, dx etc.) can also be
    used for this. IP (Pointer register) indicates the offset (in the CS (code segment)) of the instruction that is
    currently executed. SP (Stack register) holds the offset (in the SS (stack segment)) of the current stack position.

    Phew and you thought 16bit memory was hard huh

    Sorry if thats all confusing, but its the easiest way to explain it. Reread it a few times it will eventually sink
    into your brain on how memory works and how it is accessed to be read and written too

    Now we move to

    32-bit Windows
    ==========

    You have probably noticed that all this about segments really isn't fun. In 16-bit programming, segments are essential.
    Fortunately, this problem is solved in 32-bit Windows (9x and NT).

    You still have segments, but don't care about them because they aren't 64kb, but 4 GIG. Windows will probably even crash
    if you try to change one of the segment registers.

    This is called the flat memory model. There are only offsets, and they now are 32-bit, so in a range from 0 to 4,294,967,295.
    Every location in memory is indicated only by an offset.

    This is really one of the best advantages of 32-bit over 16-bit. So you can forget the segment registers now and focus
    on the other registers.

    Oh the madness of it all, wow 4 gig bits to work with

    The Fun Part begins!!!

    Its

    THE OPCODES
    =========

    Here is a list of a few opcodes you will notice alot of when making trainers or cracking etc.

    1. MOV


    This instruction is used to move (or actually copy) a value from one place to another. This 'place' can be a register,
    a memory location or an immediate value (only as source value of course). The syntax of the mov instruction is:

    mov destination, source

    You can move a value from one register to another (note that the instruction copies the value, in spite of its name
    'move', to the destination).

    mov edx, ecx

    The instruction above copies the contents of ecx to edx. The size of source and destination should be the same, this
    instruction for example is NOT valid:

    mov al, ecx ; NOT VALID

    This opcode tries to put a DWORD (32-bit) value into a byte (8-bit). This can't be done by the mov instruction
    (there are other instructions to do this). But these instructions are allowed because source and destination don't
    differ in size, like for example...

    mov al, bl
    mov cl, dl
    mov cx, dx
    mov ecx, ebx

    Memory locations are indicated with an offset (in win32, for more info see the previous page). You can also get a
    value from a certain memory location and put it in a register. Take the following table as example:

    offset 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42
    data 0D 0A 50 32 44 57 25 7A 5E 72 EF 7D FF AD C7

    (each block represents a byte)

    The offset value is indicated as a byte here, but it is a 32-bit value. Take for example 3A
    (which isn't a common value for an offset, but otherwise the table won't fit...), this also is a
    32-bit value: 0000003Ah. Just to save space, some unusual and low offsets are used. All values are hexcodes.

    Look at offset 3A in the table above. The data at that offset is 25, 7A, 5E, 72, EF, etc. To put the value at
    offset 3A in, for example, a register you use the mov instruction, too:

    mov eax, dword ptr [0000003Ah] ... but.......

    You will see this more commonly in programs as

    mov eax, dword ptr [ecx+45h]

    This means ecx+45 will point to the memory location to take the 32 bit data from, we know its 32bit because of
    the dword in the instruction. To take say 16bit of data we use WORD PTR or 8bit BYTE PTR, like the following examples..

    mov cl, byte ptr [34h] cl will get the value 0Dh (see table above)
    mov dx, word ptr [3Eh] dx will get the value 7DEFh (see table above, remember that the bytes are reversed)

    The size sometimes isn't necessary:

    mov eax, [00403045h]

    because eax is a 32-bit register, the assembler assumes (and this is the only way to do it, too) it should take
    a 32-bit value from memory location 403045.

    Immediate numbers are also allowed:

    mov edx, 5006

    This will just make the register edx contain the value 5006. The brackets, [ and ], are used to get a value from
    the memory location between the brackets, without brackets it is just a value. A register as memory location is
    allowed to (it should be a 32-bit register in 32-bit programs):

    mov eax, 403045h ; make eax have the value 403045 hex.
    mov cx, [eax] ; put the word size value at the memory location EAX (403045) into register CX.

    In mov cx, [eax], the processor first looks what value (=memory location) eax holds, then what value is at that
    location in memory, and put this word (16 bits because the destination, cx, is a 16-bit register) into CX.

    Phew

    2. ADD, SUB, MUL and DIV

    These are easy to understand Good old maths, im sure everyone can add and subtract and multiply and divide

    Anyways on with the info

    The add-opcode has the following syntax:

    add destination, source

    The calculation performed is destination = destination + source. The following forms are allowed:

    Destination Source Example
    Register Register add ecx, edx
    Register Memory add ecx, dword ptr [104h] / add ecx, [edx]
    Register Immediate value add eax, 102
    Memory Immediate value add dword ptr [401231h], 80
    Memory Register add dword ptr [401231h], edx

    This instruction is very simple. It just takes the source value, adds the destination value to it and then puts
    the result in the destination. Other mathematical instructions are:

    SUB destination, source (destination = destination - source)
    MUL destination, source (destination = destiantion * source)
    DIV source (eax = eax / source, edx = remainer)

    Its easy peasy aint it Or is it

    Subtraction works the same as add, multiplication is just dest = dest * source. Division is a little different.
    Because registers are integer values (i.e. round numbers, not floating point numbers) , the result of a division
    is split in a quotient and a remainder. For example:

    28 / 6 --> quotient = 4, remainder = 4
    30 / 9 --> quotient = 3, remainder = 3
    97 / 10 --> quotient = 9, remainder = 7
    18 / 6 --> quotient = 3, remainder = 0

    Now, depending on the size of the source, the quotient is stored in (a part of) eax, the remainder in (a part of) edx:

    Source size Division Quotient stored in Remainder Stored in...
    BYTE (8-bits) ax / source AL AH
    WORD (16-bits) dx:ax* / source AX DX
    DWORD (32-bits) edx:eax* / source EAX EDX

    * = For example: if dx = 2030h, and ax = 0040h, dx: ax = 20300040h. dx:ax is a dword value where dx represents the
    higher word and ax the lower. Edx:eax is a quadword value (64-bits) where the higher dword is edx and the lower eax.

    The source of the div-opcode can be:

    an 8-bit register (al, ah, cl,...)
    a 16-bit register (ax, dx, ...)
    a 32-bit register (eax, edx, ecx...)
    an 8-bit memory value (byte ptr [xxxx])
    a 16-bit memory value (word ptr [xxxx])
    a 32-bit memory value (dword ptr [xxxx])

    The source can not be an immediate value because then the processor cannot determine the size of the source operand.

    3. BITWISE OPS

    These instructions all take a destination and a source, except the 'NOT' instruction. Each bit in the destination is
    compared to the same bit in the source, and depending on the instruction, a 0 or a 1 is placed in the destination bit:

    Instruction AND OR XOR NOT
    Source Bit |0 0 1 1|0 0 1 1|0 0 1 1|0 1|
    Destination Bit |0 1 0 1|0 1 0 1|0 1 0 1|X X|
    Output Bit |0 0 0 1|0 1 1 1|0 1 1 0|1 0|

    AND sets the output bit to 1 if both the source and destination bit is 1.
    OR sets the output bit if either the source or destination bit is 1
    XOR sets the output bit if the source bit is different from the destination bit.
    NOT inverts the source bit.

    An example:

    mov ax, 3406
    mov dx, 13EAh
    xor ax, dx

    ax = 3406 (decimal), which is 0000110101001110 in binary.
    dx = 13EA (hex), which is 0001001111101010 in binary.
    Perform the XOR operation on these bits:


    Source 0001001111101010 (dx)
    Destination 0000110101001110 (ax)
    Output 0001111010100100 (new dx)

    The new dx is 0001111010100100 (7845 decimal, 1EA5 in hex) after the instruction.

    Another example:

    mov ecx, FFFF0000h
    not ecx

    FFFF0000 is in binary 11111111111111110000000000000000 (16 1's, 16 0's)

    If you take the inverse of every bit, you get:
    00000000000000001111111111111111 (16 0's, 16 1's), which is 0000FFFF in hex.

    So ecx is after the NOT operation 0000FFFFh.

    The last one is handy for serial generating, as is XOR. Infact XOR is used more for serials than any other instruction,
    widely used for serial checking in Winzip, Winrar, EA Games, Vivendi Universalis

    I WONT TELL YOU HOW TO MAKE KEYGENS SO DONT ASK

    4. INC/DEC(REMENTS)

    There are 2 very simple instructions, DEC and INC. These instructions increase or decrease a memory location or
    register with one. Simply put:

    inc reg -> reg = reg + 1
    dec reg -> reg = reg - 1
    inc dword ptr [103405] -> value at [103405] will increase by one.
    dec dword ptr [103405] -> value at [103405] will decrease by one.

    Ahh easy one to understand So is the next one

    5. NOP

    This instruction does absolutely nothing. This instruction just occupies space and time. It is used for filling purposes
    and patching codes.

    6. BIT rotation and shifting

    Note: Most of the examples below use 8-bit numbers, but this is just to make the picture clear.

    Shifting functions

    SHL destination, count
    SHR destination, count

    SHL and SHR shift a count number of bits in a register/memlocation left or right.

    Example:

    ; al = 01011011 (binary) here
    shr al, 3

    This means: shift all the bits of the al register 3 places to the right. So al will become 00001011. The bits on the left
    are filled up with zeroes and the bits on the right are shifted out. The last bit that is shifted out is saved in the
    carry-flag. The carry-bit is a bit in the processor's Flags register. This is not a register like eax or ecx that you
    can directly access (although there are opcodes to do this), but it's contents depend on the result of the instruction.
    This will be explained later, the only thing you'll have to remember now is that the carry is a bit in the flag register
    and that it can be on or off. This bit equals the last bit shifted out.

    shl is the same as shr, but shifts to the left.

    ; bl = 11100101 (binary) here
    shl bl, 2

    bl is 10010100 (binary) after the instruction. The last two bits are filled up with zeroes, the carry bit is 1, because
    the bit that was last shifted out is a 1.

    Then there are two other opcodes:

    SAL destination, count (Shift Arithmetic Left)
    SAR destination, count (Shift Arithmetic Right)

    SAL is the same as SHL, but SAR is not quite the same as SHR. SAR does not shift in zeroes but copies the MSB
    (most significant bit - The first bit if 1 it moves 1 in from the left, if 0 then 0's will be placed from left). Example:

    al = 10100110
    sar al, 3
    al = 11110100
    sar al, 2
    al = 11111101

    bl = 00100110
    sar bl, 3
    bl = 00000100

    This one you may have problems to get to grips with

    Rotation functions

    rol destination, count ; rotate left
    ror destination, count ; rotate right
    rcl destination, count ; rotate through carry left
    rcr destination, count ; rotate through carry right

    Rotation looks like shifting, with the difference that the bits that are shifted out are shifted in again on the other side:

    Example: ror (rotate right)


    Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
    Before 1 0 0 1 1 0 1 1
    Rotate count 3 1 0 0 1 1 0 1 1 (Shift out)
    Result 0 1 1 1 0 0 1 1

    As you can see in the figure above, the bits are rotated, i.e. every bit that is pushed out is shift in again on the
    other side. Like shifting, the carry bit holds the last bit that's shifted out. RCL and RCR are actually the same as
    ROL and ROR. Their names suggest that they use the carry bit to indicate the last shift-out bit, which is true,
    but as ROL and ROR do the same, they do not differ from them.

    7. Exchange

    Quite Straightforward this, I wont go into major details, it just swaps the values of two registers about
    (values, addresses). Like example..

    eax = 237h
    ecx = 978h
    xchg eax, ecx
    eax = 978h
    ecx = 237h

    Anyways end of day 1, if you learn this into your head the following days will get easier than harder. This is the basics I've taught you. Learn em well.

    Source
    The Hackmaster

  • #2
    FLOATS
    ======

    Ok whats a Float all about, well its simple, a float uses REAL values, what is a REAL value?

    A REAL value is a number which is not an integer, i.e. it contains numbers after a decimal
    point, like for example a float opcode can work out 5 divided by 4 and give the answer 1.25,
    also a REAL value can contain NEGATIVE numbers also like -3.567

    An integer with the same math problem will report 1 as the quotient with a remainder of 1. So
    you can see Floats are very useful indeed

    Why are we talking about floats? Some games and indeed applications will use float values to
    either work out monetary values or even in a game like percentage values and so forth.

    Both my latest trainers for Act of War and Settlers 5 (Die Siedler 5) use float values.

    FLOAT OPCODES
    =============

    Here is a list of opcodes and what they do

    FLD [source] Pushes a Float Number from the source onto the top of
    the FPU Stack.

    FST [destination] Copies a Float Number from the top of the FPU Stack
    into the destination.

    FSTP [destination] Pops a Float Number from the top of the FPU Stack
    into the destination.

    FLDZ Pushes +0.0 on top of FPU Stack

    FLD1 Pushes +1.0 on top of FPU Stack

    FLDPI Pushes PI on the top of FPU Stack

    FILD [source] Pushes an integer from the source to the top of the
    FPU Stack.

    FIST [destination] Copies an integer from the top of the FPU Stack to
    the destination.

    FISTP [destination] Pops an integer from the top of FPU Stack into the
    destination.

    FCHS Compliments the sign-bit of a float value located on
    the top of the FPU Stack or ST(0) Register.

    FNOP Performs no FPU Operation.[It's a 2 byte instruction
    unlike that of NOP which is a 1 byte instruction.]

    FABS Replaces the float value on the top of the stack with
    it's absolute value.

    FADD [operand] Adds the value of the operand with the value located
    on the top of the FPU Stack and store the result on
    the top of the FPU Stack.

    FCOS/FSIN Replaces the value on the top of the FPU Stack with
    it's cosine/sine value.

    FDIV [operand] Divide the value on the top of the FPU Stack with the
    operand and store the result on the top of FPU Stack.

    FMUL [operand] Multiply the value on the top of the FPU Stack with
    the operand and store the result on top of FPU Stack.

    FSUB [operand] Subtract operand value from the value on top of FPU
    Stack and store the result on top of FPU Stack.

    FXCHST (index) Exchanges values between top of FPU Stack and the
    ST(index) register.

    FCOM Compares the float value located on top if FPU Stack
    with the operand located in memory or the FPU Stack.

    FCOMP Same as FCOM but pops the float value from the top of
    the FPU Stack.

    FNSTSW AX Store FPU Status Word in AX. (Used for Conditions)


    Hope that's explanatory enough

    Before I show an example or two, lets talk about Stacks. What are they?

    STACKS
    ======

    Well a stack is used for a temporary location for values, a game or application may
    want to use a register for something else but want to keep the previous value for
    future reference, so the program will PUSH a value onto the stack for later
    retrieval.

    The stack is 8 small stacks in the 1, so look at it as a small filing
    cabinet in a way. Any of these values can be retrieved by calling for the stack and
    its position, like the following

    st(0) - always the top of the stack
    st(1) - next after top
    st(2) - 2nd from the top
    ..
    st(7) - Bottom of the stack

    So when you want to get a value you can if you know where it is stored, it does
    become a little complicated if you keep PUSH'ing values to the top of the stack as
    the previous value is moved down 1. So to take a value we just POP it back.

    So remember

    PUSH - Places a value on a stack
    POP - Removes a value from the stack

    But those opcodes are handy for integer values, what about floats?

    The next section will show you.

    FLOAT EXAMPLES
    ==============

    OK how to PUSH and POP values from the stack, its not difficult, here's a few
    examples

    Example 1

    Say we have a value in a known address which is a REAL value (so float) and want
    to add a value to it? For arguments sake lets say the register EAX contains the
    address 450000h which contains money in a game and we want to add a value from
    revenue which resides in an address contained in register EBX at 450008h and
    then send back to the original address?

    Here is how


    FLD [eax] - This opcode PUSH's the value at the address 450000h contained in
    EAX and pushes it to the top of the stack

    FADD [ebx] - This then adds the value at the address 450008h contained in EBX
    with the value at the top of the stack, then replaces the value
    at the top of the stack with the new value from the FADD opcode.

    FSTP [eax] - This then POP's the value on top of the stack to the address 450000h
    contained in the register EAX, where your old money value was and
    replaces with new one.

    Example 2

    Say now we want to calculate a Health Points value after taking damage, but wait!
    The damage is a float value but health is integer So how does this work out??
    Its not difficult ill show you how Again we will use the last registers for
    this example, EAX (450000h) contains our Health integer value and and EBX (450008h)
    contains our damage float value.

    Here it is


    FILD (EAX) - This opcode PUSH's an integer value to the top of the stack from the
    address 450000h contained in EAX.

    FSUB (EBX) - This subtracts the value at address 450008h (float) contained in EBX
    from the value at the top of the stack.

    FISTP (EAX) - This opcode POP's an integer value from the the top of the stack to
    the address 450000h contained in EAX. If the REAL value was 1.50 or
    higher it will send as an integer of 2, if 1.49 or lower then it will
    send as 1.

    Great huh See its not that difficult to understand

    Example 3

    This one is a toughy, we have a game but one of the addresses in the EAX register is
    needed for later on, but we also need the EAX register to work out a new ammo value,
    and no other register is free to send the address to, omg what to do what to do!!

    Dont worry, believe in the stacks The following will contain POP and PUSH command

    So for this example, EAX contains the value 800000h, the ammo value is contained
    at the address 450000h and the EBX contains the address 450008h which contains the
    either positive or negative number to be added to the ammo amount, if negative a shot
    was fired, if positive then a reload of the weapon or ammo picked up.


    PUSH EAX - This opcode PUSH's the value of EAX (notice without the [ ] it moves
    the value in EAX to the stack but if it had the [ ] it would move
    the value contained at the address of the value in EAX). In this
    case 800000h is PUSH'd on top of the stack.

    MOV EAX, 450000h - This opcode moves the value 450000h into the register EAX, which
    replaces the old 800000h value.

    FILD [EAX] - This opcode as you know will PUSH the value at the address contained
    in the register EAX, see the difference its using the [ ] so the
    game will look at the address 450000h and take the value there, and
    the PUSH to the top of the stack.

    FADD [EBX] - This again is self explanatory now, it adds the value at address
    450008h with the value on the stack, if it was a negative number it
    will decrease the value, if positive increase it, just basic maths

    FISTP [EAX] - Again this POP's an integer value from top of stack to the memory
    location contained in EAX, which is 450000h.

    CALL 46AEFF - What the hell is this??? I hear you say, wait a bit ill tell you
    just after

    POP EAX - This opcode POP's the original 800000h back into the register EAX, so
    the game hasnt lost that value.

    OK, the CALL opcode, its a handy opcode for the fact that if your program or game uses
    a routine to work out something but is always used it would be messy code if we were to
    keep manually typing it out not to mention a much bigger file.

    The CALL opcode, calls the opcodes at a certain address to work out the same function
    it does later on, so you only need to have that 1 set of opcodes for the entire program
    or game, you just CALL it, saves time and space.

    At the end of these opcodes from a CALL will be an opcode call RET (return) it will make
    the program or game go back to where it left off, in this case to the POP EAX opcode.

    That's end of day 2

    Hope you understood and it helped you see how things work.

    Any questions just post and ill answer when available

    Next time I will talk about different Jumps and Compares

    After that Ill show you how to code inject to make a trainer But as I said learn these
    well and you will understand what I'm talking about when code injecting

    Source
    The Hackmaster

    Comment


    • #3
      CONDITIONALS AND JUMPS
      ======================

      Ok this will be the last one for a while to show you, as they get more and more advanced.

      Learning the 3 days very well, should well be enough to do easy and simple trainers and
      how to find the values.

      First I want to talk about Flags, what the hell are flags?

      Well its not that difficult to understand.


      Flag registers
      ==============


      The flag register has a set of flags which are set/unset depending on calculations or
      other events. Here is the more important ones.


      ZF (Zero flag)
      This flag is set when the result of a calculation is zero (compare is actually a substraction
      without saving the results, but setting the flags only).

      SF (Sign flag)
      If set, the resulting number of a calculation is negative.

      CF (Carry flag)
      The carry flag contains the left-most bit after calculations.

      OF (Overflow flag)
      Indicates an overflow of a calculation, i.e. the result does not fit in the destination.


      There is other flags some which you will never use so I wont talk about them.


      Jumps
      =====



      Heres a list of the Opcodes for Jumps


      Opcode Meaning Condition
      JA Jump if above CF=0 & ZF=0
      JAE Jump if above or equal CF=0
      JB Jump if below CF=1
      JBE Jump if below or equal CF=1 or ZF=1
      JC Jump if carry CF=1
      JCXZ Jump if CX=0 register CX=0
      JE (is the same as JZ) Jump if equal ZF=1
      JG Jump if greater (signed) ZF=0 & SF=OF
      JGE Jump if greater or equal (signed) SF=OF
      JL Jump if less (signed) SF!=OF
      JLE Jump if less or equal (signed) ZF=1 or SF!=OF
      JMP Unconditional Jump -
      JNA Jump if not above CF=1 or ZF=1
      JNAE Jump if not above or equal CF=1
      JNB Jump if not below CF=0
      JNBE Jump if not below or equal CF=1 & ZF=0
      JNC Jump if not carry CF=0
      JNE Jump if not equal ZF=0
      JNG Jump if not greater (signed) ZF=1 or SF!=OF
      JNGE Jump if not greater or equal (signed) SF!=OF
      JNL Jump if not less (signed) SF=OF
      JNLE Jump if not less or equal (signed) ZF=0 & SF=OF
      JNO Jump if not overflow (signed) OF=0
      JNP Jump if no parity PF=0
      JNS Jump if not signed (signed) SF=0
      JNZ Jump if not zero ZF=0
      JO Jump if overflow (signed) OF=1
      JP Jump if parity PF=1
      JPE Jump if parity even PF=1
      JPO Jump if paity odd PF=0
      JS Jump if signed (signed) SF=1
      JZ Jump if zero ZF=1


      As you can see, jumps have conditions set to them from a previous calculation, test or compare.


      Look at this example


      TEST EAX,EBX
      JE 004822FFh
      MOV EAX,EBX
      JMP 004822FFh


      This little example basically tests two values to see if they are equal, if so the program
      will move the value 1 into the Zero Flag (ZF), thus allowing the conditional jump (JE) to
      goto a memory location to execute opcodes there.

      Now if it wasnt equal, the program will move 0 into ZF, and will skip the JE instruction, then
      move the value in the EBX register to the EAX register, forcing to be equal then doing an
      unconditional jump (JMP) to the same memory location.

      Games can use this, some games have a real address for values and a (what I like to call)
      ghost address, the ghost address is where the value to be shown on the game is used, but
      if a check like above exists, no matter what you force into that address will revert back
      to the real one.

      Im sure anyone trying to scan memory addresses for a game may have came up against this at
      one point.

      Other opcode that can be used is


      CMP register, register/value - Compare two values and move 0 or 1 into appropriate
      Flags.

      Ok thats enough for now, ive taught you basic ASM opcodes, floats and Conditional Jumps.

      This should be all you need to train a game

      Source
      The Hackmaster

      Comment

      Working...
      X