2023-04-20 STLLINUX V19apr2023
2023-04-20 STLLINUX V19apr2023
(an intro)
Saint Louis Linux Users Group (STLLUG)
Bryce L. Meyer
April 20th, 2023
Note: most slides are extracted
Overview from a course I developed and
teach at Franciscan University of
Steubenville…it uses the Grey
Hat Hacking textbook, and a lab
• From Weakness to Exploit: What makes a hole… we built called the Danger lab
Repeating process
Where can I find threats?
Picture (Optio
ISO Maps
MISRA C and C++ St MISRA
andards
IEEE IEEE and ISO
Standards (e.g., CWE/SANS Top 25 SANS
ISO/IEC 9899:2018)+ Maps
Compilers
Listed from
Maps OWASP
Maps MITRE CWE
SEI CERT Coding Standards Maps
(Common OWASP Top 10 (et al.)
SEI (CERT) for C, C++, Java, Perl, and Weakness and Attack Scenarios
Android Enumeration)
https://wiki.osdev.org/Stack_Trace https://www.techtarget.com/whatis/definition/stack-pointer
https://wiki.osdev.org/Stack https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/
https://en.wikipedia.org/wiki/Extended_memory https://en.wikipedia.org/wiki/Function_prologue_and_epilogue
Figuring out Stack Frames
• Track the current EIP, ESP, EBP
• Every line in the stack frame has a memory address in the stack (32-bit:
0xfffffff0 to 0x11111111 usually
• Lines in machine code are not the same space normally, they are .text…
Address of stack line Value at address
STACK:
0xffff0004| +0x0004: 0xffffa0a0 // say_hi argument 1
ESP 0xffff0000| +0x0008: 0x0804845a // Return address from say_hi
Relative address of stack line
Pointers:
EIP: 804840b (first line of say_hi) Sometimes the stack line is called the
ESP = 0xffff0000 stack frame…be wary of context
EBP = 0xffff002c (room for say_hi’s frame, way above current lines in stack)
32-bit .text is where binary instructions go…
stack The Instruction Pointer moves down the .text list until it hits
a ‘return’ instruction which sends it back to its calling
function’s binary (usually main, line below call)
Lower addresses Higher addresses
EIP
Function
1’s EBP
ESP
(defined) Variables
Function1’s Saved
Main’s Arguments
Main’s Saved EBP
Main’s Local
Function1’s
Function1
Main (‘0’)
Growth
EBP
(i.e.
added
functions)
Low Memory There can be various locations in the address space for these components!!!! High Memory
0x11111111 0xfffffff0
Key Compiler Options: gcc
• Many compile options open holes…sometimes driver or 3rd party app
makers use them for shortcuts to avoid warnings, or use them in test and
leave them in for deployed code on accident…
• -w : ignore warnings….. (bad idea!!!!)
It is bad to use No’s for these defaults (i.e. –fno-) :
• -fstack-protector(-all): add stack protection guards (i.e. canaries..more
later)
• -fpie: Position Independent Executable
• This disables NX bit implementation:
• -z execstack
https://man7.org/linux/man-pages/man1/gcc.1.html
What happens when I compile and run a
program with a function
• When a program runs, it walks the machine code instruction
lines until it encounters a call to a function.
• At the call, program loads the stack like so (higher value
addresses to lower addresses):
1. Stores function arguments in reverse order (i.e. 3,2,1)
2. Stores the instruction pointer for the line after the call
3. Stores the location of the base of the stack
4. Adds a segment of memory as allocated for each variable,
strings, numbers, etc.
What happens when I compile and run a
program with a function (2)
• When the program fills the data for the variables as it runs, it
uses the allocated memory in the stack, from lower addresses
to higher addresses, so if there is more input to the variable
then allocated, it overwrites into higher addresses
• When the function hits return instruction, it uses the stored
instruction pointer to continue into the calling function past
the call.
• If the stored instruction pointer is overwritten, it tries to use
the data that is now in that spot….usually this causes a
segmentation error
How does a stack overflow work?
STACK If myinput is the
• A variable, array, etc. is right size, it
Function1’s
assigned a size:E.g. Arguments (in overflows the
char mystringhere [200]; reverse order) variable area, past
• Another part of the the saved base
Saved Instruction pointer, into the
program allows more Pointer for
saved instruction
than the size to go into Function1 (return)
pointer … which
the variable” like: Function1’s Saved means I can put
char myinput [600]; Base Pointer
anything as Saved
strcpy (mystringhere, myinput);
Function1’s Local Instruction
(defined) Variables Pointer!!!!
mystringhere
ALL OK SO FAR….
https://ctf101.org/binary-exploitation/buffer-overflow/
Stack Buffer Overflow (3)
Set name be 101 ‘A’’s (fyi, character A=0x41)
#include <stdio.h> So
name=“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int main() { AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int secret = 0xdeadbeef; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”
char name[100] = {0};
read(0, name, 0x100); STACK:
if (secret == 0x1337) { 0xffff006c: 0xf7f7f7f7 // Saved EIP
puts("Wow! Here's a secret."); 0xffff0068: 0xffff0100 // Saved EBP
} else { 0xffff0064: 0xdeadbe41 // secret
puts("I guess you're not cool ...
enough to see my secret"); 0xffff0004: 0x41414141
} ESP 0xffff0000: 0x41414141 // name
}
https://ctf101.org/binary-exploitation/buffer-overflow/
Stack Buffer Overflow (4)
Set name be 102 ‘A’’s (fyi, character A=0x41)
#include <stdio.h> So
name=“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int main() { AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int secret = 0xdeadbeef; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”
char name[100] = {0};
read(0, name, 0x100); STACK:
if (secret == 0x1337) { 0xffff006c: 0xf7f7f7f7 // Saved EIP
puts("Wow! Here's a secret."); 0xffff0068: 0xffff0100 // Saved EBP
} else { 0xffff0064: 0xdead4141 // secret
puts("I guess you're not cool ...
enough to see my secret"); 0xffff0004: 0x41414141
} ESP 0xffff0000: 0x41414141 // name
}
https://ctf101.org/binary-exploitation/buffer-overflow/
Stack Buffer Overflow (5)
Set name be 104 ‘A’’s (fyi, character A=0x41)
#include <stdio.h> So input for
name=“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int main() { AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int secret = 0xdeadbeef; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”
char name[100] = {0};
read(0, name, 0x100); STACK:
if (secret == 0x1337) { 0xffff006c: 0xf7f7f7f7 // Saved EIP
puts("Wow! Here's a secret."); 0xffff0068: 0xffff0100 // Saved EBP
} else { 0xffff0064: 0x41414141 // secret
puts("I guess you're not cool ...
enough to see my secret"); 0xffff0004: 0x41414141
} ESP 0xffff0000: 0x41414141 // name
}
https://ctf101.org/binary-exploitation/buffer-overflow/
Stack Buffer Overflow (6)
Set name be 108 ‘A’’s (fyi, character A=0x41)
#include <stdio.h> So input for
name=“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int main() { AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int secret = 0xdeadbeef; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
char name[100] = {0}; AA”
read(0, name, 0x100); STACK:
if (secret == 0x1337) { 0xffff006c: 0xf7f7f7f7 // Saved EIP
puts("Wow! Here's a secret."); 0xffff0068: 0x41414141 // Saved EBP
} else { 0xffff0064: 0x41414141 // secret
puts("I guess you're not cool ...
enough to see my secret"); 0xffff0004: 0x41414141
} ESP -> 0xffff0000: 0x41414141 // name
}
https://ctf101.org/binary-exploitation/buffer-overflow/
Stack Buffer Overflow (7) If I substitute the
last 4 A’s
Set name be 112 ‘A’’s (fyi, character A=0x41) (0x41414141) with
#include <stdio.h> So input for
name=“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA an address in
int main() { AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
memory, when the
int secret = 0xdeadbeef;
char name[100] = {0}; AAAAA” function gets to the
read(0, name, 0x100); STACK: end (return in
if (secret == 0x1337) { 0xffff006c: 0x41414141 // Saved EIP
puts("Wow! Here's a secret."); 0xffff0068: 0x41414141 // Saved EBP assembly) it will use
0xffff0064: 0x41414141 // secret
} else { the substitute in the
puts("I guess you're not cool ...
enough to see my secret"); ESP ->
0xffff0004: 0x41414141
0xffff0000: 0x41414141 // name
Stored EIP’s place to
}
} jump to the
substituted
AT THIS POINT YOU GET A SEGMENTATION ERROR! address!!!
https://ctf101.org/binary-exploitation/buffer-overflow/
Aleph One’s famous smashing the stack paper and
shellcode
• Key 1996 paper that shows exactly how to overflow the stack using C code,
and then how to insert shellcode to gain a prompt to execute arbitrary
code, including using NOPs
• Shellcode: machine language code, targeted to a particular processor and
OS, to perform a task…usually to gain a root or admin level command
shell, to execute whatever (arbitrary) code
From paper, p.18: char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\
x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\
xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh”
https://inst.eecs.berkeley.edu/~cs161/fa08/papers/stack_smashing.pdf
http://6.s081.scripts.mit.edu/sp18/x86-64-architecture-guide.html
https://www.intel.com/content/dam/develop/external/us/en/documents/introduction-to-x64-assembly-181178.pdf
https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture
https://wiki.osdev.org/Stack_Smashing_Protector https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
https://software.intel.com/en-us/articles/introduction-to-x64-assembly
https://security.stackexchange.com/questions/169291/x32-vs-x64-reverse-engineering-and-exploit-development
64-bit
stack Lower addresses Higher addresses
RIP
Function
1’s RBP
RSP
(defined) Variables
Function1’s Saved
Main’s Arguments
Main’s Saved RBP
Stack
Main’s Local
Function1’s
Function1
Growth
Main (‘0’)
CANARY
CANARY
(i.e.
RBP
added
function
s)
Low Memory The order can change, and there can be various locations in the address space High Memory
0x1111111111111111 for these components!!!! 0xfffffffffffffff0
CAN HAVE NX-BIT MARKING IN SOME AREAS
64-bit Register example … running GHHv6 code
────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x007fffffffdef8 → 0x007fffffffe248 → "/home/brycekalel1/GHHv6/ch11/vuln"
$rcx : 0x55
$rdx : 0x14
$rsp : 0x007fffffffdd68 → "faabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabra[...]"
$rbp : 0x6261616562616164 ("daabeaab"?)
$rsi : 0x00000000402010 → "Ultr4S3cr3tP4ssw0rd!"
$rdi : 0x007fffffffdcf0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
$rip : 0x00000000401301 → <auth+171> ret
$r8 : 0x0
$r9 : 0x007ffff7dc9740 → 0x007ffff7dc9740 → [loop detected]
$r10 : 0x007ffff7de6388 → 0x0010001a00001303
$r11 : 0x007ffff7f23490 → 0x41c45a7e01fa8348
$r12 : 0x0
$r13 : 0x007fffffffdf08 → 0x007fffffffe26a → "COLORFGBG=15;0"
$r14 : 0x00000000403e00 → 0x00000000401220 → <__do_global_dtors_aux+0> endbr64
$r15 : 0x007ffff7ffd020 → 0x007ffff7ffe2e0 → 0x0000000000000000
$eflags: [zero carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
64-bit Stack example…running
GHHv6 code
Only 48 bits of memory addresses are used of 64-bits
possible by windows/linux on x86_64 (i.e. x64)
stack ────
0x007fffffffdd68│+0x0000: "faabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabra[...]" ← $rsp
0x007fffffffdd70│+0x0008: "haabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabta[...]"
0x007fffffffdd78│+0x0010: "jaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabva[...]"
0x007fffffffdd80│+0x0018: "laabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxa[...]"
0x007fffffffdd88│+0x0020: "naaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab"
0x007fffffffdd90│+0x0028: "paabqaabraabsaabtaabuaabvaabwaabxaabyaab"
0x007fffffffdd98│+0x0030: "raabsaabtaabuaabvaabwaabxaabyaab"
0x007fffffffdda0│+0x0038: "taabuaabvaabwaabxaabyaab"
Relative
Virtual memory memory
address address
(absolute) In stack
frame
Stack Canaries 101
• Stack Canaries are “ known values that are placed between a buffer
and control data on the stack to monitor buffer overflows” via wiki.
Canaries are usually a character or field. Canaries, if altered, trigger a
handling routine to prevent overflow in secure code
• Terminator canaries: uses string terminators such as NULL, LF, CF, FF.
• Random canaries: randomly generated codes to hide canaries from
attackers
• Random XOR canaries: “random canaries that are XOR-scrambled
using all or part of the control data. In this way, once the canary or
the control data is clobbered, the canary value is wrong” BUFFER
VIOLATION!!!
Arguments (in
reverse order)
Main’s Saved
Main’s Local
https://en.wikipedia.org/wiki/Buffer_overflow_protection#A_canary_example
Saved RIP
CANARY
Variables
(defined)
(buffer)
Main’s
https://en.wikipedia.org/wiki/Buffer_overflow_protection
RBP
https://unix.stackexchange.com/questions/453749/what-sets-fs0x28-stack-canary
https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/
https://ctf101.org/binary-exploitation/stack-canaries/
Defeating Stack Canaries
Stored Stored
Buffer Canary
RBP RIP
• Essentially, sneak in shellcode execution without tripping the canary values in the stack that stop
return
• Trick: Find the canary values then use just enough bytes before the canary gets hit. Store canary value
then reinject it, before swapping out Stored IP.
1. Every thread for the same program has the same canary, so find the canary location, i.e. how many
bytes can we write before hitting canary location.
2. Find: Iterate values till we get smash error, though intercept error. Iteration can be using strings of
characters (e.g., set breakpoint that sets RSI before canary triggers)
3. Use pattern search to look for $rsi value…the offset here this is where the canary is located relative
to the string buffer
4. Make exploit do a try that adds $rsi offset + canary value+ paddingSI/ESI/RSI:
+ ROP chain in exploit
Source index for string operations
https://stackoverflow.com/questions/47047386/how-to-pass-memory-address-of-a-location-in-stack-from-assembly
https://reverseengineering.stackexchange.com/questions/28059/where-stack-canary-is-located
https://github.com/GrayHatHacking/GHHv6/blob/main/ch11/exploit2.py RIP= Relative Instruction Pointer
https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/ SFP= Saved Frame Pointer=saved RBP
https://ctf101.org/binary-exploitation/stack-canaries/ Text p.228-230
Stack Canary Payload Code
(example)
payload = b"A"*72 //all the ‘a’s
payload += leak_bytes(payload, "Canary") //canary bypass
payload += p64(0xBADC0FFEE0DDF00D) #SFP //more stuff to get to
ROP pointers in stored RIP
payload += (shellcode or pointers to ROP)
Stack Smashing Protector (SSP) (a type of Canary)
• Stack Smashing Protector (SSP): Compiler option to detect stack overrun
• Uses libssp library https://github.com/gcc-mirror/gcc/tree/master/libssp
https://en.wikipedia.org/wiki/Exec_Shield
https://en.wikipedia.org/wiki/Executable_space_protection
https://www.exploit-db.com/docs/english/16030-non-executable-stack-arm-exploitation.pdf
https://en.wikipedia.org/wiki/NX_bit
ROP (Return Oriented Programming)
• Basic Concept: Return-oriented programming uses control of the call stack to
indirectly execute machine instructions or groups of machine instructions
(gadgets) immediately prior to the return instruction (ret) in subroutines
(functions) within the existing program code (loosely via Wiki)
• Some gadgets use JMP or CALL
• Return-into-library technique uses libc code already in memory in lieu of
https://ctf101.org/binary-exploitation/return-oriented-programming/
custom shellcode
• Borrowed code chunks: attack that uses chunks of library functions, instead of
https://www.ired.team/offensive
entire functions themselves, to exploit buffer overrun -security/code-injection-process-
injection/binary-exploitation/rop
• ROP Chain: Sequence of ROP
https://github.com/JonathanSalwan/ROPgadget
exploits to execute code
https://pypi.org/project/ROPGadget/
-chaining-return-oriented-progra
mming
ROP Example using libc: https://www.youtube.com/watch?v=cZKV_LZOPug
https://en.wikipedia.org/wiki/Return_statement https://www.cs.cmu.edu/~rdriley/487/labs/lab03.html
https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-67/index.html
https://montcs.bloomu.edu/Information/LowLevel/Assembly/assembly-tutorial.html
https://resources.infosecinstitute.com/topic/return-oriented-programming-rop-attacks/
https://en.wikipedia.org/wiki/Return-oriented_programming
ROP vs JOP vs SROP
• ROP(Return Oriented Programming): Executes code
ALREADY PRESENT in executable memory (at gadgets)
• Works in the presence of memory protections!
• JOP (Jump Oriented Programming): Inserts a pointer into
executable memory to code that is outside the stream of
execution…older hack method
• SROP: Sigreturn Orientated programming (SROP): exploit
that allows an attacker to control the entire state of the CPU
and allows an attacker to execute code in presence of security
measures such as non-executable memory and code signing.
https://en.wikipedia.org/wiki/Sigreturn-oriented_programming
https://en.wikipedia.org/wiki/Return-oriented_programming https://man7.org/linux/man-pages/man2/sigreturn.2.html
https://security.stackexchange.com/questions/201196/concept-of-jump-oriented-programming-jop
https://developer.arm.com/documentation/102433/0100/Jump-oriented-programming
https://resources.infosecinstitute.com/topic/return-oriented-programming-rop-attacks/
Ropper (.py, and Kali command)
• Display information about binary files in different file
formats, search for gadgets to build ROP(Return
Oriented Programming ) chains
• In short, disassembles an executable and can be used
to search for gadgets to find a spot to remote execute
code in (normal) executable libraries
• Note: install the Capstone engine for disassembly,
along with pyvex first
https://www.ibm.com/docs/en/zos/2.3.0?topic=functions-mprotect-set-protection-memory-mapping
http://www.capstone-engine.or
g/ https://gitlab.com/kalilinux/packages/ropper
https://scoding.de/ropper/
https://www.kali.org/tools/ropper/ https://github.com/sashs/Ropper https://github.com/angr/pyvex Text p. 63-4
One_gadget and execve
• Gadgets are spots that can be used to insert code and open a shell to
remotely execute code, they end in ‘RETN’.
• One_gadget is a tool to jump execution to a particular spot, especially for
Remote Code Execution (RCE). i.e. execve(“/bin/sh”, NULL, NULL);
• Execve = execute program in shell
• Running One_Gadet readies the system to open the shell by finding spots in
the code (gadets) in libc.
EXAMPLES: https://dzone.com/articles/a-ctf-example-shows-you-the-easy-and-powerful-one
https://github.com/david942j/one_gadget https://pypi.org/project/one-gadget/
https://www.ibm.com/docs/en/i/7.3?topic=functions-scanf-read-data
https://www.unix.com/man-page/osx/1/vmmap/
https://linux.die.net/man/2/execve Text p. 62-3
Ropper
Ropper looks for gadgets in a
redux target OS or program instance,
└─$ ropper --file ~/GHHv6/ch12/vmlinux --console
[INFO] Load gadgets for section: LOAD in this case the VM kernel
[LOAD] loading... 100% version of Linux (vmlinux an
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100% ELF executable which it
[LOAD] removing double gadgets... 100% disassembles)
(vmlinux/ELF/x86_64)>
(vmlinux/ELF/x86_64)> search pop rdi
[INFO] Searching for gadgets: pop rdi
[INFO] File: ~/GHHv6/ch12/vmlinux
0xffffffff810baf61: pop rdi; adc byte ptr [rax - 0x75], cl; cmp byte ptr [rbp - 0x75], cl; sbb byte ptr [rax + 0x39], cl; ret;
0xffffffff818812f7: pop rdi; adc byte ptr [rdx + 0x64541568], dl; ret;
(LOTS MORE LINES)
0xffffffff818af975: pop rdi; adc dword ptr [rbp + 0x62], esp; mov bl, 0x6b; adc dl, ch; call qword ptr [rbp + 0x64f73a70]; ret;
(LOTS MORE LINES)
0xffffffff811ad2ec: pop rdi; ret; Pointer to add to ROP chain;
(lots more lines) Add together to make
(vmlinux/ELF/x86_64)> search (whatever gadget you want) shellcode (Exploit)
Bypassing non-executable (NX) stack with
ROP
Run target
Locate base Duplicate Build /bin/sh
program and
address of libc or descriptor to (i.e. the shell) using
open new Use access
similar for target STDIN/STDOUT ROP tools using base
window to run
program /STDERR address
exploit
https://www.kali.org/tools/
https://developer.apple.com/library/archive/documentation/Performance/
Conceptual/ManagingMemory/Articles/VMPages.html
https://en.wikipedia.org/wiki/Glibc
https://github.com/GrayHatHacking/GHHv6/blob/main/ch11/exploit1.py
https://docs.pwntools.com/en/stable/rop/rop.html
https://linux.die.net/man/8/execstack https://github.com/Wenzel/linux-sysinternals
ROP Example using libc: https://www.youtube.com/watch?v=cZKV_LZOPug Text p. 221 to 225
Bypass NX with ROP Example
• -z execstack:
$ gcc vuln.c -o vuln_nx|readelf -l vuln_nx|grep -A1 GNU_STACK
disables non-
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 executable stack
0x0000000000000000 0x0000000000000000 RW 0x10 protection…
vuln.c: In function ‘auth’:
vuln.c:24:5: warning: ‘read’ writing 512 bytes into a region of size 64 overflows the
therefore allowing
destination [-Wstringop-overflow=] stack elements to be
24 | read(connfd, buf, 512); shellcode
| ^~~~~~~~~~~~~~~~~~~~~~
(LOTS OF WARNINGS) • In top compile ELF is
┌──(brycekalel1 ㉿ kali1)-[~/GHHv6/ch11] set to Read and
└─$ gcc -z execstack vuln.c -o vuln_nx && readelf -l vuln_nx|grep -A1 GNU_STACK
vuln.c: In function ‘auth’:
Write (RW) vs. RW
vuln.c:24:5: warning: ‘read’ writing 512 bytes into a region of size 64 overflows the and Execute in
destination [-Wstringop-overflow=] bottom (RWE)
(lots of warnings)
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RWE 0x10
run using GHHv6 code…
Bypass NX with ROP Example
└─$ gdb ./vuln -q -ex "set follow-fork-mode child" -ex "r" • Running vuln like
GEF for linux ready, type `gef' to start, `gef config' to configure
so puts it in a
90 commands loaded and 5 functions added for GDB 12.1 in 0.00ms using Python engine
3.11
thread in
Reading symbols from ./vuln... background, on
(No debugging symbols found in ./vuln) local port 4446
Starting program: ~/GHHv6/ch11/vuln (127.0.0.1 = local
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: to box)
'system-supplied DSO at 0x7ffff7fc9000'
[Thread debugging using libthread_db enabled] • Runs until
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". interrupted by ^C
Listening on 127.0.0.1:4446 or killed.
^C
Program received signal SIGINT, Interrupt.
• Setting vuln up so
0x00007ffff7ed6460 in __libc_accept (fd=0x3, addr=..., len=0x7fffffffddac) at it can be hacked
../sysdeps/unix/sysv/linux/accept.c:26 by another
26 ../sysdeps/unix/sysv/linux/accept.c: No such file or directory terminal
window…
run using GHHv6 code…
Bypass NX with ROP Example
.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────── registers ────
$rax : 0xfffffffffffffe00
$rbx : 0x007fffffffdef8 → 0x007fffffffe248 → "/home/brycekalel1/GHHv6/ch11/vuln"
$rsp : 0x007fffffffdd68 → 0x000000004014dc → <main+474> mov DWORD PTR [rbp-0x8], eax
$rbp : 0x007fffffffdde0 → 0x0000000000000001
$rsi : 0x007fffffffddb0 → 0x0000000000000000
$rdi : 0x3
$rip : 0x007ffff7ed6460 → 0x5877fffff0003d48 ("H="?)
....
───────────── stack ────
0x007fffffffdd68│+0x0000: 0x000000004014dc → <main+474> mov DWORD PTR [rbp-0x8], eax ← $rsp
0x007fffffffdd70│+0x0008: 0x0000000000000000
….
https://www.man7.org/linux/man-pages/man2/mmap.2.html
https://www.fortinet.com/blog/threat-research/tutorial-of-arm-stack-overflow-exploit-defeating-aslr-with-ret2plt
https://github.com/GrayHatHacking/GHHv6/blob/main/ch11/exploit3-v2.py
https://github.com/GrayHatHacking/GHHv6/blob/main/ch11/exploit3.py See also Grey Hat Hacking p.228-230
PIE (Position Independent Executables)/ PIC
(Position-Independent Code)
• Code that operates properly regardless of where it is in memory
• “PIE binary and all of its dependencies are loaded into random locations
within virtual memory each time the application is executed.” (via
Redhat) to prevent exploits
• Addresses in code complied as PIE are RELATIVE versus absolute in
dynamic compiled code
• Helps stop ROP attacks…hard to figure out where to return and put code
• gcc -fstack-protector…
• In short, every time I run code, I have to re-find the gadgets….
https://inst.eecs.berkeley.edu/~cs164/fa11/ia32-refs/ia32-chapter-seven.pdf
https://en.wikipedia.org/wiki/Position-independent_code
https://www.redhat.com/en/blog/position-independent-executables-pie
https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld
PIE bypass with Information Leak
• PIE bypass works by finding the RELATIVE values of key pointers, then
exploit the calculated locations given initial base values
•Via Wiki x86:
•BP/EBP/RBP: Stack base pointer for holding the address of the current stack frame.
•IP/EIP/RIP: Instruction pointer. Holds the program counter, the address of next instruction
Get address of
stack canary, Find program’s
Assign result (program
Saved Frame base by subtracting
base address) to
Pointer (SFP) , RIP (leaked) RIP from
ELF(base) address
(64-bit program Distance to
(relative addresses)
counter) Program Base
(leak_base)
https://stackoverflow.com/questions/45112182/why-is-saved-frame-pointer-present-in-a-stack-frame
https://stackoverflow.com/questions/27429026/understanding-how-eip-rip-register-works
https://github.com/GrayHatHacking/GHHv6/blob/main/ch11/exploit3.py
https://github.com/GrayHatHacking/GHHv6/blob/main/ch11/exploit4.py
see also Grey Hat Hacking p.230-232
https://github.com/ir0nstone/pwn-notes/blob/master/types/stack/pie/pie-bypass.md
Stack Overflow from User--Ring 3…in 1 slide PWNTOOLS
Compiler
Vulnerable Vulnerability that Buffer overflow uses Buffer overflows used
warnings
program is allows buffer overflow NOPs and crashes to locate stored
ignored,
written, discovered, likely a with Segmentation instruction pointer, an
program is
compiled CWE/CVE Fault offset from buffer
fielded
https://en.wikipedia.org/wiki/X86_virtualization
https://en.wikipedia.org/wiki/X86 See also table 2-4 in text
Threat Databases and Uses
Source Time Frame Tools Notes
• SEI CERT Coding BEFORE USE: • Clang, other modern • Standards from
Standards • During coding in development IEEE/IEC/ISO informed
for C, C++, Java, development environment environments (Eclipse, secure coding practices and
Perl, and Android examples in the SEI CERT
• Part of DevSecOps via Visual), and static Coding Standards; secure
• IEEE standards static analysis analysis tools coding should part of an
(e.g., • Manual review overall code quality process
ISO/IEC 9899:2011) • Many map to CWEs
+
• MITRE CWE BEFORE USE: • Static analysis tools • Weaknesses can lead to
• During coding in development vulnerabilities (CWEs can be
• OWASP Top 10 environment
• Manual review mapped to CVEs if a vulnerability
• CWE/SANS Top 25 • Part of DevSecOps via static is found for a weakness)
analysis • Top lists are the most likely
IN UPDATE/PATCHING weaknesses for exploit
• MITRE CVE, which Before use in field: • Static and dynamic analysis • Vulnerabilities can be exploited
• To patch in-use software and tools by various hacking tools
feeds ATT&CK systems • Manual review • NVD maps CVEs with known
Techniques • As checks as part of DevSecOps • Custom comparison: release to exploits; the worst vulnerabilities
• MITRE CAPEC process vulnerability become NSA Top 25 risks
• NIST NVD • When upgrades and revisions are • ATT&CK focuses on system • CVEs can have exploitation
required to fix known vulnerabilities level, CAPEC on application techniques listed in ATT&CK and
• NSA Top 25 in fielded code and systems. and software level in CAPEC
Arguments in Registers: 64-bit uses
registers to pass arguments into a
function….
• RDI gets arg 1, RSI gets arg 32-bit: 64-bit:
2, RDX gets arg 3, RCX gets Function: Function:
arg4, R8 gets arg 5, R9 pushl %ebp pushq %rbp
gets arg 6 movl %esp, %ebp movq %rsp, %rbp
• Arguments 7 and above
are pushed on to the Main: Main:
stack. movl (%eax), %eax movq (%rax), %rax
• (in 32-bit the args are pushl %edx movq %rdx, %rsi
pushed onto the stack in pushl %eax movq %rax, %rdi
reverse order) call greeting call greeting
https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/linux-x64-calling-convention-stack-frame