Pwn
I placed pwn in with programming, because it relies heavily on programming concepts and knowledge

ELF Analysis

Take a quick look at the file before jumping into analysis
1
readelf -h ./binary # Analyze the ELF headers
2
readelf -sW ./binary | grep FUNC # List all functions in binary
3
objdump -M intel -d ./binary | awk -v RS= '/^[[:xdigit:]]+ <main>/' # Display disassembly for main() only
4
ltrace ./binary # Watch library calls as program executes
5
strings ./binary # The classic
6
printf $(python -c 'print("A"*15)') | ./int-overflow # Easy way to change amount of bytes passed to program
7
echo -n -e ' \x41\x41\x41\x41\x41\x41\x42' > bytes # Put bytes directly into a file
8
(cat ./exploit; cat) | ./program # Pass the exploit to the program, leaves stdin open
9
./checksec.sh ./program # Runs the checksec.sh script to determine binary mitigations in place
10
​
11
# Use MSF to create the pattern and identify offsets
12
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200
13
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 200 -q 6641396541386541
14
​
15
# Similar to MSF, PEDA can support patterns too. Inside GDB
16
pattern_create 700
17
pattern_offset $ASCII_VALS
18
​
19
# Disable ASLR
20
echo 0 > /proc/sys/kernel/randomize_va_space
21
# Check if ASLR is enabled or not
22
cat /proc/sys/kernel/randomize_va_space
23
​
24
# Compile a program to be vulnerable
25
gcc -no-pie -m32 -fno-stack-protector -z execstack binary.c -o binary
26
​
27
# Strip internal symbols from a program
28
strip binary
29
​
30
# GDB-PEDA check security of a binary
31
checksec
Copied!

GDB

Program used to help debug activities as they occur. Use set disassembly-flavor intel to get rid of nasty AT&T syntax. Can analyze core dumps to help identify vulnerable locations in memory for binaries as well.
Generally, we want to set a break AFTER a vulnerable function to see what the stack looks like.
Change the libc used in GDB with the command
1
# Execute inside GDB to get correct libc offsets
2
set exec-wrapper env 'LD_PRELOAD=/home/chris/libc.so.6'
3
​
4
# Execute outside of GDB with command:
5
LD_PRELOAD=./libc.so.6 | python -c 'print("1\n"+"A"*40)' | ./vuln_elf
6
​
7
# Find /bin/sh in memory while using GDB
8
find "/bin/sh"
9
​
10
# Find "system" function in memory (has to be started first to link libs)
11
p system
12
​
13
# View env vars at a break after starting execution
14
x/100s **(char***)&environ
15
​
16
# Start a program with values passed as input (not argv)
17
run < <(python -c 'print("A"*64 + "BBBB")')
Copied!
Command
Explanation
disass main
disassemble the main function.
break main
break *main+53
break *0x8040564
Break on the main() function, or an offset, or a specific memory address. Specific addresses require a *
print $eip
Print the contents of a register, variables, or even a memory address
x/20i
x/5i *0x8040564 x/20wx $esp
x/s *0x8040564
Examine 20 Instructions from current EIP
Examine 5 instructions from a specific address Examine 20 DWORDs from the stack pointer
Examine ASCII strings in an address
info
info registers
info function
Lots of interesting info about the current program
Prints all register contents
Prints out all functions
list
Show the source code (if available)
continue
Continues execution after a breakpoint is hit
si
ni
Step Instruction (into library calls!)
Next Instruction (skips library calls!)
bt
Backtrace, shows return pointers on the stack. SUPER useful to identify the call chain to gather return pointers
info breakpoints
del breakpoints
del break 3
Show all breakpoints
Delete all breakpoints
Delete breakpoint 3
1
# Read the disassembly from main()
2
disas main
3
​
4
# Print the value of hexadecimal to ASCII
5
print (char []) 0x24424142
6
​
7
# Pass Args to a program when starting in GDB
8
run `python -c 'print("A"*50)'`
9
​
10
# Pass input to a program when starting in GDB
11
run < <(python -c 'print("A"*50)')
12
​
13
# Enable core dumps
14
ulimit -c unlimited
15
sudo chmod -s ./binary
16
​
17
# With core dumps enabled, crash the binary and load the dump
18
gdb --core=core
Copied!

Some Vulnerable Functions

If we find a program which calls some of these functions, we may be able to take control with a buffer overflow based attack.
calloc, malloc, realloc, fscanf, gets, scanf, sprintf, sscanf, strcat, strcpy, strncat, strncmp, strncpy, memchr, memcmp, memcpy, memmove, memset, scanf, gets, fwscan, sscanf

Stripped Binaries

Stripped programs have their symbol tables removed, which makes identifying user created functions difficult to find compared with non-stripped binaries. If we search for functions, we will only see functions called in linked libraries.
What we can do, is set a break on some of the functions that are called. Once that break is hit, we can inspect the backtrace with bt to identify where the return pointer will hit a call.
1
# Inspect in GDB for functions
2
i fun
3
​
4
# Set break on a linked function
5
break gets
6
​
7
# View backtrace on break to see where entry point into function
8
bt
Copied!

ret2libc

This is a technique where we use stack overflows to reach linked functions in libc and gain execution.
We can find locations and offsets in linked libraries with this neat command below. Taken from https://blog.artis3nal.com/2020-08-14-htb-october-msf/​
1
# strings to find offset for /bin/sh, this will be 0x00131a7a
2
strings -atx /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
3
131a7a /bin/sh
Copied!

Stack Canaries

In the case of a terminator canary, keep in mind that many functions such as gets() will place a null byte at the end for us! If we overrun the buffer, we can strategically reconstruct a canary value.

ASLR

ASLR makes exploitation more difficult, however there are some nifty tricks we can use to still get around it. Trampoline calls can be used to call the stack, we just need to search for opcodes which are either a JMP ESP or CALL ESP. By calling the stack pointer, we can execute our data on the stack (as long as DEP is not present!!).
PEDA makes this easy with the command jmpcall esp.
Additionally, we can check if the libraries loaded by a program are staticly loaded or not. This can be done using the ldd program.

Pwntools

1
>>> import pwn
2
>>> pwn.p64(0x7fffffffe380)
3
b'\x80\xe3\xff\xff\xff\x7f\x00\x00'
4
>>> pwn.p32(0x0804853b)
5
b';\x85\x04\x08'
Copied!

Create Shellcode

One of the easiest ways to create shellcode is using msfvenom. We can always list out the options with --list-options as a switch.