Skip to main content
added 1491 characters in body
Source Link

A little theory

Just triedIf you want to see actual trick to write at custom address jump to second part.

Lets try tweaking format string intoin printf() trick.

Breakpoint 1, __printf (format=0x555555556004 "ABABABAB") at ./stdio-common/printf.c:28

As you can see that format string address indeed resides in .rodata section of process:

(gdb) i args
format = 0x555555556004 "ABABABAB"

So how is address of format string passed to prIntf()? When When we dumped registers we saw format string address in rsi register.

Because function arguments (string address in this case) will be passed in rsi and rdi registers for purpose of speed and not in the stack we cant use format string and string arguments for this trick.

So youwe can just use strings created as local (automatic) variables to be put in stack, before return address in current stack frame, because function arguments (string address in this case) will be passed in rsi and rdi registers for purpose of speed.

Actual example

Anyway I tried this small example and it worked, printed out addresses put in local strings (created on stack). SOSo we could use this trick to make local strings mimic addresses we want to access:

Using hexadecimal format %x showed HEX representation of strings avro, nana, loli on stack (using %s string format would cause segmentation fault because printf() would interpret those values as addresses of strings but those "addresses" are probably not in mapped area of the process or are in protected memory area):

Output

So now we used local variables on stack to "masquerade" as data access. But what if we can use this to try to write on that address?

Lets change last %X format specifier to %n. Instead of printing content of data on stack with %X, we will use this data as address of variable where printf() stores number of characters already printed. So idea is to gain write access to custom address.

printf("ABABABAB\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%n");

Our FAKE address 0x61616161616161 represented as ASCII "aaaaaaa" ends in %rax register, and printf will write at this address number of characters already printed (stored in r12):

(gdb) i r
rax            0x61616161616161    27410143614427489
rbx            0x555555556052      93824992239698


      0x00007ffff7df7c3c <+7180>:   jne    0x7ffff7df8276 <__vfprintf_internal+8774>
   => 0x00007ffff7df7c42 <+7186>:   mov    %r12d,(%rax)

But in our case this will use SEGV segmentation fault since address 0x61616161616161 is not mapped into process memory.

Continuing.
ABABABAB
,00007FFFFFFFDF08
,00007FFFFFFFDF18
,0000555555557DB8
,00007FFFF7F9BF10
,00007FFFF7FC9040
,0031313131313131
,0032323232323232
Program received signal SIGSEGV, Segmentation fault.

I hope this helps!

Just tried tweaking format string into printf() trick.

Breakpoint 1, __printf (format=0x555555556004 "ABABABAB") at ./stdio-common/printf.c:28

As you can see that format string address indeed resides in .rodata section of process:

(gdb) i args
format = 0x555555556004 "ABABABAB"

So how is address of format string passed to prIntf()? When we dumped registers we saw format string address in rsi register.

So you can just use strings created as local (automatic) variables to be put in stack, before return address in current stack frame, because function arguments (string address in this case) will be passed in rsi and rdi registers for purpose of speed.

Anyway I tried this small example and it worked, printed out addresses put in local strings (created on stack). SO we could use this trick to make local strings mimic addresses we want to access:

Using hexadecimal format showed HEX representation of strings avro, nana, loli on stack (using string format would cause segmentation fault because printf would interpret those values as addresses of strings but those "addresses" are probably not in mapped area or are in protected memory area):

Output

A little theory

If you want to see actual trick to write at custom address jump to second part.

Lets try tweaking format string in printf() trick.

Breakpoint 1, __printf (format=0x555555556004 "ABABABAB") at ./stdio-common/printf.c:28
(gdb) i args
format = 0x555555556004 "ABABABAB"

So how is address of format string passed to prIntf()? When we dumped registers we saw format string address in rsi register.

Because function arguments (string address in this case) will be passed in rsi and rdi registers for purpose of speed and not in the stack we cant use format string and string arguments for this trick.

So we can just use strings created as local (automatic) variables to be put in stack, before return address in current stack frame.

Actual example

Anyway I tried this small example and it worked, printed out addresses put in local strings (created on stack). So we could use this trick to make local strings mimic addresses we want to access:

