© Anders Ingeborn +46-8-662 10 70 IDS Evasion Design Tricks for Buffer Overflow Exploits

Preview:

Citation preview

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

IDS Evasion Design Tricks for Buffer Overflow Exploits

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Why buffer overflows?

• Very effective attacks– Run attacker’s code of choice– Allowed protocols goes through firewalls

• Very common problem– Most common for the past 10 years!

• Oregon Institute of Technology (1999)

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Why these design tricks?

• Get around mismanaged bounds check– Adds possible exploitations

• Evade network based IDS

• Evade host based IDS

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Agenda

• Theory– Double injection– Existing network connection– Function calls to .dll’s

• Example

• Countermeasures

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Brief reminder

• E.g. strcpy() w/o bounds check

– copies until ’0x00’-byte

• Write outside dedicated stack memory

• Overwrite stored instruction pointer

• Jump into your code

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Simple illustration

EIP

00 12 FF 00

00 12 FF 04

00 12 FF 08

00 12 FF 0C

00 12 FF 10

00 12 FF 14

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Mismanaged bounds check

• Let’s say a vulnerable server performs a bounds check on receive – but not on strcpy()

• Let’s say strncpy() is used– but there has been a miscalculation

• It is still possible to inject

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Size restrictions?

• Separate buffers for injector and payload– Restrictions on injector, but not on payload?

• Same buffer for injector and payload– Restrictions also on payload– Do everything using as few bytes as possible

• Naive, but OK

– Change design concept• Double injection

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Simple small ”shell”

• Functional requirements– Listen for requests over network– Execute those as system commands

• Every byte counts– Keep number of libraries low– Keep number of functions low

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

250 bytes example

• Two libraries: Winsock & Kernel32

• Datagram socket instead of stream– don’t need listen() nor accept()

• Loop– Call to recvfrom()– Execute with call to WinExec()

• http://www.securityfocus/bid/2200/

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Another design concept

• Double injection– Use first payload to upload and execute

second payload

• Benefits– Very small first payload (43 bytes)– No restrictions on the size of the second

payload

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

”Double injection”

Stack

Server

pnex()

Client

First callStack

#1

Stack#2

First payload

Strcpy()

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

”Double injection”

Stack

Client Stack#1

First payload

Second payload

Second call

Communicationchannel

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

What to send 2nd time?

• Your code of choice!– May still use the socket– May still use the jump table– No need to XOR-protect NULLs

• Raw data over socket

• Proof-of-concept implementation– Confirms by sending a message

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

OK, this seems nice

• How to minimize code?

• Use pre-loaded functions– Server has already loaded some .dll’s

• Use existing network connection– Server has already an existing TCP

session with you– Find the socket descriptor, re-use it

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

How to find descriptor

• Find accept() call– Set breakpoint, debug– Where is returned value stored?

• Lots of disassemblers available– Freeware, e.g. ”dsassm”– Commercial, e.g. IDA Pro

• Example on slide 38

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Benefits

• By using pre-loaded functions– Fewer bytes

• By using same network connection– Some network based intrusion detection

systems might be evaded– No new TCP-handshakes– No haxor 31337 ports

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Benefits

• By writing a minimal injector/payload

• Stack frame below is not disrupted

• A clean return might be possible– The server process won’t crash– No log entry for a host based intrustion

detection system to detect

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

”Might” be possible?

• We got to find the correct return address– A ”static” disassemble of the .dll shows

compile time requested base address– Might not be used at run time

• We might need to restore some internal register values

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Correct return address?

• The original return address is overwritten– Our way to control, 1st injection

• Two ways to handle this– Calculate return address manually– Pop another stack frame

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Pop another frame

• Let’s say– Main calls a function in .dll– 1st function in .dll calls 2nd function– 2nd function is exploited

• Maybe we can return to main?– Return point in main at 0x40ABCD– This adress won’t change from a

disassembly of the ”static” exe

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Situation #1 illustrated

Main stack

Stack #1

Stack #2Injection

Use this return address

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Calculate return address

• Return to the ”correct” function

• A fix distance down the stack– Below stack frame #1– Is the ret addr to ”main” 0x40..– And a fix distance from there is the call

address to function #1– And a fix distance from the call (start)

address is ”our” ret addr

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

What?!

• Let’s have a look at function calls

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Function calls

pnex.dll

0x4030F2

0x40B1A8 0x1000112C

0x1000112CJMP [0x40B1A8]

0x40120F CALL 0x4030F2

”Main”

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Why do they look like this?

