The Usual

Description

In the heart of a bustling medieval market, a burly Viking with a formidable beard and weathered armor stumbles upon a peculiar sight—a vibrant flag shop adorned with banners of every hue. Intrigued by the fluttering colors, he enters the shop, his towering frame contrasting with the delicate textiles. With a mix of curiosity and confusion, he marvels at the array of flags, pondering which one might best represent his warrior clan amidst the sea of symbols and sigils.

Connect to 35.94.129.106:3008 to find the flag

nc 35.94.129.106 3008

the-usualarrow-up-right

Analysis

Decompile with Ghidra for better understand the code.

chevron-rightmain_loop functionhashtag
void main_loop(void)

{
  int iVar1;
  uint bought_item_count;
  uint bought_item;
  char *buy_prompt;
  uint index;
  uint money;
  
  money = 100;
  while( true ) {
    while( true ) {
      printf("%s",MENU);
      printf("Your balance is $%d\n",(ulong)money);
      bought_item = 0;
      buy_prompt = "What would you like to buy? (1-5) ";
      iVar1 = read_uint(&bought_item,"What would you like to buy? (1-5) ");
      if (((iVar1 != -1) && (bought_item != 0)) && (bought_item < 6)) break;
      puts("I\'m afraid we don\'t sell that");
    }
    if (bought_item == 5) break;
    bought_item_count = 0;
    buy_prompt = "How many would you like? ";
    iVar1 = read_uint(&bought_item_count,"How many would you like? ");
    if (iVar1 == -1) {
      puts("I can\'t sell that many");
    }
    else {
      iVar1 = can_afford(money,bought_item_count,bought_item);
      if (iVar1 == 0) {
        puts("You can\'t afford that");
      }
      else {
        index = 0;
        do {
          if (bought_item == 1) {
            money = money - 10;
            print_quote();
          }
          else if (bought_item == 2) {
            money = money - 45;
            print_art();
          }
          else if (bought_item == 3) {
            money = money - 130;
            print_stand();
          }
          else {
            if (bought_item != 4) {
              puts("Goodbye!");
              return;
            }
            puts("Sorry, the flag is under maintenance");
          }
          index = index + 1;
        } while (index < bought_item_count);
      }
    }
  }
  puts("Goodbye!");
  return;
}

print_flag function exists, but it's not in the main_p. Somehow we have to get to that function and read the flag.

Basic checks:

└─$ file the-usual
the-usual: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=987649bea4bf5ae80d566897f18794463e210857, for GNU/Linux 4.4.0, not stripped

└─$ checksec --file=./the-usual
[*] '.../CTFs/vikectf/2024/misc/The Usual/the-usual'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

No PIE and no canary, we could be dealing with buffer overflow.

The 3rd item: print_stand is interesting:

fgets reads 300 bytes into 32 byte buffer which just screams buffer overflow. But first we need to reach print_stand. currently we have $100, and this option needs $130. We cant make money from game, only spend. But we can forge imaginary money D:

read_uint function for whatever reason takes in our input, converts it to unsigned long using strtoularrow-up-right and then converts result to int??

We can leverage this small mistake to essentially exploit the program. Example to demonstate integer overflow attack:

Solution

Solve Script:

circle-check

Last updated