Post

Pico CTF 2022: Reverse-Engineering πŸ›  πŸ’Ύ

file-run1

A program has been provided to you, what happens if you try to run it on the command line? Download the program here.

1
2
3
4
5
6
7
➜  revEngineer ls
run
➜  revEngineer file run 
run: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f9df27b4be0359f544470c9df7db39f209366c6c, for GNU/Linux 3.2.0, not stripped
➜  revEngineer chmod +x run 
➜  revEngineer ./run 
The flag is: picoCTF{U51N6_Y0Ur_F1r57_F113_5578e314}

Flag : picoCTF{U51N6_Y0Ur_F1r57_F113_5578e314}

file-run2

Another program, but this time, it seems to want some input. What happens if you try to run it on the command line with input β€œHello!”? Download the program here.

1
2
3
➜  file-run2 chmod +x run 
➜  file-run2 ./run Hello!
The flag is: picoCTF{F1r57_4rgum3n7_981abfb5}

Flag : picoCTF{F1r57_4rgum3n7_981abfb5}

GDB Test Drive

Can you get the flag? Download this binary. Here’s the test drive instructions:

1
2
3
4
5
6
$ chmod +x gdbme
$ gdb gdbme
(gdb) layout asm
(gdb) break *(main+99)
(gdb) run
(gdb) jump *(main+104)

image

1
2
3
4
5
6
7
8
9
10
(gdb) break *(main+99)
Breakpoint 1 at 0x132a
(gdb) run
Starting program: /cases/pico2022/revEngineer/gbdtestdrive/gdbme

Breakpoint 1, 0x000055555555532a in main ()
(gdb) jump *(main+104)
Continuing at 0x55555555532f.
picoCTF{d3bugg3r_dr1v3_93b87433}
(gdb) ior 1 (process 23118) exited normally]

Flag : picoCTF{d3bugg3r_dr1v3_93b87433}

patchme.py

Can you get the flag? Run this Python program in the same directory as this encrypted flag.

patchme.flag.py

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
#### THIS FUNCTION WILL NOT HELP YOU FIND THE FLAG --LT ########################
def str_xor(secret, key):
    #extend key to secret length
    new_key = key
    i = 0
    while len(new_key) < len(secret):
        new_key = new_key + key[i]
        i = (i + 1) % len(key)        
    return "".join([chr(ord(secret_c) ^ ord(new_key_c)) for (secret_c,new_key_c) in zip(secret,new_key)])
###############################################################################


flag_enc = open('flag.txt.enc', 'rb').read()



def level_1_pw_check():
    user_pw = input("Please enter correct password for flag: ")
    if( user_pw == "ak98" + \
                   "-=90" + \
                   "adfjhgj321" + \
                   "sleuth9000"):
        print("Welcome back... your flag, user:")
        decryption = str_xor(flag_enc.decode(), "utilitarian")
        print(decryption)
        return
    print("That password is incorrect")



level_1_pw_check()

We simply need to change the if condition as below to decrypt the flag regardless of incorrect password.

1
2
3
4
5
6
7
8
9
10
11
def level_1_pw_check():
    user_pw = input("Please enter correct password for flag: ")
    if( user_pw != "ak98" + \
                   "-=90" + \
                   "adfjhgj321" + \
                   "sleuth9000"):
        print("Welcome back... your flag, user:")
        decryption = str_xor(flag_enc.decode(), "utilitarian")
        print(decryption)
        return
    print("That password is incorrect")
1
2
3
4
python patchme.flag.py 
Please enter correct password for flag: haha
Welcome back... your flag, user:
picoCTF{p47ch1ng_l1f3_h4ck_4d5af99c}

Flag : picoCTF{p47ch1ng_l1f3_h4ck_4d5af99c}

Safe Opener

Can you open this safe? I forgot the key to my safe but this program is supposed to help me with retrieving the lost key. Can you help me unlock my safe? Put the password you recover into the picoCTF flag format like: picoCTF{password}

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
import java.io.*;
import java.util.*;  
public class SafeOpener {
    public static void main(String args[]) throws IOException {
        BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
        Base64.Encoder encoder = Base64.getEncoder();
        String encodedkey = "";
        String key = "";
        int i = 0;
        boolean isOpen;
        

        while (i < 3) {
            System.out.print("Enter password for the safe: ");
            key = keyboard.readLine();

            encodedkey = encoder.encodeToString(key.getBytes());
            System.out.println(encodedkey);
              
            isOpen = openSafe(encodedkey);
            if (!isOpen) {
                System.out.println("You have  " + (2 - i) + " attempt(s) left");
                i++;
                continue;
            }
            break;
        }
    }
    
