auditing closed-source applications using reverse engineering in a security context speech outline:...

33
Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1. Different Approaches to auditing binaries 2. How to spot common programming mistakes in the binary 3. Writing a small script that automates the task of searching for suspicious coding constructs 4. Example of using this script to find a buffer overflow in a major web server application. © HalVar Flake

Upload: wilfred-johnston

Post on 23-Dec-2015

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Auditing Closed-Source ApplicationsUsing reverse engineering in a security context

Speech Outline:

1. Different Approaches to auditing binaries2. How to spot common programming mistakes in the

binary3. Writing a small script that automates the task of

searching for suspicious coding constructs4. Example of using this script to find a buffer

overflow in a major web server application.

© HalVar Flake

Page 2: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

White Hat vs Black Hat auditingWhite Hat Auditing:

Black Hat Auditing

• All code has to be audited• Continues after a vulnerability has been found• Has to be repeated upon every upgrade

Trying to find a single vulnerable condition throughwhich the security of an application can be compromised

• Only audits suspicious parts of the code• Only one vulnerable condition is needed• Will only be repeated if all old problems have been fixed.

Trying to ensure application security by auditing every line of code in agiven application, hopefully fixing all problems and leaving the programin a secure and stable condition

© HalVar Flake

Page 3: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Closed-Source Auditing Approaches1. Stress Testing with Junk Input

Long strings of data are more or less randomly generated and sent to the application,usually trying to overflow every single string that gets parsed by a certain protocol.

Pros:

• Stress testing tools are re-usable for a given protocol• Will work automatically with little to no supervision• Do not require specialized personnel to use

Cons:

• The analyzed protocol needs to be known in advance• Complex problems involving several conditions at once

will be missed• Undocumented options and backdoors will be missed

© HalVar Flake

Page 4: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Closed-Source Auditing Approaches2. Manual Reverse Engineering

A reverse engineer carefully reads the disassembly of the program, tediously re-constructing the program flow and spotting programming errors. This was the approach Joey__ demonstrated at BlackHat Singapore.

Pros:

• Even the most complex issues can be spotted

Cons:

• The process involved is incredibly time-consuming• A highly skilled and specialized auditor is needed• The danger is inherent that an auditor will burn out

and thus miss obvious problems

© HalVar Flake

Page 5: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Closed-Source Auditing Approaches3. Looking at suspicious code constructs

A reverse engineer audits calls to functions wich are know to be the source of commonprogramming errors. He looks through these calls and decides which ones to read moreclosely.

Pros:• Reasonable depth: Even relatively complex issues can

be uncovered• In comparison to a complete manual audit, this approach

saves quite a bit of time• The process of looking for suspicious constructs can be

automated to a certain degreeCons:

• Not all problems will be uncovered• Needs highly specialized auditor• If nothing is found, the auditor is back to approach Nr. 2

© HalVar Flake

Page 6: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

The right tool for the task:

IDA Pro by Ilfak Guilfanov www.datarescue.com

• Can disassemble x86, SPARC, MIPS and much more ...• Includes a powerful scripting language• Can recognize statically linked library calls • Features a powerful plug-in interface

© HalVar Flake

Page 7: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dynamically linked library calls:Diagram of program flow

ApplicationCode

DynamicLinkage Table

Executable Image

strcpy ( ) - Code

sprintf ( ) - Code

strcat ( ) - Code

...

Dynamic Library

© HalVar Flake

Page 8: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Statically linked library calls :Diagram of program flow

ApplicationCode

strcpy( ) - Code

Executable Image

strcat( ) - Code

....

© HalVar Flake

Page 9: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Assembly recap: Passing argumentsA simple example

void *memcpy(void *dest, void *src, size_t n);

Assembly representation:

push 4mov eax, unkn_40D278push eaxlea eax, [ebp+var_458]push eaxcall _memcpy

© HalVar Flake

Page 10: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

The classical strcpy/strcat

This call targets a stack buffer

The source is variable, not a static string

© HalVar Flake

Page 11: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

Criteria for suspicious strcpy/strcat calls:

• Does the call target a stack or heap buffer of fixed size ?• Is the source buffer dynamic and not a fixed string ?

The classical strcpy/strcat

© HalVar Flake

Page 12: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructssprintf( ) targeting fixed buffers

Expanded strings are not static and not fixed in length

© HalVar Flake

Format string containing „%s“

Target buffer is a stack buffer

Page 13: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

sprintf( ) targeting fixed buffers

Criteria for suspicious sprintf( ) calls:

• Does the call target a stack or heap buffer of fixed size ?• Does the format string contain a „%s“ ?• Is the expanded string of non-fixed length ?

© HalVar Flake

Page 14: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

*scanf( ) parsing untrusted input

Format string contains „%s“

Data is parsed into stack buffers

© HalVar Flake

Page 15: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

*scanf( ) parsing untrusted input

Criteria for suspicious *scanf( ) calls:

• Does the format string contain a „%s“ ?• Does the call parse a string into a fixed buffer ?

© HalVar Flake

Page 16: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

strncat/strncpy failing to null-terminate

Copying data into a stack buffer again ...

© HalVar Flake

If the source is larger than n (4000 bytes), no NULL will be appended

Page 17: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

strncat/strncpy failing to null-terminate

The target buffer is only n bytes long

Page 18: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

strncat/strncpy failing to null-terminate

Criteria for suspicious strncat/strncpy( ) calls:

• Is the length n the same size as or bigger than the targeted buffer ?• Is the source buffer dynamic and not a fixed string ?• Does the call target a stack or heap buffer of fixed size ?

© HalVar Flake

Page 19: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

format-string vulnerabilities

