68
Format Strings Lee Eun-Hun

Format Strings Lee Eun-Hun. Format Parameters Some format parameters ParameterInput TypeOutput Type %dValueDecimal %uValueUnsigned Decimal %xValueHexadecimal

Embed Size (px)

Citation preview

Format StringsLee Eun-Hun

Format Parame-ters

Some format parameters

Parameter Input Type Output Type

%d Value Decimal

%u Value Unsigned Decimal

%x Value Hexadecimal

%s Pointer String

%n Pointer Number of bytes written so far

fmt_uncommon.c

Result

46Bytes

What happens in memory?Top of the stack

Low address Address of format string

Value of A (5)

Address of A (0xbffff844)

Value of B (7)

High address Bottom of the Stack

Change fmt_uncommon.c

Result

What is this value?

Then what happens in memory?

Top of the stack

Low address Address of format string

Value of A (5)

Address of A (0xbffff844)

High address Bottom of the Stack

So this point next memory area.(first value found below stack frame)

The Format String Vulnera-bility

fmt_vuln.c

Result

Why it is working fine?

fmt_vuln_alter.c

Result

Why it isn’t working?

What happens in memory?

Top of the stack

Low address Address of format string

Address of Argv[1]

High ad-dress

Bottom of the Stack

In Right Case

What happens in memory?

Top of the stack

Low address Address of Argv[1]

High ad-dress

Bottom of the Stack

In Wrong Case

So in this case,argv[1] pretends as format string.

So lets do some trick

Top of the stack

Low address Address of argv[1] (test-ing%x)

High ad-dress

Bottom of the Stack (bffff420)

Lets do more trick

What happens in memory?Top of the stack

Low address Address of argv[1]

some stack values

High address Argv[1] (%08x. %08x. %08x. %08x. %08x. %08x. … …)

Reading from Arbitrary Mem-ory Addresses

Let’s reading from arbitrary memory address

Getenvaddr.c

What happens in memory?Top of the stack

Low address Address of argv[1]

some stack values

High address Address of PATH

Writing to Arbi-trary Memory Addresses

It’s time to WRITING to arbi-trary memory address!

31Bytes

Let’s see in memory’s viewTop of the stack

Low address Address of argv[1]

Some stack value (bffff420)

Some stack value (b7fe75fc)

Some stack value (00000000)

Agrv[1](address : test_val + %08x.%08x.%08x.%n)

High address Some stack values

0x08049794 test_val

31

Another example

-> So we can control writing value!

Our GOAL• Change value at 0x08049794 as ‘aabbccdd’

• HOW?

Memory 94 95 96 97

First write to 0x08049794 aa 00 00 00

Second write to 0x08049795 bb 00 00 00

Third write to 0x08049796 cc 00 00 00

Forth write to 0x08049797 dd 00 00 00

Result aa bb cc dd 00 00 00

Let’s do first step

On memory’s viewTop of the stack

Low address Address of argv[1]

Some stack value (bffff420)

Some stack value (b7fe75fc)

Some stack value (00000000)

Agrv[1](address : 0x08049794)

High address Some stack values (%x%x%150x%n) and so on…

0x08049794

170(aa)

Then how about second step?

Top of the stack

Low address Address of argv[1]

Some stack value (bffff420)

Some stack value (b7fe75fc)

Some stack value (00000000)

Agrv[1](address : 0x08049794)

Address : 0x08049795

High address Some stack values (%x%x%150x%n) and so on…

0x08049794

0x08049795

170(aa)

187(bb)

Is it work?

NO!

What is problem?• If we put $(printf “\x94\x97\x04\x08\x95\x97\x04\

x08”)%x%x%150x%n%n then…CAN WE PUT ‘177(bb)’ TO 0x08049795??

• So we NEED some JUNK value.(Junk value must be 4Bytes.)

SolutionTop of the stack

Low address Address of argv[1]

Some stack value (bffff420)

Some stack value (b7fe75fc)

Some stack value (00000000)

Address : 0x08049794

