[ Security ] Ch11. Buffer Overflow

38A·2024년 10월 8일
0

컴퓨터 보안

목록 보기
10/11
post-thumbnail

Understanding Process with GDB

  • GDB: GNU Project Debugger
  • It allows you to see what is going on inside another program while it executes or what another program was doing at the moment it crashed.
  • It can do four main kinds of things to help you catch bugs in the act:
    • Start your program, specifying anything that might affect its behavior.
    • Make your program stop on specified conditions.
    • Examine what has happened, when your program has stopped.
    • Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another
  • GDB-PEDA
    • PEDA: Python Exploit Development Assistance for GDB
      • GDB-PEDA is installed on the Prebuilt SEED VM.
    • Enhance the display of GDB
      • Colorize and display disassembly codes, registers, memory information during debugging
    • Add commands to support debugging and exploit development (for a full list of commands use peda help)

Process Memory

GDB command ( PDF )


Buffer Overflow Attack

  • Vulnerable Program
    • Reading 300 bytes of data from badfile.
    • Storing the file contents into a str variable of size 400 bytes.
    • Calling func1 function with str as an argument.
    • Note : Badfile is created by the user and hence the contents are in control of the user.
  • Consequences of Buffer Overflow
    • Overwriting return address with some random address can point to :
      • Invalid instruction
      • Non-existing address
      • Access violation
      • Attacker’s code → Malicious code to gain access
  • How to Run Malicious Code
  • Environment Setup

Malicious Input

  • Generating Malicious Input

Task A

  • Find the distance between the buffer base address and return
    address

Task B : Find the address of malicious code

  • Malicious code is written in the badfile which is passed as an argument to the vulnerable function.
  • Using gdb, we can find the address of the function argument.
  • To increase the chances of jumping to the correct address, of the malicious code, we can fill the badfile with NOP instructions and place the malicious code at the end of the buffer.
    • NOP (0x90) - Instruction that does nothing.
    • Q. What would happen without NOPs?
  • Considerations for new address
    • The new address in the return address of function stack [0x7fffffffdd88 + X] should not contain zero in any of its byte, or the badfile will have a zero causing strcpy() to end copying.
      • e.g., 0x7fffffffdd88 + 0x78 = 0x7fffffffde00, the last byte contains zero leading to end copy.
  • Compiling the vulnerable code with all the countermeasures disabled
  • Executing the exploit code and stack code

Shellcode

  • Aim of the malicious code
    • Allow to run more commands (i.e) to gain access of the system
  • Solution: Shell Program
  • Challenges
    • Loader Issue
    • Zeros in the code
  • Assembly code (machine instructions) for launching a shell
  • Registers used
    • $rax: 0x3b (59) → Value of system call execve()
    • $rdi: address to "/bin/sh"
    • $rsi: address of the argument array
      • argv[0] = the address of "/bin/sh"
      • argv[1] = 0 (i.e., no more arguments)
    • $rdx: zero (no environment variables are passed)

Countermeasures

  • Developer approaches:
    • Use of safer functions like strncpy(), strncat() etc, safer dynamic link
      libraries that check the length of the data before copying.
  • OS approaches:
    • Address Space Layout Randomization (ASLR)
  • Compiler approaches:
    • Stack-Guard
  • Hardware approaches:
    • Non-Executable Stack

ASLR ( OS approach )

  • Principles of Address Space Layout Randomization
  • In Linux, ASLR can be configured by kernel parameter ‘randomize_va_spaceVDSO : kernel, user space 사이 영역
    2: Full address space ( + Heap )x -> stack, y -> heap
  • Defeat it
    • (From Author’s slides) On running the script for about 19 minutes on a 32-bit Linux machine, we got the access to the shell (malicious code got executed)

Stack Guard ( Compiler approach )

  • Stackguard is a compiler approach to defeat buffer overflow.
  • A random secret value (change 되었는지 check) is generated and stored in a memory location (not on stack) and is assigned to a local variable of the function which gets stored in the stack.
  • After the copy function is function, it is checked if the value of the local variable is changed. If yes, buffer overflow has taken place and the program exits without returning.
    개념으로만 이해해도 OK