    public static boolean openSafe(String password) {
        String encodedkey = "cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz";
        
        if (password.equals(encodedkey)) {
            System.out.println("Sesame open");
            return true;
        }
        else {
            System.out.println("Password is incorrect\n");
            return false;
        }
    }
}

You’re given a java program to reverse engineer the password from. From the program we can see that the password string is encoded in base64. We can simply do as below.

1
2
➜  safeopener echo 'cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz' | base64 -d
pl3as3_l3t_m3_1nt0_th3_saf3
1
2
3
4
➜  safeopener java SafeOpener
Enter password for the safe: pl3as3_l3t_m3_1nt0_th3_saf3
cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz
Sesame open

Flag : picoCTF{pl3as3_l3t_m3_1nt0_th3_saf3}

unpackme.py

Can you get the flag? Reverse engineer this Python program.

1
2
3
4
5
6
7
8
9
10
import base64
from cryptography.fernet import Fernet

payload = b'gAAAAABiMD1Dt87s50caSunQlHoZqPOwtGNaQXexN-gjKwZeuLEN_-v6UcFJHVXOT4B6DcD1SB7cnd6yTcHg9e9LZCAeJY2cJ0r0sfyGPRiH60F-WbkyUjlAdDywI8RPdTpDYLuBmpZ_Kun-kHyTzMjeKR6R26Z4JITUS8n7Dj9X--9eNLajH6UuYD4GkjRACpsidl_8z33DlB86u_xDCMMm7HFK2oJTs8HG1fBex6enQsu0frUAJbx56DxhRvWawAysDMtLE50vaohrzkVV7Yaz4ClilwgfjQ=='

key_str = 'correctstaplecorrectstaplecorrec'
key_base64 = base64.b64encode(key_str.encode())
f = Fernet(key_base64)
plain = f.decrypt(payload)
exec(plain.decode())

We can simply run the program line by line via python interpreter to reverse engineer the code.

1
2
3
4
5
6
7
8
9
10
11
>>> payload = b'gAAAAABiMD1Dt87s50caSunQlHoZqPOwtGNaQXexN-gjKwZeuLEN_-v6UcFJHVXOT4B6DcD1SB7cnd6yTcHg9e9LZCAeJY2cJ0r0sfyGPRiH60F-WbkyUjlAdDywI8RPdTpDYLuBmpZ_Kun-kHyTzMjeKR6R26Z4JITUS8n7Dj9X--9eNLajH6UuYD4GkjRACpsidl_8z33DlB86u_xDCMMm7HFK2oJTs8HG1fBex6enQsu0frUAJbx56DxhRvWawAysDMtLE50vaohrzkVV7Yaz4ClilwgfjQ=='
>>> key_str = 'correctstaplecorrectstaplecorrec'
>>> key_base64 = base64.b64encode(key_str.encode())
>>> key_base64
b'Y29ycmVjdHN0YXBsZWNvcnJlY3RzdGFwbGVjb3JyZWM='
>>> f = Fernet(key_base64)
>>> f
<cryptography.fernet.Fernet object at 0x7fc9bb354dc0>
>>> plain = f.decrypt(payload)
>>> plain
b"\npw = input('What\\'s the password? ')\n\nif pw == 'batteryhorse':\n  print('picoCTF{175_chr157m45_8aef58d2}')\nelse:\n  print('That password is incorrect.')\n\n"
1
2
3
➜  unpackmepy python unpackme.flag.py 
What's the password? batteryhorse
picoCTF{175_chr157m45_8aef58d2}

Flag : picoCTF{175_chr157m45_8aef58d2}

bloat.py

Can you get the flag? Run this Python program in the same directory as this encrypted flag.

1
2
3
➜  bloatpy python bloat.flag.py 
Please enter correct password for flag: dunno
That password is incorrect

Reviewing the python program, the function arg133() seems to be the place where the program is checking for user input for correct password.

1
if arg432 == a[71]+a[64]+a[79]+a[79]+a[88]+a[66]+a[71]+a[64]+a[77]+a[66]+a[68]
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
import sys
a = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ \
            "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "

