Today I would like to talk about understanding Program Organization since this gives us understanding about security threats it faces till know. In order to prevent software security issues, software and hardware vendors keep working on securing software and hardware like creating ASLR, DEP (NX Bits), ProPolice, Stack Guards, Canaries and so on. So after understanding and having an overview of program organization, we will be able to analyze how those security features are implemented and what they do and why they still not helping us to prevent being hacking via malicious code execution.

In any computing system there is CPU, RAM (Memory), I/O devices (give brief explanation). These basic building blocks of computing hardware communicate via System Bus. CPU consists of 4 parts, control unit which is responsible for retrieving and decoding instruction and storing data in the memory. Execution Unit – is the place where execution takes place. When CPU executes instruction, it requires internal memory to do the Arithmetic operation [1]. That is where general purpose registers are used, they can be thought of as a temporary memory location. Flags are used to indicate various events when the execution takes place. For example when the instruction results zero, then this flag is set to according value. CPU registers are the core for storing data where CPU gets its instructions from.

IA-32 CPU architecture provides 16 basic program execution registers that can be used by system and by programmers. These registers are always grouped into 4 parts by their responsibility. The general purpose register consist of 8 registers that are responsible for storing operands and pointers. These registers can be controlled by the programmer. The 32 bit general purpose registers are as follows: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP and they are responsible for storing: Operands for logical and arithmetic operation, address calculation and for pointing to the 32 bit memory [1]. For our research will be using ESP, EBP and EIP registers as they are the key in finding and accessing the memory cell and finding their respective location. Quick delineation of the registers can be seen from the figure 7. Segment registers holds up to 6 segment registers. These registers are responsible for determining which part of the application is the machine code and which part is the data. This can be seen clearly from the Assembly programming language syntax. (Provide an example). The segment registers are as follows: CS, DS, SS, ES, FS and GS and they store 16 bit segment selector. The segment selector identifies a segment in the memory and can be shown with assembly code in Fig 1. The brief delineation of the registers can be seen from figure -8EFLAG register/ program status and control. This register is responsible on the status of the program and allows the limited use of control of the processor. The example can be seen from the C programming language when the exit status is defined. The example can be seen from following source code, SC 2 and Assembly version SC 1.

Figure 1-        General Purpose register name [1]

Figure 2-        Segment registers [1]

; ########## Source Code ########################
section .data                           ; section for initialized data
str:     db 'Hello world!', 0Ah         ; message string with new-line char at the end (10 decimal)
str_len: equ $ - str                    ; calcs length of string (bytes) by subtracting this' address ($ symbol) from the str's start address