Argument deficiency

Format string is a dynamic variable

© HalVar Flake

Page 20: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming Constructs

format-string vulnerabilities

Criteria for suspicious *printf-calls

• Does the call suffer from an argument deficiency ?• Is the format string dynamic instead of a static string ?

© HalVar Flake

Page 21: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming ConstructsCast-screwups

void func(char *dnslabel){ char buffer[256]; char *indx = dnslabel; int count;

count = *indx; buffer[0] = '\x00';

while (count != 0 && (count + strlen (buffer)) < sizeof (buffer) - 1) { strncat (buffer, indx, count); indx += count; count = *indx; }}

© HalVar Flake

Page 22: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Dangerous Programming ConstructsCast-screwups

Criteria for suspicious size_t utilization

• Does the function copy memory with a size_t as length ?• Is the size_t a dynamic value instead of a hardwired one ?• Is the size_t subtracted from immediately before the call ?• Is the size_t at any point written after it has been sign-extended with the movsx-mnemonic ?

© HalVar Flake

Page 23: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Automating the boring parts:Hands on: A simple sprintf( ) analyzing script

Things to check for when analyzing a sprintf()-call:

• Does the sprintf( ) target a static buffer ?

• Does the format string contain an „%s“ ?

• Does the call suffer from an argument deficiency ?

• If so, is the format string static or dynamic ?

© HalVar Flake

Page 24: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Automating the boring parts:Hands on: A simple sprintf( ) analyzing script

static GetStackCorr(lpCall){ while((GetMnem(lpCall) != "add")&&(GetOpnd(lpCall, 0) != "esp")) lpCall = Rfirst(lpCall);

return(xtol(GetOpnd(lpCall, 1)));}

Trace the code further until an „add esp, somevalue“ is found

Convert the somevalue to a number and return it

© HalVar Flake

Page 25: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Automating the boring parts:Hands on: A simple sprintf( ) analyzing script

static GetBinString(eaString){ auto strTemp, chr; strTemp = ""; chr = Byte(eaString); while((chr != 0)&&(chr != 0xFF)) { strTemp = form("%s%c", strTemp, chr); eaString = eaString + 1; chr = Byte(eaString); } return(strTemp);}

Zero the string

Get a byte

Until either a NULL or a 0xFF is found, append one byte ata time to the string, then return the string.

© HalVar Flake

Page 26: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Automating the boring parts:Hands on: A simple sprintf( ) analyzing script

Steps to take to retrieve argument n of a call:

1. Locate the n-th push before the function call2. If an immediate offset is pushed, return this value3. If a register was pushed, trace back until the

instruction is found which loaded the registerand return the value it was loaded with

© HalVar Flake

Page 27: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

static GetArg(lpCall, n){ auto TempReg; while(n > 0) { lpCall = RfirstB(lpCall); if(GetMnem(lpCall) == "push") n = n-1; } if(GetOpType(lpCall, 0) == 1) { TempReg = GetOpnd(lpCall, 0); lpCall = RfirstB(lpCall); while(GetOpnd(lpCall, 0) != TempReg) lpCall = RfirstB(lpCall); return(GetOpnd(lpCall, 1)); } else return(GetOpnd(lpCall, 0));}

Trace back until the n-th push is found

Is the pushed operanda register ?

Find where theregister was last

accessed ...

... and return the value which was pushed ...

© HalVar Flake

Page 28: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

static AuditSprintf(lpCall){ auto fString, fStrAddr, buffTarget; buffTarget = GetArg(lpCall, 1); fString = GetArg(lpCall, 2); if(strstr(fString, "offset") != -1) fString = substr(fString, 7, -1); fStrAddr = LocByName(fString); fString = BinStrGet(fStrAddr); if(GetStackCorr(lpCall) < 12) if(strlen(fString) < 2) Message("%lx --> Format String Problem ?\n", lpCall); if(strstr(fString, "%s") != -1) if(strstr(buffTarget, "var_") != -1)

Message("%lx --> Overflow problem ? \"%s\"\n", lpCall, fString);}

Clean up the arguments

Check for argument deficiency

Check for a dynamic format string

Scan the format string for „%s“

Check if the target is a stack variable© HalVar Flake

Page 29: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

static main(){ auto FuncAddr, xref; FuncAddr = AskAddr(-1, "Enter address:"); xref = Rfirst(FuncAddr); while(xref != -1) { if(GetMnem(xref) == "call") AuditSprintf(xref); xref = Rnext(FuncAddr, xref); } xref = DfirstB(FuncAddr); while(xref != -1) { if(GetMnem(xref) == "call") AuditSprintf(xref); xref = DnextB(FuncAddr, xref); }}

Ask auditor to enter theaddress of the sprintf( )

Call the auditing functiononce for each call to sprintf( )

Repeat for all indirect calls

© HalVar Flake

Page 30: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Hands on: Seeing the script in action

Running it against iWS 4.1 SHTML.DLL

We feed our script the number 0x10007068The result:

This looks as if we can supply a very long string here ...

© HalVar Flake

Page 31: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Hands on: Seeing the script in action

Running it against iWS 4.1 SHTML.DLL

The suspicious call ...

... the target buffer push ...

... and the corresponding register load.

© HalVar Flake

Page 32: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Hands on: Seeing the script in action

Running it against iWS 4.1 SHTML.DLL

... and a target buffer of only 256 bytes ...

© HalVar Flake

Page 33: Auditing Closed-Source Applications Using reverse engineering in a security context Speech Outline: 1.Different Approaches to auditing binaries 2.How to

Happy EndWhy doesn‘t the webserver respond any more ?

© HalVar Flake