Using hexadecimal format %x showed HEX representation of strings avro, nana, loli on stack (using %s string format would cause segmentation fault because printf() would interpret those values as addresses of strings but those "addresses" are probably not in mapped area of the process or are in protected memory area):

Output

So now we used local variables on stack to "masquerade" as data access. But what if we can use this to try to write on that address?

Lets change last %X format specifier to %n. Instead of printing content of data on stack with %X, we will use this data as address of variable where printf() stores number of characters already printed. So idea is to gain write access to custom address.

printf("ABABABAB\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%016llX\n,%n");

Our FAKE address 0x61616161616161 represented as ASCII "aaaaaaa" ends in %rax register, and printf will write at this address number of characters already printed (stored in r12):

(gdb) i r
rax            0x61616161616161    27410143614427489
rbx            0x555555556052      93824992239698


      0x00007ffff7df7c3c <+7180>:   jne    0x7ffff7df8276 <__vfprintf_internal+8774>
   => 0x00007ffff7df7c42 <+7186>:   mov    %r12d,(%rax)

But in our case this will use SEGV segmentation fault since address 0x61616161616161 is not mapped into process memory.

Continuing.
ABABABAB
,00007FFFFFFFDF08
,00007FFFFFFFDF18
,0000555555557DB8
,00007FFFF7F9BF10
,00007FFFF7FC9040
,0031313131313131
,0032323232323232
Program received signal SIGSEGV, Segmentation fault.

I hope this helps!

added 2 characters in body
Source Link
 

Sample code

We have to print 5 random values until we reached what we wanted, our local strings!

Using hexadecimal format showed HEX representation of strings avroavro, nananana, loliloli on stack (using string format would cause segmentation fault because printf would interpret those values as addresses of strings but those "addresses" are probably not in mapped area or are in protected memory area):

OutputOutput

Sample code

Using hexadecimal format showed HEX representation of strings avro, nana, loli on stack (using string format would cause segmentation fault because printf would interpret those values as addresses of strings but those "addresses" are probably not in mapped area or are in protected memory area):

Output

 

Sample code

We have to print 5 random values until we reached what we wanted, our local strings!

Using hexadecimal format showed HEX representation of strings avro, nana, loli on stack (using string format would cause segmentation fault because printf would interpret those values as addresses of strings but those "addresses" are probably not in mapped area or are in protected memory area):

Output

added 553 characters in body
Source Link

SO there should beyou can see return address to main() 0x555555555165, and expect to find format string address on stack at address 0x7fffffffdde0 But when Iwe dump stack instead of format string address there is just 8 bytes of zeros where function argument should be, between __libc_start_call_main() stack frame return address and printf() stack frame return address:

But when iSo how is address of format string passed to prIntf()? When we dumped registers iwe saw format string address in rsi register.

Anyway I tried this small example and tit worked, printed out addresses put in local strings (created on stack). SO we could use this trick to make local strings mimic addresses we want to access:

SO there should be format string address on stack at address 0x7fffffffdde0 But when I dump stack instead of format string address there is just 8 bytes of zeros where function argument should be, between __libc_start_call_main() stack frame return address and printf() stack frame return address:

But when i dumped registers i saw format string address in rsi register.

Anyway I tried this small example and t worked, printed out addresses put in local strings (created on stack)

you can see return address to main() 0x555555555165, and expect to find format string address on stack at address 0x7fffffffdde0 But when we dump stack instead of format string address there is just 8 bytes of zeros where function argument should be, between __libc_start_call_main() stack frame return address and printf() stack frame return address:

So how is address of format string passed to prIntf()? When we dumped registers we saw format string address in rsi register.

Anyway I tried this small example and it worked, printed out addresses put in local strings (created on stack). SO we could use this trick to make local strings mimic addresses we want to access:

added 553 characters in body
Source Link
Loading
added 656 characters in body
Source Link
Loading
added 39 characters in body
Source Link
Loading
added 63 characters in body
Source Link
Loading
deleted 4 characters in body
Source Link
Loading
Source Link
Loading