Monday, August 13, 2007

x86 System Boot up

After system powers up and completes BIOS POST, INT 19 is issued. This interrupt directs the Microprocessor to start loading the OS. The boot sector of the primary boot device(floppy,HDD, CD ROM) is loaded at 0x0000:0x7c00

The loaded bootsector is defined as bootable only if it has the flag 0xAA55 present at the end of the sector. This means bytes 511 and 512 should be 0x55 and 0xAA respectively.

I used VMWARE Workstation to bootup a x86 virtual machine. I wrote some Linux/AT&T assembly code in my experiments.
I used the GNU GAS assembler using cygwin on a Windows PC.

Simple Hello World Bootable program.
====================================================================
BootSector.s
====================================================================
# Saurabh Tangri
.text
.globl start
.code16
.text
start:
movb $0xE, %ah # Function 0x0E(AH=0Eh Write Character in TTY Mode) of Interrupt 0x10
movb $'H', %al # write 'H'
int $0x10
movb $'e', %al # write 'e'
int $0x10
movb $'l', %al # write 'l'
int $0x10
movb $'l', %al # write 'l'
int $0x10
movb $'o', %al # write 'o'
int $0x10
movb $' ', %al # write ' '
int $0x10
movb $'W', %al # write 'W'
int $0x10
movb $'o', %al # write 'o'
int $0x10
movb $'r', %al # write 'r'
int $0x10
movb $'l', %al # write 'l'
int $0x10
movb $'d', %al # write 'd'
int $0x10
ret

.org 0x1fe, 0x90 # Last 2 bytes of the boot sector.
# .org 0x1FE basically directs assembler to add NOPS(opcode =0x90)
# till the base offset 0x1FE. After this it puts a flag 0xAA55 at the 512th word.
# It is an indication that the generated floppy image would be bootable.

boot_flag: .word 0xAA55 # Flag indicating a boot disk
====================================================================
MakeFile
====================================================================
AS=as
LD=ld
OBJCOPY=objcopy

.s.o:
${AS} -a $< -o $*.o >$*.map

all: final.img

final.img: bootsect
mv bootsect final.img

bootsect: bootsect.out
$(OBJCOPY) -O binary -j .text $< $@

bootsect.out: bootsect.o
${LD} -r -Ttext 0x7c00 -e _start -s -o bootsect.out bootsect.o

Next I want to dump study on PCI and x86 segmentation in my blogs.

...blogging....

Tuesday, October 18, 2005

IA-32 procedure calls and returns

The STACK



The stack is a contiguous array of memory locations. IA32 programs utilize stack to support procedure calls. When using the flat memorymodel(in the case of Windows), the stack can be located anywhere in the linear address space for the program. A stack can be up to 4 GBytes long, the maximum size of a segment.Items are placed on the stack using the PUSH instruction and removed from the stack using thePOP instruction. A portion of the stack allocated for a single frame is called as a stack frame.


When an item is pushed onto the stack, the processor decrements the ESP register, then writes the item at the new top of stack. When an item is popped off the stack, theprocessor reads the item from the top of stack, then increments the ESP register. In this manner,the stack grows down in memory (towards lesser addresses) when items are pushed on the stackand shrinks up (towards greater addresses) when the items are popped from the stack.

The topmost stack frame is delimited by two pointers the %ebp serving as the frame/base pointer and %esp serving as the stack pointer. The %eax is called as the accumulator and is used to return values from functions.

The CALL machine code instruction decrements the ESP register by the size of a return address and stores the address of the immediately following machine code instruction to the address pointed to by the ESP register. Or in simple words it pushes the return address(the instruction after call) and jumps to the target instruction. Symetrically, the RET machine code instruction fetches the stored return address from the address pointed to by the ESP register and increments the ESP register by the size of a return address. The PUSH and POP machine code instructions can be used to store and fetch an arbitrary register to and from the stack in a similar manner.

Thus a call in assembly is the same as:
push eip ; pushes the current EIP onto the stack
jmp ; jump to the function address

Now lets analyze two small programs :
The listings were disassembled using the intel compiler for windows(trial version).
icl /FA /Od program.CPP (I have'nt enforced any calling conventions( cdecl,fastcall,stdcall) for this simple listing It creates a .asm file containing the translated code.

Program 1 :
int main()
{
int a = 7 ;
return 0;
}

  1. _main PROC NEAR
  2. B1$1:; Preds $B1$0
  3. push ebp ;~~~ start of Prologue
  4. mov ebp, esp
  5. sub esp, 3
  6. and esp, -8
  7. add esp, 4
  8. push esi ;~~~ end of Prologue
  9. mov DWORD PTR [ebp-4], 7
  10. xor eax, eax
  11. leave ; ~~~ start of epilogue
  12. ret ; ~~~ end of epilogue
  13. ; mark_end;

Prologue
At the beginning of any procedure, two things must always be done beforeanything else:
1. Save the caller's frame pointer on the stack: push %ebp
2. Set as the callee's frame pointer the current stack pointer: movl %ebp, %esp

Epilogue
Just as we had to set up stack frame for the callee procedure, we must restore it to its current state before returning. This involves three steps (the inverse of the setup steps):
1. Set as the caller's stack pointer the current (callee's) frame pointer: movl %ebp, %esp
2. Restore the caller's frame pointer from the stack: popl %ebp
These two instructions may be replaced with a single leave instruction.
3. Once we have cleaned up after ourselves, a return (ret) instruction canbe executed. After the
leave instruction, the stack pointer will be at thetop of the return address pushed by the
call instruction. Therefore, the ret instruction acts to pop the return address off the stack and jump to it. (pop eip)

Program 2 :

