CSE 127: Buffer Overflow (Continuation)
Spring 2022 Lecture 2
Continuation
Copyright By PowCoder代写 加微信 powcoder
Linux process memory layout
• Stack:Storeslocal variables.
• Heap:Dynamic memory for programmer to allocate.
• Data segment: Stores global variables, separated into initialized and uninitialized.
• Textsegment:Stores the code being executed.
• Stack divided into frames
• Framestoreslocalsandargstocalledfunctions
• Stack pointer points to top of stack
• x86: Stack grows down (from high to low addresses)
• x86:Storedin%espregister(%rspon64-bit) • Frame pointer points to caller’s stack frame
• Alsocalledbasepointer
• x86:Storedin%ebpregister(%rbpon64-bit)
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst
• %register $literal offset(memory-reference)
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst
• %register $literal offset(memory-reference)
• Examples:
movl %eax, %edx →
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst • %register
• Examples:
movl %eax, %edx
$literal offset(memory-reference)
C Pseudo-code
→ edx = eax
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst • %register
• Examples:
$literal offset(memory-reference)
movl %eax, %edx
movl $0x123, %edx →
C Pseudo-code
→ edx = eax
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst
• %register $literal
• Examples:
offset(memory-reference)
movl %eax, %edx → edx = eax movl $0x123, %edx → edx = 0x123
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst • %register
• Examples:
$literal offset(memory-reference)
movl %eax, %edx
movl $0x123, %edx
movl (%ebx), %edx →
→ edx = 0x123
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst • %register
• Examples:
movl %eax, %edx
movl $0x123, %edx
movl (%ebx), %edx → edx = *((int32_t)*) ebx)
$literal offset(memory-reference)
→ edx=eax → edx=0x123
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst • %register
• Examples:
$literal offset(memory-reference)
movl%eax, %edx
movl $0x123, %edx
movl (%ebx), %edx
movl 4(%ebx), %edx →
→ edx=0x123
→ edx = *((int32_t)*) ebx)
Brief review of x86 assembly
• We’regoingtouseAT&T/gasmsyntax
• op src, dst • %register
• Examples:
movl%eax, %edx movl $0x123, %edx movl (%ebx), %edx movl 4(%ebx), %edx
$literal offset(memory-reference)
→ edx=0x123
→ edx = *((int32_t)*) ebx)
→ edx = *((int32_t)*) ebx+4)
Brief review of stack instructions
Stack operation equivalent
pushl %eax → subl $4, %esp movl %eax, (%esp)
Brief review of stack instructions
Stack operation
pushl %eax popl %eax
equivalent
→ subl $4, %esp movl %eax, (%esp)
→ movl (%esp), %eax addl $4, %esp
Brief review of stack instructions
Stack operation
pushl %eax
equivalent
→ subl $4, %esp movl %eax, (%esp)
→ movl (%esp), %eax addl $4, %esp
c a l l $0x12345 → pushl %eip
movl $0x12345, %eip
Brief review of stack instructions
Stack operation
pushl %eax
Pseudo-asm equ
→ subl $4, %esp movl %eax, (%esp)
→ movl (%esp), %eax addl $4, %esp
c a l l $0x12345 → pushl %eip
movl $0x12345, %eip ret → popl %eip
Brief review of stack instructions
Stack operation
pushl %eax popl %eax
Pseudo-asm equ
→ subl $4, %esp movl %eax, (%esp)
→ movl (%esp), %eax addl $4, %esp
$0x12345 → pushl %eip
movl $0x12345, %eip
→ popl %eip
→ movl %ebp, %esp pop %ebp
int check_authentication (char *password){ int auth_flag = 0;
char password_buffer[16];
strcpy(password_buffer, password);
if (strcmp(password_buffer, “brillig”)==0)
auth_flag = 1;
if (strcmp(password_buffer, “outgrabe”)==0)
auth_flag = 1; return auth_flag; }
passwordbuf.c
#include
#include
int main(int argc, char**argv) {
char nice[] = “is nice.”; char name[8];
strcpy(name,argv[1]); printf(“%s %s\n”,name,nice);
return 0; }
example1.c
#include
#include
int main(int argc, char**argv) {
char nice[] = “is nice.”; char name[8];
strcpy(name,argv[1]); printf(“%s %s\n”,name,nice);
return 0; }
What happens if we read a long name?
#include
#include
int main(int argc, char**argv) { char nice[] = “is nice.”;
char name[8]; strcpy(name,argv[1]);
printf(“%s %s\n”,name,nice); return 0;
What happens if we read a long name?
If not null terminated, can read more of the stack.
#include
void foo() {
printf(“hello all!!\n”); exit(0);
void func(int a, int b, char *str) {
int c = 0xdeadbeef;
char buf[4];
strcpy(buf,str);
int main(int argc, char**argv) { func(0xaaaaaaaa,0xbbbbbbbb,argv[1] );
example2.c
If program argument is long…
If program argument is long…
Stack buffer overflow
• If source string of strcpy controlled by attacker and destination on the stack:
• Attacker gets to control where the function returns by overwriting the return address
• Attacker gets to transfer control to anywhere • Wheredoyoujump?
Can jump to existing functions
Overwrite saved ret with &foo. #include
#include
void foo() {
printf(“hello all!!\n”); exit(0);
void func(int a, int b, char *str) {
int c = 0xdeadbeef;
char buf[4];
strcpy(buf,str);
int main(int argc, char**argv) { func(0xaaaaaaaa,0xbbbbbbbb,argv[1] );
Jump to existing functions
Jump to attacker-supplied code
• Putcodeinstring
• Shellcode: Small code fragment that receives initial control in a control flow hijack exploit
• Control flow hijack: taking control of instruction pointer • Earliestattacksusedshellcodetoexecashell
• Targetasetuidrootprogram,getsyourootshell
int main(void) {
char* name[1];
name[0] = “/bin/sh“; name[1] = NULL; execve(name[0], name, NULL); return 0;
Can we just take output from gcc/clang?
• Shellcodecannotcontainnullcharacters‘\0’ • Why?
• If payload is via gets() must also avoid line breaks • Why?
• Fix: Use different instructions and NOPs.
Payload is not always robust
• Exact address of shellcode start not always easy to guess.
Payload is not always robust
• Exact address of shellcode start not always easy to guess.
• Amisswillresultina segfault.
Payload is not always robust
• Exact address of shellcode start not always easy to guess.
• Amisswillresultina segfault.
• Fix:NOPsled.Fillspace with NOP instructions to allow error in stack locations.
Possible Mitigations
Avoiding Buffer Overflows Attack • Do memory auditing by using Valgrind memcheck
#include
int main() {
int *buf = malloc(sizeof(int) * 20); for (int i=0; i<20; i++){
buf[i] = i;
// forgot to free buf
valgrind.c
Avoiding Buffer Overflows Attack
• Usefgetsinsteadofgets()
• Usestrncmp()insteadofstrcmp() • Usestrncpy()insteadofstrcpy()
Use of gets
#include
int main() { char string[10];
printf(“Enter the String: “); gets(string);
printf(“\n%s”,string); return 0;
Use of fgets
#include
int main() {
char string[20]; printf(“Enter the string: “);
fgets(string,20,stdin); #input from stdin stream
printf(“\nThe string is: %s”,string);
Group Task
Question 1
Where can an attacker who is trying to “smash the stack” put their attack code if the buffer to be overflowed is on the stack?
a. On the stack before the return pointer
b. On the stack frame of another function
c. On the heap
d. All of the above
Question 2
Which of these kinds of buffer overflows can be a security threat?
a. Unsafe Library function calls
b. Buffers that store internal data
c. Stack smashing d. All of the above
Question 3
Use Valgrind to uncover the problem with the below.
int fun(int n) {
char *pInfo = malloc (n *sizeof(char));
/* Do some work */
return 0; }
Next up: Defenses and more advanced attacks.
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com