JUNK

Address : 0x08049795

High address Some stack values (%x%x%150x%n)

0x08049794

0x08049795

170(aa)

187(bb)

Now we can do it

I just wonder• What if we modify 0x08049794’s value in just one

step?

It dosen’t work

WHY?

How about two step?

It is work!

Another writing memory example• Make new C program

New goal• Last example, we modify test_val to “0xddccbbaa”

• How about modify test_val to “0x0806abcd”?Is there a new problem?

• Let’s do it!

Let’s try

Do subtract by using %n is possible?

New problem• Last example “0xddccbbaa”,

‘dd > cc’‘cc > bb’‘bb > aa’so, we only need to add some Bytes.

• This time “0x0806abcd”,‘08 > 06’‘06 < ab’‘ab < cd’then we need subract some Bytes.

• We can’t subtract, so we add bytes for calculation.Like ‘1ab > cd’

Solution

You can see next_val is overwrittened.

Keep going on

Why it is not ’08’????

New problem again• %2x option doesn’t print only 2 Byte!

• Because of ‘%2x’ point at ‘JUNK’, it print 8 Bytes!

• So solution is same as before!

Final result

Direct Parame-ter Access

Direct Parameter Access

So we can access some parameter directly by using $ op-tion.

Test direct reading access

So, we can access ‘AAAA’ simply.

Test direct writing access• Let’s modify test_val as ‘0xbffffd72’

We don’t need ‘JUNK’ value, be-cause we directly access to address.

Using Short Writes

h option• ‘Short’ is two-Byte word.

• We can define ‘short’ simply put h at parameter.(%hi, %hd, %hn and so on)

• By using short, we can modify 4 Bytes value in 2 step!

Some example

Why need short write?• At previous side, I show 4 Byte write also can over-

write memory in two step.

• Then what is benefit?

Let’s change order of write• With 4 Byte word

• It doesn’t work, because writing at 0x08049794 over-writes previous job.

Benefit of short writes

• Short take only 2 Bytes, so we can avoid overwrite.So order doesn’t matter.

Detours with .dtors

Two function• Constructor : excute before main function.

• Destructor : excute before exit system call.

• Table section ‘.dtors’ and ‘.ctors’ are made for de-structor and constructor.

Dtors_sample.c

• Cleanup function is defined with destructor at-tribute, so cleanup function is automatically call when main call exit system call.

Result

.dtors table section• The .dtors table array always begins with 0xffffffff

and ends with the NULL address of 0x00000000.

• Between these two are the addresses of all func-tions that have been declared with the destructor attributes.

• .dtors table section is always include in binary even if you don’t use destructor attribute, if you com-piled with GNU C compiler.

nm command• nm command list symbols from object files.

• It can be used to find the address of function.

nm command example• As definition,

__DTOR_END__ contains 0xffffffff__DTOR_LIST__ contains 0x00000000

• And address between __D-TOR_END__ and __DTOR_LIST__(0x080495b0) contains address of cleanup function.(0x080483e8)

See actual content• By using objdump command, we can see actual

content of .dtors section.

• So as we can see .dtors section address is 0x80495ac, and it contains 0xffffffff, 0x080483e8, and 0x00000000.

.dtors sction is WRITABLE!

./fmt_vuln also contain .dtors section

.dtors section is WRITABLE, so by overwrite this section we can do some malicious attack!

Let’s do it!• We will run shellcode when exit system call by

overwrite .dtors section.

• So we need to get shellcode address.

• Also we need .dtors section address.

Change .dtors section• Change __DTOR_END__ value as shellcode address.

• It change __DTOR_END__ value as shellcode ad-dress, so when main call exit system call it sud-denly run shellcode.

Let’s see in memory viewTop of the stack

Low address Address of argv[1]

Some stack value

Some stack value

Some stack value

Address of 0x08049696

Address of 0x08049694

High address Some stack values

0x08049694 0000 0000

0x08049794 -74 Pass 0xbfff

Pass 0xf9f1

Question?