Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
11 views46 pages

04-Control Hijacking Attacks

The document discusses control hijacking attacks, focusing on buffer overflows as a common technique for attackers to gain control of a victim's machine by manipulating memory and altering execution flow. It explains the mechanics of buffer overflows, including how they occur in programming languages like C/C++, and outlines various attack strategies, including the use of shellcode and format string vulnerabilities. Additionally, it highlights the importance of understanding memory regions and the implications of exploiting such vulnerabilities in software applications.

Uploaded by

aahilbot121
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views46 pages

04-Control Hijacking Attacks

The document discusses control hijacking attacks, focusing on buffer overflows as a common technique for attackers to gain control of a victim's machine by manipulating memory and altering execution flow. It explains the mechanics of buffer overflows, including how they occur in programming languages like C/C++, and outlines various attack strategies, including the use of shellcode and format string vulnerabilities. Additionally, it highlights the importance of understanding memory regions and the implications of exploiting such vulnerabilities in software applications.

Uploaded by

aahilbot121
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

Control Hijacking Attacks

Alexandros Kapravelos
[email protected]

(Derived from slides by Chris Kruegel)


Attacker’s mindset
• Take control of the victim’s machine
– Hijack the execution flow of a running program
– Execute arbitrary code
• Requirements
– Inject attack code or attack parameters
– Abuse vulnerability and modify memory such that control flow is
redirected
• Change of control flow
– alter a code pointer (i.e., value that influences program counter)
– change memory region that should not be accessed
Buffer Overflows
• Result from mistakes done while writing code
– coding flaws because of
• unfamiliarity with language
• Ignorance about security issues
• unwillingness to take extra effort
• Often related to particular programming language
• Buffer overflows
– mostly relevant for C / C++ programs
– not in languages with automatic memory management
• dynamic bounds checks (e.g., Java)
• automatic resizing of buffers (e.g., Perl)
Buffer Overflows
• One of the most used attack techniques
• Advantages
– very effective
• attack code runs with privileges of exploited process
– can be exploited locally and remotely
• interesting for network services
• Disadvantages
– architecture dependent
• directly inject assembler code
– operating system dependent
• use of system calls
– some guesswork involved (correct addresses)
Process memory regions
• Stack segment Top of
memory
– local variables
– procedure calls
• Data segment
– global initialized variables (data)
– global uninitialized variables (bss)
– dynamic variables (heap)
• Code (Text) segment
– program instructions
– usually read-only
Overflow types
• Overflow memory region on the stack
– overflow function return address
– overflow function frame (base) pointer
– overflow longjmp buffer
• Overflow (dynamically allocated) memory region on the
heap
• Overflow function pointers
– stack, heap, BSS
Stack
• Usually grows towards smaller memory addresses
– Intel, Motorola, SPARC, MIPS
• Processor register points to top of stack
– stack pointer – SP
– points to last stack element or first free slot
• Composed of frames
– pushed on top of stack as consequence of function calls
– address of current frame stored in processor register
• frame/base pointer – FP
– used to conveniently reference local variables
Stack
Procedure Call
A Closer Look
A Closer Look
The foo Frame
Taking Control of the Program
Buffer Overflow
• Code (or parameters) get injected because
– program accepts more input than there is space allocated

• In particular, an array (or buffer) has not enough space


– especially easy with C strings (character arrays)
– plenty of vulnerable library functions
strcpy, strcat, gets, fgets, sprintf ..

• Input spills to adjacent regions and modifies


– code pointer or application data
• all the possibilities that we have enumerated before
– normally, this just crashes the program (e.g., sigsegv)
Example
// Test2.c
#include <stdio.h>
#include <string.h>

int vulnerable(char* param) Buffer that can contain 100 bytes


{
char buffer[100];
Copy an arbitrary number of
strcpy(buffer, param);
characters from param to buffer
}

int main(int argc, char* argv[])