section .text                           ; this is the code section
global _start                           ; _start is the entry point and needs global scope to be 'seen' by the linker -equivalent to main() in C/C++
_start:                                 ; procedure start
        mov     eax, 4                   ; specify the sys_write function code (from OS vector table)
        mov     ebx, 1                   ; specify file descriptor stdout -in linux, everything's treated as a file, even hardware devices
        mov     ecx, str                 ; move start _address_ of string message to ecx register
        mov     edx, str_len             ; move length of message (in bytes)
        int     80h                      ; tell kernel to perform the system call we just set up - in linux services are requested through the kernel
        mov     eax, 1                   ; specify sys_exit function code (from OS vector table)
        mov     ebx, 0                   ; specify return code for OS (0 = everything's fine)

int     80h                      ; tell kernel to perform system call

; ######### end #########


Source Code 1 –               Assembly Code

######## Source of Hello World in C version ########

in main (int argc, char **argv){

printf(“Hello World”);

return 0;

}

#########End of code ###########

Source Code 2 –               C code

EIP register contains 32 bit pointer which is as big as the single memory. Each memory cell is 32 bit long or 4 bytes. Further details will be provided in the next section. In virtual Memory or RAM every process is laid out in the same memory space – regardless of the actual physical memory location. Every process that is created, the space is given according to how much space is required by the application. Every process is in its own little world, not being aware of other processes. The OS and CPU usually aid the process to be kept separate [1], [2]. For every process or program created the memory looks as shown in Fig – 1.
Figure 3 – Stack created for the process [3]

Stack is LIFO or Last In First Out abstract data types, that is laid out in linear manner. Stack consist of continious array of memory cells that be used to store values for temporary use. Stack operates mainly with two instructions “push” and “pop” to create or to remove the memory blocks, but the data will remain there, just the EIP instruction pointer will point to the previous or next memory block. We will not cover in depth stack as it is outside of the research scope.

Note:  /* Descriptions are used to explain the source code. */

When the program is compiled and run, the program first declares the test function and they are declared as integers: a, b, c and d. There are also local variables in this function that include the one undeclared flag variable and 10 bytes long char buffer. The memories for these variables are located in the stack segment and the according machine instructions are located in the text or code segment. The C source code is shown below in Source Code – 3.

### start of the code ###

void test_function(int a, int b, int c, int d) {

int flag;

char buffer[10];

flag = 31337;

buffer[0] = ‘A’; }

int main() {    test_function(1, 2, 3, 4); }

###END OF THE CODE ###

Source Code 3 –               C source code

The inner operation can be seen by using the GDB or ‘ollyDBG’. When looking at the code using the GDB, there will be function prologue and epilogue that builds up the stack for the process. Source code 4 will show the assembly code.

################### START OF CODE #################

3ntr0py@hacking:~/booksrc $ gdb -q ./a.out

Using host libthread_db library “/lib/tls/i686/cmov/libthread_db.so.1”.

(gdb) disass main

Dump of assembler code for function main():

0x08048357 <main+0>:    push   ebp

0x08048358 <main+1>:    mov    ebp,esp

0x0804835a <main+3>:    sub    esp,0x18

0x0804835d <main+6>:    and    esp,0xfffffff0

0x08048360 <main+9>:    mov    eax,0x0

0x08048365 <main+14>:   sub    esp,eax

0x08048367 <main+16>:   mov    DWORD PTR [esp+12],0x4

0x0804836f <main+24>:   mov    DWORD PTR [esp+8],0x3

0x08048377 <main+32>:   mov    DWORD PTR [esp+4],0x2

0x0804837f <main+40>:   mov    DWORD PTR [esp],0x1

0x08048386 <main+47>:   call   0x8048344 <test_function>

0x0804838b <main+52>:   leave

0x0804838c <main+53>:   ret

End of assembler dump

(gdb) disass test_function()

Dump of assembler code for function test_function:

0x08048344 <test_function+0>:   push   ebp

0x08048345 <test_function+1>:   mov    ebp,esp

0x08048347 <test_function+3>:   sub    esp,0x28

0x0804834a <test_function+6>:   mov    DWORD PTR [ebp-12],0x7a69

0x08048351 <test_function+13>:  mov    BYTE PTR [ebp-40],0x41

0x08048355 <test_function+17>:  leave

0x08048356 <test_function+18>:  ret

End of assembler dump

(gdb)

############### END OF CODE ############

Source Code 4 –               Inner Operation of the Program

When the function is called within main function, all sorts of data are pushed into the stack. For our example, when the test function is called the variables are pushed in the reverse order as it is LIFO shown in Source Code – 5.

#######

(gdb) disass main

Dump of assembler code for function main:

0x08048357 <main+0>:    push   ebp

0x08048358 <main+1>:    mov    ebp,esp

0x0804835a <main+3>:    sub    esp,0x18

0x0804835d <main+6>:    and    esp,0xfffffff0

0x08048360 <main+9>:    mov    eax,0x0

0x08048365 <main+14>:   sub    esp,eax

0x08048367 <main+16>:   mov    DWORD PTR [esp+12],0x4

0x0804836f <main+24>:   mov    DWORD PTR [esp+8],0x3

0x08048377 <main+32>:   mov    DWORD PTR [esp+4],0x2

0x0804837f <main+40>:   mov    DWORD PTR [esp],0x1

0x08048386 <main+47>:   call   0x8048344 <test_function>

0x0804838b <main+52>:   leave

0x0804838c <main+53>:   ret

End of assembler dump

(gdb)

Source Code 5 –               Stack push operation

The call instruction both stores the return address on the stack and jumps EIP to the beginning of test_function(), so test_function()’s procedure prologue instructions finish building the stack frame. In this step, the current value of EBP is pushed to the stack. This value is called the saved frame pointer (SFP) and is later used to restore EBP back to its original state. The current value of ESP is then copied into EBP to set the new frame pointer. This frame pointer is used to reference the local variables of the function (flag and buffer). Memory is saved for these variables by subtracting from ESP.

This is high basically how the program is organized inside the CPU and RAM, even though the technology is growing and the architecture of the CPU and system vary basic organization of the program remains similar to this structure. So, understanding the program organization will help us how the security related issues in the software remain major topic.

References:

[1] ‘Intel® 64 and IA-32 Architectures Developer’s Manual: Vol 1’.

[2] Wikipedia contributors, ‘Operating system’

[3] C. Cowan, F. Wagle, Calton Pu, S. Beattie, and J. Walpole, ‘Buffer overflows: attacks and defenses for the vulnerability of the decade’, in DARPA Information Survivability Conference and Exposition, 2000. DISCEX  ’00. Proceedings, 2000, vol. 2, pp. 119–129 vol.2.