General registers (accoumlators) - an accumulator is a register in which intermediate arithmetic and logic results are storedan accumulator is a register in which intermediate arithmetic and logic results are stored.
For more information the "IA-32 Intel® Architecture Software Developer's Manual Volume 1: Basic Architecture" is a good starting point.
6.1.2Virtual Memory concepts
Virtual memory is a construct implemented in as a subsystem of a processor. It essentially allows processes to operate as if they were alone on the system  as well as provide perpetual contiguous memory.
Figure 1 - Virtual Memory 
6.1.3Basic knowledge of Compilers and Debuggers
A basic understanding of C/C++ compilers is also necessary in order to be aware of intricacies in what the assembly code generated will be and also compiler constructs to optimize code and also the layout of the program in memory depending on the addressing mode. Experience with debuggers will prove useful for generating and analyzing disassembled code. Illustrations and examples in section 5.3 use the gdb compiler.
6.2Program flow dynamics
We assume the reader is understands fundamental concepts of computing and the x86 architecture. As Shellcode interrupts the normal flow of a process, it is important to understand how the instructions of a program are executed, how the process makes use of registers and memory and also how function calls are handled using a call stack. The stack is a memory area allocated by the operating system, it essentially used to hold the execution states of process, and a level of the stack represents an execution text of variables in that state and the return address to a memory area where the next instruction exists. Context transitions occur when a function is called, or when a hardware or software interrupt is serviced. The following diagram is an illustration of how a program is organized in memory.
The text region is determined by the program; it includes code and read only data. The data region contains static variables and dynamic memory allocated by the program. The stack region is the focus area pertaining to shellcode, because a stack overflow is the means by which shellcode can be injected into a running program. “A stack is an abstract data type frequently used in computer science. As stack of objects has the property that the last object placed on the stack will be the first object removed. This property is commonly referred to as last in, first out queue, or a LIFO. ” The following illustration, reworked from “Smashing The Stack For Fun And Profit ” demonstrates how a process uses the stack.
We start of with a simple program that makes a call to function ‘A’ which takes 3 arguments. Function A declares 2 character arrays and returns. The diagram below shows the C code and corresponding assembly code:
When function A is called, its arguments are first pushed on the stack, followed by the RET address which is the address of the next instruction following the function call. Following that are the local variables Buffer1 and Buffer 2. The following diagram shows the stack right before the epilog portion of function A which is not shown in the assembly code above.
Notice that Buffer2 and Buffer1 are using more space that was declared in the function code, the additional bytes are necessary since records can only be addressed in multiples of 4 bytes, hence the compiler compensates by putting in extra bytes.
6.3Introduction to Stack based buffer overflows
To illustrate the buffer overflow we use a simple program which initializes a string of 8 bytes and passes it to a function A, which takes character pointer and copies the string into a local buffer. Because there is no bounds checking in function A, it will copy the entire string overwriting SFP and RET location in the stack.
This mechanism can be used to modify the RET address. If the contents of the string were to be populated with machine opcodes and padded with an address which points to first instruction Buffer1 in this case, we would have achieved a means to execute foreign code. This is the crux of how ShellCode can be injected into a running program. In this scenario the address AAAA may be an address that lies outside the process’s memory area and a segmentation violation will be triggered.
7Developing the Shellcode
7.1Finding the vulnerability /Buffer Overflow
Systematic methods to detect a buffer flow are available. A trail an error approach is always an option. Simply execute the target application and specify large parameters, a segmentation fault is will indicate that a buffer overflow has occurred.
7.2Writing the Shellcode:
Shellcode is sequence of machine instructions or opcode. Opcode can be written directly in hexcode, or they can be written in assembly and converted to the opcodes, or they can be written in C in which case the assembly and then the opcodes must be extracted. To take advantage of the injected code and to gain access to the target system, system calls must be used. System calls are “a special case of a software initiated trap … the machine instruction used to initiate a system call typically causes a hardware trap that is handled specially by the kernel .”
A system call handler is issued by the kernel when such an interrupt is executed. On linux there are two ways of implementing a system call, they are icall87/icall27 gates and INT 0x80 software interrupt, these are machine instructions that cause the processor to jump to a system call entry point. The EAX register contains a descriptor for the system call. Refer to “Designing Shell Code Demystified  for details about accessing system calls in an assembly. Depending on the value in the EAX register, other registers will be used accordingly.
Section 6.3 demonstrates the development of shell code that spawns a shell.
7.3Example - SHELL SPAWNING SHELLCODE
The following example extracted from “Buffer Overflow and ShellCode .” The assembly code generated is for an Intel based Linux system. We start with knowledge of a program that possesses a buffer overflow vulnerability to exploit.
The process is as follows:
The C code looks as shown:
The next step is to extract the assembly code using a compiler. GDB is used in this case producing the assembly code show in the diagrams below. Refer to the referenced article for a full explanation of the assembly code.
Dump of assembler code for function main:
End of assembler dump.
To compose the shellcode, a few intricacies are needed:
A condensed version of the shellcode will look like this:
And this corresponding shell code can be used to initialize the buffer that will be used.
Note that null bytes in the character buffer this will cause the string to be considered terminated when these bytes are processed, through strcpy for example, therefore the shellcode must be written such that there are no null opcodes.
To test the shellcode the following construct can be used.
Notice that we are modifying the return address with the address of the opcode buffer.
When main returns the shellcode will be executed.
NIDS (Network Intrusion Detection System) can be used to identify shellcode on the wire using Signature databases and Protocol analysis methods. This targets the shellcode bytes and can easily expose the whole attack by pointing out the shellcode in the traffic.
IPS (Intrusion Prevention System) identifies shellcode by running the code on a sandbox/virtualization in order to detect if the given code is malicious or not. This targets the shellcode actions, and can easily see that the shellcode is trying to perform actions which can are considered to be "malicious".
Shellcode is a powerful mechanism for the exploitation of software vulnerabilities. Software engineers with a mind for security should be aware of how to develop them and understand how they can be injected through system vulnerabilities. Shellcode can be employed to automate software security tests, where the shellcode is written to expose and draw attention to security holes
1. Wikipedia - http://en.wikipedia.org/wiki/Shellcode
2. Foster James C. & M Stuart (March 2003)
Sockets, Shellcode, Porting, & Coding: Reverse Engineering Exploits and Tool Coding for Security Professionals.
The Basics of ShellCoding. Retrieved November 26 from
Smashing The Stack For Fun And Profit. Retrieved November 26, 2007 from http://www.cs.wright.edu/~tkprasad/courses/cs781/alephOne.html
What every programmer should know about memory. Retrieved November 26 from
6. Wikipedia (November 2007).
Virtual Memory. Retrieved November 26 from
7. Wikipedia (November 2007)
X86 Architecture. Retrieved November 26 from
8. Aleph One (November 08, 1996)
Designing Shellcode Demystified. Retrieved November 26 from
Download 39.05 Kb.
Share with your friends:
The database is protected by copyright ©ininet.org 2023