Non-Executable Stack ( Hardware approach )

  • NX bit, standing for No-eXecute feature in CPU separates code from data which marks certain areas of the memory as non-executable.
  • This countermeasure can be defeated using a different technique called Return-to-libc attack (there is a separate chapter on this attack)

Return-to-Libc

  • Non-executable Stack
    • Running shellcode in C programexecve("\bin\sh")backdoor
  • How to Defeat This Countermeasure
    • Jump to existing code: e.g. libc library.
    • Function: system(cmd)
      • cmd argument is a command which gets executed
  • Vulnerable Program
  • Environment Setup
  • Overview of the Attack
    • Task A : Find address of system().
      • To overwrite return address with system()’s address.
    • Task B : Find address of the "/bin/sh" string. -> argument of system function
      • To run command "/bin/sh" from system()
    • Task C : Construct arguments for system() -> passing parameter
      • To find location in the stack to place "/bin/sh" address (argument for system())

Task A: To Find system()’s Address

  • Debug the vulnerable program using gdb
  • Using p (print) command, print address of system() and exit()ldd : 관련 library list

Task B: To Find "/bin/sh" String Address

  • libc includes "/bin/sh"
    • system() provided by libc is designed to execute commands through the shell. It uses "/bin/sh" path by default to invoke the shell
    • By embedding the "/bin/sh" string in libc, the system can efficiently refer to this predefined string instead of generating it dynamically each time a shell is invoked
  • Is it possible to embed the malicious string we want?
    • Use environment variable!
    • Address of “MYSTRING” environment variable is sensitive to the length of the program name

Task C: Argument for system()

  • We can jump to system() by overwriting the return address in func2()
  • Before we jump to system(), we should set argument
    • In x64, $rdi is used for first argument of function
  • Thus, our goal is to set $rdi to address of "/bin/sh“
  • How can we set $rdi without executing the code we injected?
    → Return Oriented Programming (ROP)!

Return-Oriented Programming (ROP)

  • ROP is an advanced technique used by attackers to execute arbitrary code in a program that has protections such as non-executable stack or data execution prevention (DEP)
  • ROP uses existing code snippets (gadgets) to achieve the desired behavior
    • A “gadget” is a short sequence of instructions that ends with a ret (return) instruction.
    • Gadgets are typically found in the program's existing code, uch as in its binary or shared libraries (like libc)
    • These gadgets perform useful tasks, such as loading values into registers, performing arithmetic operations, or system calls
  • In ROP, instead of injecting new code, the attacker changes program’s control flow by overwriting the return address on the stack with the address of a gadget. (The program returns to the attacker-chosen gadget instead of it normal return point)
  • After executing the gadget, control return to the next gadget, and so on.
  • By chaining gadgets together, the attacker can achieve complex functionality.
  • Stack for gadget
  • Find the address for gadget "pop rdi; ret"
  • Find the offset distance between the base of the buffer and return address
  • Generating Malicious Input
  • Execution: First Attemptnot working ...
  • Debugging
    • Issue of stack alignment
      • movaps (Move Aligned Packed Single-Precision) requires 16-byte aligned memory addresses.
      • If the memory address is not aligned to a 16-byte boundary, movaps can cause an invalid memory access error (segmentation fault).
      • The previous approach didn’t account for 16-byte stack alignment.
      • Therefore, we need to align the stack pointer ($rsp) to a 16-byte boundary before calling system()
      • This issue can be resolved by injecting an additional "ret" gadget.
      • The "ret" instruction moves the $rsp up by 8 bytes. (equivalent to "sub rsp, 8")
  • Execution: Second Attempt

HGU 전산전자공학부 고윤민 교수님의 24-2 컴퓨터 보안 수업을 듣고 작성한 포스트이며, 첨부한 모든 사진은 교수님 수업 PPT의 사진 원본에 필기를 한 수정본입니다.

profile
HGU - 개인 공부 기록용 블로그

0개의 댓글