SEH and the Stack
• Proj ED 319: SEH-Based Stack Overflow
Exploit


• Send AAAAAA...AAABCDEXXXXXX...XXX
• BCDE writes into the SEH


• In "Stack of thread 000022F4"
• Start of string in stack


• AAAAA...
• End of stack
CNIT 127: Exploit Development




Ch 18: Source Code Auditing
Updated 5-17-22
Why Audit Source Code?
• Best way to discover vulnerabilities


• Can be done with just source code and
grep


• Specialized tools make it much easier
Cscope
• A source code browsing tool


• Useful for large code trees,
such as the whole Linux
kernel


• Many useful search
functions


• Cbrowser: GUI front-end


• Links Ch 18a, 18b
Ctags
• Indexes source code


• Creates a tag file with
locations for language
tags in files scanned


• Works in many
languages, including C
and C++


– Link Ch 18c
Text Editor
• Vim and Emacs have features that make
writing and searching though large
amounts of code easy


• Bracket-matching: find matching ([{
Automated Source Code
Analysis Tools
• Badly out-of date (last revised in 2007)


• Output a little hard to understand


– Links Ch 18d, 18e
• Many available, specialized by language


• Link Ch 18f
• Easy to use


• Finds about half the obvious
vulnerabilities we've exploited
cppcheck
Heap Overflow
Finds Some Vulnerabilities
• But not the overflow!
Format String Vulnerability
• It doesn't find
it at all!
Flawfinder
• Much better


• In Kali


• apt-get update


• apt-get install flawfinder
Methodology
Top-Down (Specific) Approach
• Search for specific lines of vulnerable
code, such as format string errors


• Auditor doesn't have to understand
application in depth


• Misses vulnerabilities that span more than
one part of the code
Bottom-Up Approach
• Auditor reads large portion of code


• Starting at main()


• Time-consuming but can reveal subtle
bugs
Selective Approach
• Most auditors use this approach


• Locate code that can be reached with
attacker-defined input


• Focus energy on that code


• Learn the purpose of that code thoroughly
Vulnerability Classes
Generic Logic Errors
• Requires good understanding of an
application


– And internal structures and classes


• Example: wildcard certificates


– Pascal-based CA will sell a certificate for


*0.evil.com


– C-based browser will see it as *, a wildcard


– It will match any domain


• Link Ch 18g
(Almost) Extinct Bug Classes
• Unbounded memory copy functions


– strcpy(), sprintf(), strcat(), gets(), …


• Hunted nearly to extinction
Root Cause (from Microsoft)
Bypassing ASLR & DEP
Format Strings
• Easy to find with a code audit


– Although cppcheck failed


• Often found in logging code


• Vulnerable only if attacker controls the
format string
Generic Incorrect Bounds-Checking
• Coder attempts to check limits, but does
it incorrectly


• Example: Snort RPC Processor (2003)


– Processes a series of RPC fragments


– Checks each fragment to make sure it's not
larger than the buffer


– But it should check the total size of all
combined fragments
Snort RPC Processor (2003)
Loop Constructs
• Coders often use intricate loops, and loops
within loops


• Complex interactions can lead to insecurities


• Led to a buffer overflow in Sendmail


• Link Ch 18h
Demonstration Exploit
• Link Ch 18i
Off-by-One Vulnerabilities
• Often caused by improper


null-termination of strings


• Frequently found in loops or introduced
by common string functions


• Can lead to arbitrary code execution
Example from Apache
• When both if statements are true


– Space allocated is one byte too small


– memcpy will write one null out of bounds
OpenBSD ftp Daemon
• If last character is a quote, it can be
written past the bounds of the input
buffer
strncat()
• Strncat always null-terminates its output
string


• Will write a null byte out of bounds unless
the third argument is equal to the
remaining space in the buffer minus one
byte
Non-Null Termination Issues
• If a string is not terminated with a null


– Memory after the string is interpreted as part
of the string


– May increase length of string


– String writes may corrupt memory outside the
string buffer


– Can lead to arbitrary code execution
strncpy()
• If there's not enough space in the
destination buffer


– strncpy() won't null-terminate the string it
writes
strncpy() Example
– First strncpy won't null-terminate not_term_buf


– Second strcpy is unsafe, even though both
buffers are the same size


– Fix it by adding this line of code after the first
strcpy
Skipping Past Null-Termination
• String-processing loops that process more
than one character at a time


– Or where assumptions about string length are
made


• Can make it possible to write past end of
a buffer


– Possible arbitrary code execution
Example from Apache
• This line is intended to skip past :// in a
URL


– cp += 3
But Not All Schemes End in ://
• If the URI is ldap:a


– The null byte is skipped
Signed Comparison Vulnerabilities
• Coder attempts to check input length


• But uses a signed integer variable


• Or two different integer types or sizes


– C sometimes converts them both to signed
integers before comparing them


• Following example from Apache


– Led to code execution on Windows and BSD
Unix
Example from Apache
• bufsize is a signed integer


– Remaining space in the buffer


• r->remaining is signed


– Chunk size from the request


• len_to_read should be the smaller of the two


– Negative chunk size tricks the code into performing a
large memcpy later, because it's cast to
unsigned
Integer Conversions
• Link Ch 18l
• A hashed password can begin with 0e and
contain only digits (very rare)


– Like 0e12353589661821035685


• PHP reads that as scientific notation


– 0^123…


– Always zero (link Ch 18j)
Double Free Vulnerabilities
• Freeing the same memory chunk twice


• Can lead to memory corruption and arbitrary
code execution


• Most common when heap buffers are stored
in pointers with global scope


• Good practice: when a global pointer is
freed, set it to Null to prevent it being re-
used


• Prevents dangling pointers
Out-of-Scope Memory Usage
Vulnerabilities
• Use of a memory region
before or after it is valid


• Also called "Dangling
Pointer"


– Image from Wikipedia


• Link Ch 18k)
Uninitialized Variable Usage
• Static memory in the .data or .bss
sections of an executable are initialized
to null on program startup


• But memory on the stack or heap is not


• Uninitialized variables will contain data
from previous function calls


• Argument data, saved registers, or local
variables from previous function calls
Uninitialized Variable Usage
• Rare, because they can lead to immediate
program crashes


• So they get fixed


• Look for them in code that is rarely used


• Such as handlers for uncommon errors


• Compilers attempt to prevent these errors
Example
• If data is null


– test is never assigned any value


– But test is still freed
Exploitation
• The "uninitialized" data in test is not
random


• It comes from previous variables and
function calls


• It may be controlled by the attacker


• So the free() leads to a controllable
memory write


– Arbitrary code execution
Use After Free Vulnerabilities
• Heap buffers are temporary


– Released with free()


• But a program may use a pointer after
free()


– If more than one variable points to the same
object


• Allows an attacker to write to RAM


– Possible arbitrary code execution
Multithreaded Issues and


Re-Entrant Safe Code
• A global variable is used by more than one
thread, without proper locking


– A variable might be changed unexpectedly by
another thread


• Such issues won't appear until the server
is under heavy load


– May remain as intermittent software bugs
that are never verified
Ch 18: Source Code Auditing

Ch 18: Source Code Auditing

  • 1.
  • 2.
    • Proj ED319: SEH-Based Stack Overflow Exploit • Send AAAAAA...AAABCDEXXXXXX...XXX
  • 3.
    • BCDE writesinto the SEH • In "Stack of thread 000022F4"
  • 4.
    • Start ofstring in stack • AAAAA...
  • 5.
  • 6.
    CNIT 127: ExploitDevelopment 
 
 Ch 18: Source Code Auditing Updated 5-17-22
  • 7.
    Why Audit SourceCode? • Best way to discover vulnerabilities • Can be done with just source code and grep • Specialized tools make it much easier
  • 8.
    Cscope • A sourcecode browsing tool • Useful for large code trees, such as the whole Linux kernel • Many useful search functions • Cbrowser: GUI front-end • Links Ch 18a, 18b
  • 9.
    Ctags • Indexes sourcecode • Creates a tag file with locations for language tags in files scanned • Works in many languages, including C and C++ – Link Ch 18c
  • 10.
    Text Editor • Vimand Emacs have features that make writing and searching though large amounts of code easy • Bracket-matching: find matching ([{
  • 11.
  • 12.
    • Badly out-ofdate (last revised in 2007) • Output a little hard to understand – Links Ch 18d, 18e
  • 13.
    • Many available,specialized by language • Link Ch 18f
  • 14.
    • Easy touse • Finds about half the obvious vulnerabilities we've exploited cppcheck
  • 15.
  • 16.
    Finds Some Vulnerabilities •But not the overflow!
  • 17.
    Format String Vulnerability •It doesn't find it at all!
  • 18.
    Flawfinder • Much better •In Kali • apt-get update • apt-get install flawfinder
  • 19.
  • 20.
    Top-Down (Specific) Approach •Search for specific lines of vulnerable code, such as format string errors • Auditor doesn't have to understand application in depth • Misses vulnerabilities that span more than one part of the code
  • 21.
    Bottom-Up Approach • Auditorreads large portion of code • Starting at main() • Time-consuming but can reveal subtle bugs
  • 22.
    Selective Approach • Mostauditors use this approach • Locate code that can be reached with attacker-defined input • Focus energy on that code • Learn the purpose of that code thoroughly
  • 23.
  • 24.
    Generic Logic Errors •Requires good understanding of an application – And internal structures and classes • Example: wildcard certificates – Pascal-based CA will sell a certificate for 
 *0.evil.com – C-based browser will see it as *, a wildcard – It will match any domain • Link Ch 18g
  • 25.
    (Almost) Extinct BugClasses • Unbounded memory copy functions – strcpy(), sprintf(), strcat(), gets(), … • Hunted nearly to extinction
  • 26.
    Root Cause (fromMicrosoft)
  • 27.
  • 28.
    Format Strings • Easyto find with a code audit – Although cppcheck failed • Often found in logging code • Vulnerable only if attacker controls the format string
  • 29.
    Generic Incorrect Bounds-Checking •Coder attempts to check limits, but does it incorrectly • Example: Snort RPC Processor (2003) – Processes a series of RPC fragments – Checks each fragment to make sure it's not larger than the buffer – But it should check the total size of all combined fragments
  • 30.
  • 31.
    Loop Constructs • Codersoften use intricate loops, and loops within loops • Complex interactions can lead to insecurities • Led to a buffer overflow in Sendmail • Link Ch 18h
  • 32.
  • 33.
    Off-by-One Vulnerabilities • Oftencaused by improper 
 null-termination of strings • Frequently found in loops or introduced by common string functions • Can lead to arbitrary code execution
  • 34.
    Example from Apache •When both if statements are true – Space allocated is one byte too small – memcpy will write one null out of bounds
  • 35.
    OpenBSD ftp Daemon •If last character is a quote, it can be written past the bounds of the input buffer
  • 36.
    strncat() • Strncat alwaysnull-terminates its output string • Will write a null byte out of bounds unless the third argument is equal to the remaining space in the buffer minus one byte
  • 37.
    Non-Null Termination Issues •If a string is not terminated with a null – Memory after the string is interpreted as part of the string – May increase length of string – String writes may corrupt memory outside the string buffer – Can lead to arbitrary code execution
  • 38.
    strncpy() • If there'snot enough space in the destination buffer – strncpy() won't null-terminate the string it writes
  • 39.
    strncpy() Example – Firststrncpy won't null-terminate not_term_buf – Second strcpy is unsafe, even though both buffers are the same size – Fix it by adding this line of code after the first strcpy
  • 40.
    Skipping Past Null-Termination •String-processing loops that process more than one character at a time – Or where assumptions about string length are made • Can make it possible to write past end of a buffer – Possible arbitrary code execution
  • 41.
    Example from Apache •This line is intended to skip past :// in a URL – cp += 3
  • 42.
    But Not AllSchemes End in :// • If the URI is ldap:a – The null byte is skipped
  • 43.
    Signed Comparison Vulnerabilities •Coder attempts to check input length • But uses a signed integer variable • Or two different integer types or sizes – C sometimes converts them both to signed integers before comparing them • Following example from Apache – Led to code execution on Windows and BSD Unix
  • 44.
    Example from Apache •bufsize is a signed integer – Remaining space in the buffer • r->remaining is signed – Chunk size from the request • len_to_read should be the smaller of the two – Negative chunk size tricks the code into performing a large memcpy later, because it's cast to unsigned
  • 45.
  • 46.
  • 47.
    • A hashedpassword can begin with 0e and contain only digits (very rare) – Like 0e12353589661821035685 • PHP reads that as scientific notation – 0^123… – Always zero (link Ch 18j)
  • 48.
    Double Free Vulnerabilities •Freeing the same memory chunk twice • Can lead to memory corruption and arbitrary code execution • Most common when heap buffers are stored in pointers with global scope • Good practice: when a global pointer is freed, set it to Null to prevent it being re- used • Prevents dangling pointers
  • 49.
    Out-of-Scope Memory Usage Vulnerabilities •Use of a memory region before or after it is valid • Also called "Dangling Pointer" – Image from Wikipedia • Link Ch 18k)
  • 50.
    Uninitialized Variable Usage •Static memory in the .data or .bss sections of an executable are initialized to null on program startup • But memory on the stack or heap is not • Uninitialized variables will contain data from previous function calls • Argument data, saved registers, or local variables from previous function calls
  • 51.
    Uninitialized Variable Usage •Rare, because they can lead to immediate program crashes • So they get fixed • Look for them in code that is rarely used • Such as handlers for uncommon errors • Compilers attempt to prevent these errors
  • 52.
    Example • If datais null – test is never assigned any value – But test is still freed
  • 53.
    Exploitation • The "uninitialized"data in test is not random • It comes from previous variables and function calls • It may be controlled by the attacker • So the free() leads to a controllable memory write – Arbitrary code execution
  • 54.
    Use After FreeVulnerabilities • Heap buffers are temporary – Released with free() • But a program may use a pointer after free() – If more than one variable points to the same object • Allows an attacker to write to RAM – Possible arbitrary code execution
  • 55.
    Multithreaded Issues and 
 Re-EntrantSafe Code • A global variable is used by more than one thread, without proper locking – A variable might be changed unexpectedly by another thread • Such issues won't appear until the server is under heavy load – May remain as intermittent software bugs that are never verified