1 min read

picoCTF "ret" Reverse Engineering Writeup

picoCTF "ret" Reverse Engineering Writeup

Challenge Info

Walkthrough

Step 1: Recon

Just run it and see how it behaves:

./ret

→ It prompts for a password, and shows Access denied if you get it wrong.

Step 2: Static Scan

Use strings to scan the .rodata section and check whether the flag or a hint is hardcoded:

strings ret | grep -i pico

→ It prints Password correct, please see flag: picoCTF{Redacted}

Flag obtained directly: picoCTF{Redacted}

Step 3: Decompile and Inspect (verifying the program logic)

undefined8 main(void)

{
  int iVar1;
  long in_FS_OFFSET;
  char local_68 [48];
  char local_38 [40];
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  builtin_strncpy(local_38,"picoCTF{3lf_r3v3r5ing_succe55ful_7851ef7",0x28);
  printf("Enter the password to unlock this file: ");
  __isoc99_scanf(&DAT_00102031,local_68);
  printf("You entered: %s\n",local_68);
  iVar1 = strcmp(local_68,local_38);
  if (iVar1 == 0) {
    puts("Password correct, please see flag: picoCTF{3lf_r3v3r5ing_succe55ful_7851ef7d}");
    puts(local_38);
  }
  else {
    puts("Access denied");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

Key points from the Ghidra decompilation:

  • The program copies the string "picoCTF{3lf_r3v3r5ing_succe55ful_7851ef7" (note the missing trailing d}) into local_38 via builtin_strncpy(..., 0x28)
  • It then compares with strcmp(local_68, local_38):
    • If your input equals this prefix string, it prints the success message together with the complete flag picoCTF{Redacted}
  • So the "password" is really the prefix: picoCTF{3lf_r3v3r5ing_succe55ful_7851ef7 (entering this string triggers the success branch, and the program then prints the full flag on its own)

Takeaways

  • Beginner RE challenges often hardcode the flag/hint straight into .rodata: reach for strings first for a quick recon pass
  • Identify the "comparison point" and the "success branch": here the strcmp only checks a prefix, and the complete flag is only printed after a match