Post

unpackme - PicoCTF Write-Up

A write-up on the challenge unpackme.

Introduction

Hello! 👋 Today, we’re going to take a look at the ‘unpackme’ challenge on PicoCTF by LT ‘syreal’ Jones. The difficulty level is medium.”

Challenge Description

Can you get the flag?

Reverse engineer this binary.

Solution

So, let’s make the binary executable using chmod.

1
chmod +x unpackme-upx

Now, let’s try running the executable and see what it does.

1
2
3
4
┌──(printn㉿printn)-[~]
└─$ ./unpackme-upx 
What's my favorite number? 1
Sorry, that's not it!

From the first hint, we are asked what UPX is, and a quick search online gives us this: UPX is a free and open-source executable packer that compresses and reduces the size of executable files

So let’s unpack the binaray with UPX.

1
2
3
4
5
6
7
8
9
10
11
┌──(printn㉿printn)-[~]
└─$ upx -d unpackme-upx
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2024
UPX 4.2.2       Markus Oberhumer, Laszlo Molnar & John Reiser    Jan 3rd 2024

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
   1006445 <-    379188   37.68%   linux/amd64   unpackme-upx

Unpacked 1 file.

We can now open it up in Ghidra and analyze it with the default settings. After it has analyzed we Ghidra finds the main function:

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
undefined8 main(void)

{
  long in_FS_OFFSET;
  int local_44;
  char *local_40;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined4 local_20;
  undefined2 local_1c;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_38 = 0x4c75257240343a41;
  local_30 = 0x30623e306b6d4146;
  local_28 = 0x6865666430486637;
  local_20 = 0x36636433;
  local_1c = 0x4e;
  printf("What\'s my favorite number? ");
  __isoc99_scanf(&DAT_004b3020,&local_44);
  if (local_44 == 0xb83cb) {
    local_40 = (char *)rotate_encrypt(0,&local_38);
    fputs(local_40,(FILE *)stdout);
    putchar(10);
    free(local_40);
  }
  else {
    puts("Sorry, that\'s not it!");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

We see that it checks if our input is the same as 0xb83cb, which is encrypted in base 16 (hexadecimal). Converting it to base 10, we get the number 754635.

1
2
3
4
┌──(printn㉿printn)-[~]
└─$ ./unpackme-upx
What's my favorite number? 754635
picoCTF{up><_m3_f7w_5769b54e}

And we get the flag 😃: picoCTF{up><_m3_f7w_5769b54e}

This post is licensed under CC BY 4.0 by the author.