• OS only need to patch one place in the code, not every call

• OS does not need to know how to generate complete jump instructions, just patch in address of function

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Find call/start address

0x4030F2

0x40B1A8 0x1000112C

JMP [0x40B1A8]

0x40120F CALL 0x4030F2

”Main”

Main stack

0x401214

Stack #1

Injection0x401214

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Calculate return address

0x4030F2

0x40B1A8 0x1000112C

JMP [0x40B1A8]

0x40120F CALL 0x4030F2

”Main”

pnex.dll

0x401214

0x1000112C

0x1000113C0x10001137 CALL …

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Might be possible?

• We got to find the correct return address– A ”static” disassemble of the .dll shows

compile time requested base address– Might not be used at run time

• We might need to restore some internal register values

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Internal register values

• Internal register values of function #1 might be stored on the stack– When function #2 starts executing

• These has to be restored– Function #2 restores them before RET– But our first injector overwrites their

stored values during the string copy

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Function call

Stack #1

Stack #2

Arguments

RegistersRET address

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Function call

Stack #1

Stack #2

Arguments

RegistersRET address

String copy

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Clean return requirement

• We need to be able to restore neccessary internal registers– A normal execution/debug shows which

registers are neccessary to restore

• We have to restore them manually– Predictable/static values?– Possible to calculate from other

untouched information at fix positions?

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

OK, this sounds cool, but?

• Proof-of-concept implementation– Simple vulnerable server– Remote client with exploit

• Is included on CD

• Will be available on BlackHat website

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Implementation exposed

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Server

– Accept connections• Receive ”commands”• Upper limit at 100 bytes

– Call parse and execute function in dynamically linked library pnex.dll

• parsnexec()

– Parsnexec() calls internal function• internal()• contains a stack overflow vulnerability

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Initial injection

• Server uses strncpy()– But a miscalculation is present

• Injection– Point EIP to a RET in ”main”

• Null terminated injector, 0x004010D7

– Program will jump to address just below– Which points to argument (our buffer)

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

First payload

• Find socket descriptor

• Find address of recv() function

• Call recv()

• Store second payload in free memory

• Jump to second payload

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Find socket descriptor

00401171 lea eax, [ebp-4]00401174 push eax00401175 lea eax, [ebp-0DCh]0040117B push eax0040117C push dword ptr [ebp-29Ch]00401182 call _accept@1200401187 mov [ebp-298h], eax0040118D cmp dword ptr [ebp-298h], 000401194 jge short loc_4011A900401196 push offset aErrorOnAccept ; "Error on accept!\n"0040119B call _printf

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Using the socket

Stack frame #1

Stack memory • Stack frames’ placement might change• Socket’s position within frame doesn’t• Fix relative distance from top of frame

Stack frame #2

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Debug and look at memory

Orig. RET Argument

0x40 RET Argument Argument

Socket

Stack

Stack

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Offset

• Socket descriptor will always be 32 bytes from where ESP points to after the injection

• ESP points one byte down the stack frame of parsnexec()

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Code

0x89,0xE5, // 1-2 mov ebp, esp

0x66,0x81,0xEC,0xF0,0x03, // 3-7 sub sp

0x31,0xC0, // 8-9 xor

0x50, //10 push "flags"

0x6A,0x7F, //11-12 push "size"

0x8D,0x44,0x24,0x08, //13-16 lea [esp+8] "buff"

0x50, //17 push eax

0x8D,0x45,0x20, //18-20 lea [ebp+20] "sock"

0xFF,0x30, //21-22 push [eax]

0xB8,0xFF,0xEC,0x30,0x40, //23-27 mov eax, 0x4030ec

0xC1,0xE8,0x08, //28-30 shr eax,8

0xFF,0xD0, //31-32 call eax

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Find recv() function

0040B180 ; 0040B180 ; Imports from WS2_32.dll0040B180 ; 0040B180 extrn __imp__WSAStartup@8:dword ; DATA XREF: .text:00402FA40040B184 extrn __imp__socket@12:dword ; DATA XREF: .text:00402FAA0040B188 extrn __imp__htonl@4:dword ; DATA XREF: .text:004030CE0040B18C extrn __imp__htons@4:dword ; DATA XREF: .text:004030D40040B190 extrn __imp__bind@12:dword ; DATA XREF: .text:004030DA0040B194 extrn __imp__listen@8:dword ; DATA XREF: .text:004030E00040B198 extrn __imp__accept@12:dword ; DATA XREF: .text:004030E60040B19C extrn __imp__recv@16:dword ; DATA XREF: .text:004030EC0040B1A0 extrn __imp__send@16:dword ; DATA XREF: .text:0040318C

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Recevie call