def arg133(arg432):
  if arg432 == a[71]+a[64]+a[79]+a[79]+a[88]+a[66]+a[71]+a[64]+a[77]+a[66]+a[68]:
    return True
  else:
    print(a[51]+a[71]+a[64]+a[83]+a[94]+a[79]+a[64]+a[82]+a[82]+a[86]+a[78]+\
a[81]+a[67]+a[94]+a[72]+a[82]+a[94]+a[72]+a[77]+a[66]+a[78]+a[81]+\
a[81]+a[68]+a[66]+a[83])
    sys.exit(0)
    return False

def arg111(arg444):
  return arg122(arg444.decode(), a[81]+a[64]+a[79]+a[82]+a[66]+a[64]+a[75]+\
a[75]+a[72]+a[78]+a[77])

def arg232():
  return input(a[47]+a[75]+a[68]+a[64]+a[82]+a[68]+a[94]+a[68]+a[77]+a[83]+\
a[68]+a[81]+a[94]+a[66]+a[78]+a[81]+a[81]+a[68]+a[66]+a[83]+\
a[94]+a[79]+a[64]+a[82]+a[82]+a[86]+a[78]+a[81]+a[67]+a[94]+\
a[69]+a[78]+a[81]+a[94]+a[69]+a[75]+a[64]+a[70]+a[25]+a[94])

def arg132():
  return open('flag.txt.enc', 'rb').read()

def arg112():
  print(a[54]+a[68]+a[75]+a[66]+a[78]+a[76]+a[68]+a[94]+a[65]+a[64]+a[66]+\
a[74]+a[13]+a[13]+a[13]+a[94]+a[88]+a[78]+a[84]+a[81]+a[94]+a[69]+\
a[75]+a[64]+a[70]+a[11]+a[94]+a[84]+a[82]+a[68]+a[81]+a[25])

def arg122(arg432, arg423):
    arg433 = arg423
    i = 0
    while len(arg433) < len(arg432):
        arg433 = arg433 + arg423[i]
        i = (i + 1) % len(arg423)        
    return "".join([chr(ord(arg422) ^ ord(arg442)) for (arg422,arg442) in zip(arg432,arg433)])
    
arg444 = arg132()
arg432 = arg232()
arg133(arg432)
arg112()
arg423 = arg111(arg444)
print(arg423)
sys.exit(0)

So we can simply reverse engineer the password from the python interpreter as below.

1
2
3
4
>>> a = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ \
            "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "
>>> a[71]+a[64]+a[79]+a[79]+a[88]+a[66]+a[71]+a[64]+a[77]+a[66]+a[68]
'happychance'
1
2
3
4
➜  bloatpy python bloat.flag.py 
Please enter correct password for flag: happychance
Welcome back... your flag, user:
picoCTF{d30bfu5c4710n_f7w_c47f9e9c}

Flag : picoCTF{d30bfu5c4710n_f7w_c47f9e9c}

Fresh java

Can you get the flag? Reverse engineer this Java program.

The java program is loaded into ghidra.

ghidra

From the program’s logic, we can see that it is checking each character for correct password. From here we can manually reverse engineer the password.

repasswd

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  cVar3 = objectRef.charAt(0x21);
  if (cVar3 != '}') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x20);
  if (cVar3 != '0') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x1f);
  if (cVar3 != 'f') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x1e);
  if (cVar3 != '9') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x1d);
  if (cVar3 != '5') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x1c);
  if (cVar3 != 'c') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x1b);
  if (cVar3 != '6') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x1a);
  if (cVar3 != '2') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x19);
  if (cVar3 != '1') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x18);
  if (cVar3 != '_') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x17);
  if (cVar3 != 'd') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x16);
  if (cVar3 != '3') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x15);
  if (cVar3 != 'r') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x14);
  if (cVar3 != '1') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x13);
  if (cVar3 != 'u') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x12);
  if (cVar3 != 'q') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x11);
  if (cVar3 != '3') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0x10);
  if (cVar3 != 'r') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0xf);
  if (cVar3 != '_') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0xe);
  if (cVar3 != 'g') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0xd);
  if (cVar3 != 'n') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0xc);
  if (cVar3 != '1') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0xb);
  if (cVar3 != 'l') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(10);
  if (cVar3 != '0') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(9);
  if (cVar3 != '0') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(8);
  if (cVar3 != '7') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(7);
  if (cVar3 != '{') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(6);
  if (cVar3 != 'F') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(5);
  if (cVar3 != 'T') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(4);
  if (cVar3 != 'C') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(3);
  if (cVar3 != 'o') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(2);
  if (cVar3 != 'c') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(1);
  if (cVar3 != 'i') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
  cVar3 = objectRef.charAt(0);
  if (cVar3 != 'p') {
    pPVar1 = System.out;
    pPVar1.println("Invalid key");
    return;
  }