{
vulnerable(argv[1]);
printf(“Everything's fine\n”);
}
Let's Crash

> ./test2 hello Everything's fine

> ./test2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault

>
What Happened?

> gdb ./test2 (gdb) run hello


41 41 41 41
Starting program: ./test2 Everything's fine params
41 41 41 41
ret address 41 41 41 41
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAA 41 41 41 41
saved EBP
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
41 41 41 41
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA 41 41 41 41
buffer
41 41 41 41
Starting program: ./test2 AAAAAAAAA...
Program received signal SIGSEGV, 41 41 41 41
Segmentation fault.
0x41414141 in ?? ()
Choosing Where to Jump
• Address inside a buffer of which the attacker controls the content
– works for remote attacks
– the attacker need to know the address of the buffer, the memory page containing the
buffer must be executable
• Address of a environment variable
– easy to implement, works with tiny buffers
– only for local exploits, some program clean the environment, the stack must be
executable
• Address of a function inside the program
– works for remote attacks, does not require an executable stack
– need to find the right code, one or more fake frames must be put on the stack
Jumping into the Buffer

• The buffer that we are overflowing is usually a good place to put the
code (shellcode) that we want to execute

• The buffer is somewhere on the stack, but in most cases the exact
address is unknown
– The address must be precise: jumping one byte before or after would just
make the application crash
– On the local system, it is possible to calculate the address with a debugger,
but it is very unlikely to be the same address on a different machine
– Any change to the environment variables affect the stack position
Solution: The NOP Sled
• A sled is a “landing area” that is put in front of the shellcode
• Must be created in a way such that wherever the program jump into it..
– .. it always finds a valid instruction
– .. it always reaches the end of the sled and the beginning of the shellcode

• The simplest sled is a sequence of no operation (NOP) instructions


– single byte instruction (0x90) that does not do anything
– more complex sleds possible (ADMmutate)

• It mitigates the problem of finding the exact address to the buffer by increasing
the size of the target are area
Assembling the Malicious Buffer

params
buf address ret address
base pointer
shellcode

buffer
90 90 90 90
90 90 90 90
Code Pointer

previous frame

function arguments

new code pointer


shellcode
Any return address into
the NOP sled succeeds
NOP sled
Solution: Jump using a Register

• Find a register that points to the buffer (or somewhere into it)
– ESP
– EAX (return value of a function call)

• Locate an instruction that jump/call using that register


– can also be in one of the libraries
– does not even need to be a real instruction, just look for the right
sequence of bytes
jmp ESP = 0xFF 0xE4

• Overwrite the return address with the address of that instruction


shellcode
Buffer Overflow
• Executable content (called shellcode)
– usually, a shell should be started
• for remote exploits - input/output redirection via socket
– use system call (execve) to spawn shell

• Shellcode can do practically anything


– create a new user
– change a user password
– modify the .rhost file
– bind a shell to a port (remote shell)
– open a connection to the attacker machine
Shellcode
void main(int argc, char **argv) { char *name[2];
name[0] = “/bin/sh“; name[1] = NULL;

execve(name[0], &name[0], &name[1]); exit(0);


}

int execve(char *file, char *argv[], char *env[])

• file is name of program to be executed


“/bin/sh”
• argv is address of null-terminated argument array
{ “/bin/sh“, NULL }
• env is address of null-terminated environment array
NULL (0)
Shellcode

int execve(char *file, char *argv[], char *env[])

(gdb) disas execve


....
mov 0x8(%ebp),%ebx copy *file to ebx
mov 0xc(%ebp),%ecx copy *argv[] to ecx
mov 0x10(%ebp),%edx copy *env[] to edx
mov $0xb,%eax
int $0x80 put the system call
.... number in eax
(execve = 0xb)

invoke the syscall


Shellcode
• Spawning the shell in assembly

1. move system call number (0x0b) into %eax


2. move address of string /bin/sh into %ebx
3. move address of the address of /bin/sh into %ecx (using lea)
4. move address of null word into %edx
5. execute the interrupt 0x80 instruction
Shellcode
• file parameter
– we need the null terminated string /bin/sh somewhere in memory

• argv parameter
– we need the address of the string /bin/sh somewhere in memory,
– followed by a NULL word

• env parameter
– we need a NULL word somewhere in memory
– we will reuse the null pointer at the end of argv

30
Shellcode
• execve arguments

located at address addr

/bin/sh0addr0000

env -- pointer to null-word

arg -- pointer to address of null-terminated string

file -- null-terminated string


Shellcode

• Problem - position of code in memory is unknown


– How to determine address of string
• We can make use of instructions using relative
addressing
• call instruction saves IP on the stack and jumps
• Idea
– jmp instruction at beginning of shellcode to call instruction
– call instruction right before /bin/sh string
– call jumps back to first instruction after jump
– now address of /bin/sh is on the stack
Shellcode

jmp_addr
jmp call_addr
popl %esi %esi holds address
of string /bin/sh
Shellcode
call_addr
call jmp_addr + 1
/bin/sh0000
The Shellcode (almost ready)

jmp 0x26 #2 bytes


popl %esi #1 byte
movl %esi,0x8(%esi) #3 bytes setup
movb $0x0,0x7(%esi) #4 bytes
movl $0x0,0xc(%esi) #7 bytes
movl $0xb,%eax #5 bytes
movl %esi,%ebx #2 bytes
leal 0x8(%esi),%ecx #3 bytes execve()
leal 0xc(%esi),%edx #3 bytes
int $0x80 #2 bytes
movl $0x1, %eax #5 bytes
movl $0x0, %ebx #5 bytes exit()
int $0x80 #2 bytes
call -0x2b #5 bytes
.string \"/bin/sh\" #8 bytes setup
Pulling It All Together

previous frame
new code pointer
function arguments

return address
shellcode
previous frame pointer

local variables

char buffer[]
Pulling It All Together

previous frame
new code pointer
function arguments

return address
shellcode
previous frame pointer

local variables

Overflow char buffer[]


Pulling It All Together

previous frame

function arguments

new code pointer

shellcode
Shellcode

• Shellcode is usually copied into a string buffer

• Problem
– any null byte would stop copying
→ null bytes must be eliminated

mov 0x0, reg → xor reg,reg


mov 0x1, reg → xor reg, reg; inc reg
Shellcode
• Concept of user identifiers (uids)
– real user id
• ID of process owner

– effective user id
• ID used for permission checks

– saved user id
• used to temporarily drop and restore privileges

• Problem
– exploited program could have temporarily dropped privileges

• Shellcode has to enable privileges again (using setuid)

• Setuid Demystified: Hao Chen, David Wagner, and Drew Dean


Small Buffers
• Buffer can be too small to hold exploit code
• Store exploit code in environmental variable
– environment stored on stack
– return address has to be redirected to environment variable

• Advantage
– exploit code can be arbitrary long
• Disadvantage
– access to environment needed
Heap Overflow
• Heap overflow requires modification of boundary tags
– in-band management information
– task is to fake these tags to trick dlmalloc into overwriting addresses of attackers
choice

• Different techniques for other memory managers


– System V (Solaris, IRIX) - self-adjusting binary trees
– Phrack 57-9 (Once upon a free())
Format String Vulnerability
• Problem of user supplied input that is used with *printf()
– printf(“Hello world\n“); // is ok
– printf(user_input); // vulnerable

• *printf()
– function with variable number of arguments
int printf(const char *format, ...)
– as usual, arguments are fetched from the stack

• const char *format is called format string


– used to specify type of arguments
• %d or %x for numbers
• %s for strings
Format String Vulnerability

#include <stdio.h>

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


buf[128];
int x = 1;

snprintf(buf, sizeof(buf), argv[1]);


buf[sizeof(buf) - 1] = '\0';
printf("buffer (%d): %s\n", strlen(buf),buf);
printf("x is %d/%#x (@ %p)\n", x, x, &x);
return 0;

}
Format String Vulnerability

akaprav@tardis:~/test > ./vul ”AAAA %x %x %x %x“


buffer (28): AAAA 40017000 1 bffff680 4000a32c
x is 1/0x1 (@ 0xbffff638)

akaprav@tardis:~/test > ./vul "AAAA %x %x %x %x %x“


buffer (35): AAAA 40017000 1 bffff680 4000a32c 1
x is 1/0x1 (@ 0xbffff638)

akaprav@tardis:~/test > ./vul "AAAA %x %x %x %x %x %x“


buffer (44): AAAA 40017000 1 bffff680 4000a32c 1 41414141
x is 1/0x1 (@ 0xbffff638)
Format String Vulnerability

Stack Layout
char buf[128]

int x
stack frame for main()

fmt string

sizeof(buf) arguments for snprintf()


&buf[0]

stack frame for snprintf()


Format String Vulnerability
Format String Vulnerability
• %n
The number of characters written so far is stored into the
integer indicated by the int*(or variant) pointer argument

(man 3 printf)

• One can use width modifier to write arbitrary values


– for example, %.500d
– even in case of truncation, the values that would have been written are used for %n

You might also like