int foo(){
int b = 8 ;
return 5;
}
int main(){
int a = 7 ;
foo();
return 0;
}

  1. PUBLIC ?foo@@YAHXZ
  2. ?foo@@YAHXZ PROC NEAR
  3. $B1$1: ; Preds $B1$0
  4. push ebp
  5. mov ebp, esp
  6. push esi
  7. mov DWORD PTR [ebp-4], 8
  8. mov eax, 5
  9. leave
  10. ret
  11. ALIGN 4
  12. ; LOE
  13. ; mark_end;
  14. _main PROC NEAR
  15. $B2$1; Preds $B2$0
  16. push ebp
  17. mov ebp, esp
  18. sub esp, 3
  19. and esp, -8
  20. add esp, 4
  21. push esi
  22. mov DWORD PTR [ebp-4], 7
  23. call ?foo@@YAHXZ
  24. ; LOE
  25. $B2$2: ; Preds $B2$1
  26. xor eax, eax
  27. leave
  28. ret
  29. ; mark_end;

Monday, October 17, 2005

Windows Internal Structures 1


In my efforts to document my understanding of windows internals, I have decided to blog my brains out.....

Part of it is also rehearsed in my master's degree thesis.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Windows Kernel Objects


  • PCR (Processor Control Region)
    When in Kernel Mode FS Register is set to a GDT selector whose base address points to the beginning of the Processor Control Region (0xFFDFF000). PCR is a very important kernel structure and the operating system maintains a distinct copy of it for each processor.

typedef struct _KPCR {
/*000*/ NT_TIB NtTib;
/*01C*/ struct _KPCR *SelfPcr; // flat address of this PCR
/*020*/ PKPRCB Prcb;
/*024*/ KIRQL Irql; // IRQL for each processor to arbitrate premption
/*028*/ DWORD IRR;
/*02C*/ DWORD IrrActive;
/*030*/ DWORD IDR;
/*034*/ DWORD Reserved2;
/*038*/ struct _KIDTENTRY *IDT; // Interrupt description table
/*03C*/ struct _KGDTENTRY *GDT; // Global description table
/*040*/ struct _TSS *TSS;
/*044*/ WORD MajorVersion;
/*046*/ WORD MinorVersion;
/*048*/ KAFFINITY SetMember;
/*04C*/ DWORD StallScaleFactor;
/*050*/ BYTE DebugActive;
/*051*/ BYTE Number;
/*???*/ } KPCR, *PKPCR;

The picture shows the GDT showing the kernel mode segments

CS : Selector = 0008, Base = 00000000, Limit = FFFFFFFF, DPL0, Type = CODE -ra

DS : Selector = 0023, Base = 00000000, Limit = FFFFFFFF, DPL3, Type = DATA -wa

FS : Selector = 0030, Base = FFDFF000, Limit = 00001FFF, DPL0, Type = DATA -wa

This kernel structure points to another important structure called the PRCB(Processor control Block). This structure maintains the state of the processor and plays a sinificant role in thread scheduling.

struct _KPRCB /* sizeof 00000C50 3152 */ {
/* off 0x00000000 */ unsigned short MinorVersion;
/* off 0x00000002 */ unsigned short MajorVersion;
/* off 0x00000004 */ struct _KTHREAD* CurrentThread;
/* off 0x00000008 */ struct _KTHREAD* NextThread;
/* off 0x0000000C */ struct _KTHREAD* IdleThread;
/* off 0x00000010 */ char Number; /* off 0x00000011 */ char Reserved;
/* off 0x00000012 */ unsigned short BuildType;
/* off 0x00000014 */ unsigned long SetMember;
/* off 0x00000018 */ char CpuType;
/* off 0x00000019 */ char CpuID;
/* off 0x0000001A */ unsigned short CpuStep;
/* off 0x0000001C */ struct _KPROCESSOR_STATE ProcessorState;
/* off 0x0000033C */ unsigned long KernelReserved[16];
/* off 0x0000037C */ unsigned long HalReserved[16];
/* off 0x000003BC */ unsigned char PrcbPad0[92];
/* off 0x00000418 */ struct _KSPIN_LOCK_QUEUE LockQueue[16];
/* off 0x00000498 */ unsigned char PrcbPad1[8]; /* off 0x000004A0


As we know that the fundamental schedulable entity in a system is a thread and not a process. We need to relate all these kernel structure for a better understanding. The KTHREAD structure is thread specific and is contained in the ETHREAD structure which contains other thread specific information.

The current thread can be found using the static PRCB structure. PRCB points to the KTHREAD structure of the current, idle and the next threads.

The diagram shows the relationship. ETHREAD contains KTHREAD and KTHREAD points to TEB(Thread Enviroment Block). Also the ETHREAD has a relationship to its process via the pointer to the EPROCESS block.

So we have 6 new structures (ETHREAD,KTHREAD,TEB,EPROCESS,KPROCESS,PEB)

Unlike the relationship that exists in the kernel thread structures. The EPROCESS structure contains both the KPROCESS structure and the Process enviroment block(PEB).

The Eprocess and Kprocess structures are contained in the kernel space whereas the PEB resides in the user memory.

The eprocess mains a linked list kind of mechanism which is used to traverse through the list of active processes(PsActiveprocessHead).

The thread enviroment block also has a pointer to its processes enviroment block(PEB).

The PEB catalogs various process attributes like (image base address, module list, heap size and count etc). This information remains in user space and is utilized by the heap manager or image loader. THE PEB is always mapped at the address 0x7ffdf000.

Sunday, October 09, 2005

Welcome to my Blog

I know I am late in the game, but its never too late to score an ace. hahah trying to give a punchline to this first post. I hope I post enough to not get this account expired