nixawk / Awesome-Windows-Debug

Debug Windows Application / Kernel
81 stars 34 forks source link

x86 Architecture #1

Open nixawk opened 7 years ago

nixawk commented 7 years ago

The x86 architecture has

64-bit x86 has additional registers.

General-Purpose Registers (GPR)

The 8 GPRs are:

All registers can be accessed in 16-bit and 32-bit modes. In 16-bit mode, the register is identified by its two-letter abbreviation from the list above. In 32-bit mode, this two-letter abbreviation is prefixed with an 'E' (extended). For example, 'EAX' is the accumulator register as a 32-bit value.

Similarly, in the 64-bit version, the 'E' is replaced with an 'R', so the 64-bit version of 'EAX' is called 'RAX'.

It is also possible to address the first four registers (AX, CX, DX and BX) in their size of 16-bit as two 8-bit halves. The least significant byte (LSB), or low half, is identified by replacing the 'X' with an 'L'. The most significant byte (MSB), or high half, uses an 'H' instead. For example, CL is the LSB of the counter register, whereas CH is its MSB.

In total, this gives us five ways to access the accumulator, counter, data and base registers: 64-bit, 32-bit, 16-bit, 8-bit LSB, and 8-bit MSB. The other four are accessed in only three ways: 64-bit, 32-bit and 16-bit. The following table summarises this:

registers

Segment Registers

The 6 Segment Registers are:

EFLAGS Register

The EFLAGS is a 32-bit register used as a collection of bits representing Boolean values to store the results of operations and the state of the processor.

eflags-register

The bits named 0 and 1 are reserved bits and shouldn't be modified.

The different use of these flags are:

eflags-register-bits

Carry Flag. Set if the last arithmetic operation carried (addition) or borrowed (subtraction) a bit beyond the size of the register. This is then checked when the operation is followed with an add-with-carry or subtract-with-borrow to deal with values too large for just one register to contain.

00A931C9 >   33C0           XOR EAX,EAX
00A931CB     B8 00000080    MOV EAX,80000000
00A931D0     05 00000080    ADD EAX,80000000
00A931D5     90             NOP

Parity Flag. Set if the number of set bits in the least significant byte is a multiple of 2.

00A231C9 >   33C0           XOR EAX,EAX

Zero Flag. Set if the result of an operation is Zero (0).

00A231C9 >   33C0           XOR EAX,EAX
00A231C9 >   33C0           XOR EAX,EAX
00A231CB     04 01          ADD AL,1
00A231CD     2C 01          SUB AL,1
00A231CF     90             NOP

Sign Flag. Set if the result of an operation is negative.

00A231C9 >   33C0           XOR EAX,EAX
00A231CB     2C 01          SUB AL,1

Instruction Pointer

The EIP register contains the address of the next instruction to be executed if no branching is done.

EIP can only be read through the stack after a call instruction. Let's a demo for shellcode execution.

eip-redirects
#include "stdafx.h"
#include <stdio.h>

void EipTrigger(void)
{
    /*
     * windows/exec - 193 bytes
     * http://www.metasploit.com
     * VERBOSE=false, PrependMigrate=false, EXITFUNC=process,
     * CMD=calc.exe
     */

    char *shellcode =
    "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
    "\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
    "\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
    "\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
    "\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
    "\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
    "\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
    "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
    "\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
    "\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f"
    "\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5"
    "\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"
    "\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";

    int (*ret)() = (int(*)())shellcode;
    ret();
}

int main(int argc, char *argv[])
{
    printf("Hello Main Function\n");
    return 0;
}
0:000> bp $exentry
*** WARNING: Unable to verify checksum for EIP.exe
0:000> bl
 0 e 00411109     0001 (0001)  0:**** EIP!ILT+260(_mainCRTStartup)
0:000> g
Breakpoint 0 hit
eax=7529ef9a ebx=7ffda000 ecx=00000000 edx=00411109 esi=00000000 edi=00000000
eip=00411109 esp=0012ff8c ebp=0012ff94 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
EIP!ILT+260(_mainCRTStartup):
00411109 e9c2060000      jmp     EIP!mainCRTStartup (004117d0)
0:000> p
eax=7529ef9a ebx=7ffda000 ecx=00000000 edx=00411109 esi=00000000 edi=00000000
eip=004117d0 esp=0012ff8c ebp=0012ff94 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
EIP!mainCRTStartup:
004117d0 8bff            mov     edi,edi
0:000> r eip
eip=004117d0
0:000> x EIP!EipTrigger
00411390 EIP!EipTrigger (void)
0:000> r eip=00411390
0:000> g
ModLoad: 74da0000 74dec000   C:\Windows\system32\apphelp.dll
eax=00000172 ebx=00000000 ecx=fba6ad26 edx=0012fe6c esi=77008380 edi=77008340
eip=76f76bb4 esp=0012fe64 ebp=0012fe80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
76f76bb4 c3              ret

Memory

The x86 architecture is little-endian, meaning that multi-byte values are written least significant byte first. (This refers only to the ordering of the bytes, not to the bits.)

References