1
2
3
4
➜  freshjava java KeygenMe
Enter key:
picoCTF{700l1ng_r3qu1r3d_126c59f0}
Valid key

Flag : picoCTF{700l1ng_r3qu1r3d_126c59f0}

Bbbbloat

Can you get the flag? Reverse engineer this binary.

1
2
3
➜  Bbbbloat ./bbbbloat 
What's my favorite number? 99
Sorry, that's not it!

Using r2 we can dynamically debug the program as below.

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
➜  Bbbbloat r2 -d bbbbloat 
Process with PID 68182 started...
= attach 68182 68182
bin.baddr 0x559726213000
Using 0x559726213000
asm.bits 64
Warning: r_bin_file_hash: file exceeds bin.hashlimit
 -- Mind the trap.
[0x7fac5c90e100]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for objc references
[x] Check for vtables
[TOFIX: aaft can't run in debugger mode.ions (aaft)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x7fac5c90e100]> afll
address            size  nbbs edges    cc cost          min bound range max bound          calls locals args xref frame name
================== ==== ===== ===== ===== ==== ================== ===== ================== ===== ====== ==== ==== ===== ====
0x0000559726214160   46     1     0     1   15 0x0000559726214160    46 0x000055972621418e     1    0      1    0     8 entry0
0x0000559726216fe0 4121     1     0     1 2060 0x0000559726216fe0  4121 0x0000559726217ff9     0    0      0    1     0 reloc.__libc_start_main
0x00005597262140d0   11     1     0     1    4 0x00005597262140d0    11 0x00005597262140db     0    0      0    1     0 sym.imp.free
0x00005597262140e0   11     1     0     1    4 0x00005597262140e0    11 0x00005597262140eb     0    0      0    1     0 sym.imp.putchar
0x00005597262140f0   11     1     0     1    4 0x00005597262140f0    11 0x00005597262140fb     0    0      0    1     0 sym.imp.puts
0x0000559726214100   11     1     0     1    4 0x0000559726214100    11 0x000055972621410b     0    0      0    0     0 sym.imp.strlen
0x0000559726214110   11     1     0     1    4 0x0000559726214110    11 0x000055972621411b     0    0      0    1     0 sym.imp.__stack_chk_fail
0x0000559726214120   11     1     0     1    4 0x0000559726214120    11 0x000055972621412b     0    0      0    1     0 sym.imp.printf
0x0000559726214130   11     1     0     1    4 0x0000559726214130    11 0x000055972621413b     0    0      0    1     0 sym.imp.fputs
0x0000559726213000  341     3     2     3  158 0x0000559726213000   348 0x000055972621315c     0    0      2    0     0 loc.imp._ITM_deregisterTMCloneTable
0x0000559726214140   11     1     0     1    4 0x0000559726214140    11 0x000055972621414b     0    0      0    1     0 sym.imp.__isoc99_scanf
0x0000559726214150   11     1     0     1    4 0x0000559726214150    11 0x000055972621415b     0    0      0    0     0 sym.imp.strdup
0x0000559726214240   60     5     5     4   22 0x00005597262141c0   137 0x0000559726214249     0    0      0    0     0 entry.init0
0x0000559726214200   54     5     5     4   24 0x0000559726214200    57 0x0000559726214239     2    0      0    0     8 entry.fini0
0x00005597262140c0   11     1     0     1    4 0x00005597262140c0    11 0x00005597262140cb     0    0      0    1     0 fcn.5597262140c0
0x0000559726214190   34     4     4     4   14 0x0000559726214190    41 0x00005597262141b9     0    0      0    1     0 fcn.559726214190
0x0000559726214307  675     6     6     4  178 0x0000559726214307   675 0x00005597262145aa     8   10      2    1    88 main
[0x7fac5c90e100]> db main
[0x7fac5c90e100]> pdf@main
            ; DATA XREF from entry0 @ 0x559726214181
β”Œ 675: int main (int argc, char **argv, char **envp);
β”‚           ; var int64_t var_50h @ rbp-0x50
β”‚           ; var int64_t var_44h @ rbp-0x44
β”‚           ; var int64_t var_40h @ rbp-0x40
β”‚           ; var int64_t var_3ch @ rbp-0x3c
β”‚           ; var int64_t var_38h @ rbp-0x38
β”‚           ; var int64_t var_30h @ rbp-0x30
β”‚           ; var int64_t var_28h @ rbp-0x28
β”‚           ; var int64_t var_20h @ rbp-0x20
β”‚           ; var int64_t var_18h @ rbp-0x18
β”‚           ; var int64_t var_8h @ rbp-0x8
β”‚           ; arg int argc @ rdi
β”‚           ; arg char **argv @ rsi
β”‚           0x559726214307 b    f30f1efa       endbr64
β”‚           0x55972621430b      55             push rbp
β”‚           0x55972621430c      4889e5         mov rbp, rsp
β”‚           0x55972621430f      4883ec50       sub rsp, 0x50
β”‚           0x559726214313      897dbc         mov dword [var_44h], edi ; argc
β”‚           0x559726214316      488975b0       mov qword [var_50h], rsi ; argv
[0x7fac5c90e100]> db 0x5597262144cb
[0x7fac5c90e100]> dc
hit breakpoint at: 559726214307
[0x55972621430c]> dc
What's my favorite number? 99
hit breakpoint at: 5597262144cb
[0x5597262144cb]> dr
rax = 0x00000063
rbx = 0x5597262145b0
rcx = 0x00000000
rdx = 0x000d2c49
r8 = 0x0000000a
r9 = 0x00000000
r10 = 0x7fac5c892ac0
r11 = 0x00000000
r12 = 0x559726214160
r13 = 0x7ffec33e00b0
r14 = 0x00000000
r15 = 0x00000000
rsi = 0x000d2c49
rdi = 0x000d2c49
rsp = 0x7ffec33dff70
rbp = 0x7ffec33dffc0
rip = 0x5597262144cb
rflags = 0x00000202
orax = 0xffffffffffffffff
[0x5597262144cb]> dr rax=0x86187
0x00000063 ->0x00086187
[0x5597262144cb]> dc
picoCTF{cu7_7h3_bl047_2d7aeca1}
[0x7fac5c7da176]> 
[0x7fac5c7da176]> dc
child exited with status 0

==> Process finished

Flag : picoCTF{cu7_7h3_bl047_2d7aeca1}

unpackme

Can you get the flag? Reverse engineer this binary.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  unpackeme file unpackme-upx 
unpackme-upx: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, no section header
➜  unpackeme upx -d unpackme-upx -o unpackme
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2020
UPX 3.96        Markus Oberhumer, Laszlo Molnar & John Reiser   Jan 23rd 2020

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
   1002408 <-    379116   37.82%   linux/amd64   unpackme

Unpacked 1 file.
➜  unpackeme ./unpackme 
What's my favorite number? 223
Sorry, that's not it!

Alright time to reverse engineer the binary after unpacking.

1

2

3

4

5

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
➜  unpackeme gdb unpackme
(gdb) set disassembly-flavor intel
(gdb) disassemble main
(gdb) break main
Breakpoint 1 at 0x401e73
(gdb) break *(main+133)
Breakpoint 2 at 0x401ef8
(gdb) run
Starting program: /cases/pico2022/revEngineer/unpackeme/unpackme

Breakpoint 1, 0x0000000000401e73 in main ()
(gdb) continue
Continuing.
What's my favorite number? 99
Breakpoint 2, 0x0000000000401ef8 in main ()
rax            0x63                99
rbx            0x400530            4195632
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x7fffffffd930      140737488345392
rbp            0x7fffffffdec0      0x7fffffffdec0
rsp            0x7fffffffde70      0x7fffffffde70
r8             0xa                 10
r9             0x0                 0
r10            0x4ba400            4957184
r11            0x0                 0
r12            0x402ff0            4206576
r13            0x0                 0
--Type <RET> for more, q to quit, c to continue without paging--
(gdb) set $eax=0xb83cb 
rax            0xb83cb             754635
rbx            0x400530            4195632
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x7fffffffd930      140737488345392
rbp            0x7fffffffdec0      0x7fffffffdec0
rsp            0x7fffffffde70      0x7fffffffde70
r8             0xa                 10
r9             0x0                 0
r10            0x4ba400            4957184
r11            0x0                 0
r12            0x402ff0            4206576
r13            0x0                 0
--Type <RET> for more, q to quit, c to continue without paging--
(gdb) ni
0x0000000000401efd in main ()
0x0000000000401eff in main ()
(gdb) continue
Continuing.
picoCTF{up><_m3_f7w_ed7b0850}
[Inferior 1 (process 67587) exited normally]

Flag : picoCTF{up><_m3_f7w_ed7b0850}

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