Inject. ESPEBP

?? Overwritten by injector

flags

socketbufflength

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Second payload

• Send message back to client– Still using same TCP session

• Calculate return address

• Restore all registers and return clean!– EBP, ESP, EBX and EIP

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Send message

Find send() function through disassembly

0040B180 ; 0040B180 ; Imports from WS2_32.dll0040B180 ; 0040B180 extrn __imp__WSAStartup@8:dword ; DATA XREF: .text:00402FA40040B184 extrn __imp__socket@12:dword ; DATA XREF: .text:00402FAA0040B188 extrn __imp__htonl@4:dword ; DATA XREF: .text:004030CE0040B18C extrn __imp__htons@4:dword ; DATA XREF: .text:004030D40040B190 extrn __imp__bind@12:dword ; DATA XREF: .text:004030DA0040B194 extrn __imp__listen@8:dword ; DATA XREF: .text:004030E00040B198 extrn __imp__accept@12:dword ; DATA XREF: .text:004030E60040B19C extrn __imp__recv@16:dword ; DATA XREF: .text:004030EC0040B1A0 extrn __imp__send@16:dword ; DATA XREF: .text:0040318C

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Still using the same socket

0x6A,0x00, //push 0x0 "flags"

0x6A,0x1D, //push "length"

0x8D,0x47,0x43, //lea eax,dword ptr [edi+0x43]

0x50, //push "buf"

0x8D,0x45,0x20, //lea eax,dword ptr [ebp+0x20]

0xFF,0x30, //push [eax] "socket"

0xB8,0x8C,0x31,0x40,0x00, //mov eax, 0x40318c

0xFF,0xD0, //call eax

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Finding return address

• Demo implementation returns to function parsnexec() in pnex.dll

• Return address manually calculated

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Find call/start address

0x40B1A8 0x1000112C

0x40120F CALL 0x4030F2

”Main”

Main stack

0x401214

Stack #1

Injection0x401214

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Calculate return address

0x4030F2

0x40B1A8 0x1000112C

JMP [0x40B1A8]

0x40120F CALL 0x4030F2

”Main”

pnex.dll

0x401214

0x1000112C

0x1000113C0x10001137 CALL …

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Code

0x8D,0x45,0x0C, //lea eax, [ebp+0xC]0x8B,0x18, //mov ebx, [eax] "ret to main"0x81,0xC3,0x94,0x9F,0x00,0x00,

//add ebx, 0x9F94 "fix offset in main"0x8B,0x03, //mov eax, [ebx] "fix offset in .dll"0x83,0xC0,0x10, //add eax, 0x10 "ret to parsnexec"

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Restore internal registers

• Calculated from top of stack frame of parsnexec()– ESP shall point to top of frame– EBP shall point to base of frame

• Size of frame is fix, just add

– EBX shall point to an variable in frame• Position within frame is fix, just add

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Code

0x89,0xFC, //mov esp, edi "set esp"0x81,0xC4,0xEC,0x03,0x00,0x00, //add esp

0x89,0xE5, //mov ebp, esp ”set ebp"0x81,0xC5,0xBC,0x02,0x00,0x00, //add ebp,

0x89,0xE3, //mov ebx, esp "set reg. ebx"0x81,0xC3,0x54,0x02,0x00,0x00, //add ebx, 0x254 "ptr to res buf"

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Summary

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Summary

• Double injection– Let the first payload upload a second – Jump to second payload

• Execute your code of choice

• Use existing network connection– Socket descriptor– Use existing functions, i.e. jump table

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Benefits

• Evade network based IDS– No unrecognized 31337 ports– No new TCP handshakes

• Evade host based IDS– No new connections– No log entry

• Access violation• Unexpected termination...

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Countermeasures

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

IDS countermeasures

• NIDS application protocol interpretation– ASCII-encoding (currently hot topic)– Payloads may use fake headers– Interpretation adds complexity to IDS,

i.e. slows down analysis

• HIDS ”strange behavior” awareness– Statistically ”long” session etc.– Adds complexity

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Other countermeasures

• Prohibit execution on stack

• Put a reverse application proxy in front of server

© Anders Ingeborn +46-8-662 10 70 www.ixsecurity.com

Questions?

• Catch me during the conference!

• E-mail: ingeborn@ixsecurity.com

Recommended