1 Baby RE
CHALLENGE DESCRIPTION
Show us your basic skills! (P.S. There are 4 ways to solve this, are you willing to try them all?)
Maybe
Method 1:
First, we extract the given zip file:
xi@onlywans:~/hackthebox/challenges/babyReV$ 7z x Baby\ RE.zip
7-Zip 24.07 (x64) : Copyright (c) 1999-2024 Igor Pavlov : 2024-06-19
64-bit locale=en_US.UTF-8 Threads:4 OPEN_MAX:1024
Scanning the drive for archives:
1 file, 2885 bytes (3 KiB)
Extracting archive: Baby RE.zip
--
Path = Baby RE.zip
Type = zip
Physical Size = 2885
Enter password (will not be echoed):
Everything is Ok
Size: 16760
Compressed: 2885
Then we execute the binary( and we know it's a linux executable based on the output from file ) after giving it execution permissions:
xi@onlywans:~/hackthebox/challenges/babyReV$ file baby
baby: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=25adc53b89f781335a27bf1b81f5c4cb74581022, for GNU/Linux 3.2.0, not stripped
xi@onlywans:~/hackthebox/challenges/babyReV$ ./baby
Insert key:
As we can see it's asking for a key, and after guessing a random key:
xi@onlywans:~/hackthebox/challenges/babyReV$ ./baby
Insert key:
abc123
Try again later.
Now let’s statically analyze it, we are going to start with the program strings and see if we can find any strings that may help us:
xi@onlywans:~/hackthebox/challenges/babyReV$ strings baby
/lib64/ld-linux-x86-64.so.2
mgUa
libc.so.6
puts
stdin
fgets
__cxa_finalize
strcmp
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u/UH
HTB{B4BYH
_R3V_TH4H
TS_Ef
[]A\A]A^A_
Dont run `strings` on this challenge, that is not the way!!!!
Insert key:
abcde122313
Try again later.
;*3$"
GCC: (Debian 9.2.1-8) 9.2.1 20190909
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.7444
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
baby.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
_ITM_deregisterTMCloneTable
puts@@GLIBC_2.2.5
stdin@@GLIBC_2.2.5
_edata
__libc_start_main@@GLIBC_2.2.5
fgets@@GLIBC_2.2.5
__data_start
strcmp@@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
__libc_csu_init
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got.plt
.data
.bss
.comment
lots of strings there let's clean it up and go through the most obvious ones:

Now we have the flag and the password with just the strings command, let's try some dynamic analysis with ltrace
xi@onlywans:~/hackthebox/challenges/babyReV$ ./baby
Insert key:
abcde122313
HTB{B4BY_R3V_TH4TS_EZ}
ltrace

first the function fgets gets called to take input from user input then the user input is passed to strcmp which compares the input against the password abcde122313
2 You Cant C Me
CHALLENGE DESCRIPTION
Can you see me?
Lets try that
Static analysis
xi@onlywans:~/hackthebox/challenges/YouCantCMe$ file auth
auth: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, stripped
xi@onlywans:~/hackthebox/challenges/YouCantCMe$ strings auth > strings

Now we have the password, we can can simply use it when asked and get the flag easily:
xi@onlywans:~/hackthebox/challenges/YouCantCMe$ ./auth
Welcome!
m^&&fi
Uo&kUZ'ZUYUcI said, you can't c me
Nope that wasn’t the password
Dynamic Analysis
We can perform a dynamic analysis with ltrace
xi@onlywans:~/hackthebox/challenges/YouCantCMe$ ltrace ./auth
printf("Welcome!\n"Welcome!
) = 9
malloc(21) = 0xc596b0
fgets(lmao
"lmao\n", 21, 0x7fa6b25328e0) = 0xc596b0
strcmp("wh00ps!_y0u_d1d_c_m3", "lmao\n") = 11
printf("I said, you can't c me!\n"I said, you can't c me!
) = 24
+++ exited (status 0) +++
We really got the password:
xi@onlywans:~/hackthebox/challenges/YouCantCMe$ ./auth
Welcome!
wh00ps!_y0u_d1d_c_m3
HTB{wh00ps!_y0u_d1d_c_m3}
3 Baby Crypt
Baby Crypt is an Reversing challenge. Players use basic analysis to find an XOR decryption, and use known plaintext in order to uncover a key to retrieve the flag.
When run, the binary prompts the user for a key and prints out some mangled text, which changes depending on the user input
xi@onlywans:~/hackthebox/challenges/BabyCrypt$ ./baby_crypt
Give me the key and I'll give you the flag: mmmmmmh
R Xa%*h+ioin~E?cE5.bmh;
We can open the binary in a de-compiler such as Ghidra and navigate to the code browser. Here’s the decompiled output of the main() function:
undefined8 main(void)
{
char *__s;
long in_FS_OFFSET;
int local_44;
undefined8 local_38;
undefined8 local_30;
undefined8 local_28;
undefined2 local_20;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
printf("Give me the key and I\'ll give you the flag: ");
__s = (char *)malloc(4);
fgets(__s,4,stdin);
local_38 = 0x6f0547480c35643f;
local_30 = 0x28130304026f0446;
local_28 = 0x5000f4358280e52;
local_20 = 0x4d56;
for (local_44 = 0; local_44 < 0x1a; local_44 = local_44 + 1) {
*(byte *)((long)&local_38 + (long)local_44) =
*(byte *)((long)&local_38 + (long)local_44) ^ __s[local_44 % 3];
}
printf("%.26s\n",&local_38);
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
Basically, it asks for a 3-byte key then performs a XOR cipher. Since the expected output is the flag and we know the format, we can reverse the XOR cipher and get the expected key.
Let m be the plaintext byte, k the key byte and c be the ciphertext byte. XOR cipher this property
$$ c = m \oplus k \iff k = c \oplus m $$
Hence, we can take the first three bytes of the ciphertext (variable called local_38, in little endian format) and XOR them with the plaintext bytes:
$ python3 -q
>>> chr(ord('H') ^ 0x3f)
'w'
>>> chr(ord('T') ^ 0x64)
'0'
>>> chr(ord('B') ^ 0x35)
'w'
Here is the full exploit:
def xor_bytes(m_byte, k_byte):
# XOR the plaintext byte with the key byte
return m_byte ^ k_byte
def to_little_endian_bytes(key):
# Convert key to bytes and reverse for little-endian order
return key.to_bytes(8, byteorder='little')
# Original key in hexadecimal
key = 0x6f0547480c35643f
# Convert key to little-endian byte representation
little_endian_key_bytes = to_little_endian_bytes(key)
# Characters to XOR
characters = ['H', 'T', 'B']
# XOR each character's ASCII value with the corresponding key byte
results = {}
for i, char in enumerate(characters):
m_byte = ord(char)
k_byte = little_endian_key_bytes[i % len(little_endian_key_bytes)]
c_byte = xor_bytes(m_byte, k_byte)
results[char] = c_byte
# Convert XOR results back to plaintext characters
plaintext_results = {char: chr(result) for char, result in results.items()}
# Print the results
for char, result in plaintext_results.items():
print(f"Plaintext result for '{char}': {result}")
Explanation:
- XOR Operation: Each character's ASCII value is XORed with the corresponding byte from the little-endian key.
- Convert Back to Plain Text: After XORing, each result (which is a byte value) is converted back to a character using the
chr()function. - Output: The script prints the plaintext characters resulting from the XOR operation.
Example Output:
If you run the script, it will output the plaintext characters obtained from XORing 'H', 'T', and 'B' with the corresponding bytes from the little-endian version of the key 0x6f0547480c35643f.
Each XORed byte is mapped back to a character, producing the plaintext equivalent of the XOR operation.
4 Anti Flag
Anti flag is an easy Reversing challenge.Players will bypass an anti-debugging measure in order to pass a check and recover the flag
If we execute the binary, it simply prints a failure message and exits:

If its run under a tracing tool such as ltrace or strace, a different message is is printed.


The binary instead prints Well done!! and then exits. Before that, a call to ptrace() is made Using ptrace(PTRACE_TRACEME) is a common and very simple anti-debugging measure in Linux, a process may call PTRACE_TRACEME to request that its parent attach to it is for debugging. However, if a process is already debugging it will return the error EPERM. The process can check this, and exit if it fails.
Decompilatiom
If we open it in Ghidra, we will see this main function:
/* WARNING: Removing unreachable block (ram,0x00101525) */
undefined8
main(undefined8 param_1,undefined8 param_2,undefined8 param_3,undefined8 param_4,undefined8 param_5,
undefined8 param_6)
{
size_t sVar1;
long lVar2;
sVar1 = strlen(&DAT_00102011);
malloc(sVar1 << 2);
lVar2 = ptrace(PTRACE_TRACEME,0,1,0,param_5,param_6,param_2);
if (lVar2 == -1) {
puts("Well done!!");
}
else {
puts("No flag for you :(");
}
return 0;
}
Assembly code analysis
Disassembly of section .text:
00000000000010e0 <.text>:
10e0: f3 0f 1e fa endbr64
10e4: 31 ed xor ebp,ebp
10e6: 49 89 d1 mov r9,rdx
10e9: 5e pop rsi
10ea: 48 89 e2 mov rdx,rsp
10ed: 48 83 e4 f0 and rsp,0xfffffffffffffff0
10f1: 50 push rax
10f2: 54 push rsp
10f3: 4c 8d 05 c6 04 00 00 lea r8,[rip+0x4c6] # 15c0 <ptrace@plt+0x4f0>
10fa: 48 8d 0d 4f 04 00 00 lea rcx,[rip+0x44f] # 1550 <ptrace@plt+0x480>
1101: 48 8d 3d 7e 03 00 00 lea rdi,[rip+0x37e] # 1486 <ptrace@plt+0x3b6>
1108: ff 15 d2 2e 00 00 call QWORD PTR [rip+0x2ed2] # 3fe0 <ptrace@plt+0x2f10>
110e: f4 hlt
110f: 90 nop
1110: 48 8d 3d f9 2e 00 00 lea rdi,[rip+0x2ef9] # 4010 <ptrace@plt+0x2f40>
1117: 48 8d 05 f2 2e 00 00 lea rax,[rip+0x2ef2] # 4010 <ptrace@plt+0x2f40>
111e: 48 39 f8 cmp rax,rdi
1121: 74 15 je 1138 <ptrace@plt+0x68>
1123: 48 8b 05 ae 2e 00 00 mov rax,QWORD PTR [rip+0x2eae] # 3fd8 <ptrace@plt+0x2f08>
112a: 48 85 c0 test rax,rax
112d: 74 09 je 1138 <ptrace@plt+0x68>
112f: ff e0 jmp rax
1131: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
1138: c3 ret
1139: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
1140: 48 8d 3d c9 2e 00 00 lea rdi,[rip+0x2ec9] # 4010 <ptrace@plt+0x2f40>
1147: 48 8d 35 c2 2e 00 00 lea rsi,[rip+0x2ec2] # 4010 <ptrace@plt+0x2f40>
114e: 48 29 fe sub rsi,rdi
1151: 48 89 f0 mov rax,rsi
1154: 48 c1 ee 3f shr rsi,0x3f
1158: 48 c1 f8 03 sar rax,0x3
115c: 48 01 c6 add rsi,rax
115f: 48 d1 fe sar rsi,1
1162: 74 14 je 1178 <ptrace@plt+0xa8>
1164: 48 8b 05 85 2e 00 00 mov rax,QWORD PTR [rip+0x2e85] # 3ff0 <ptrace@plt+0x2f20>
116b: 48 85 c0 test rax,rax
116e: 74 08 je 1178 <ptrace@plt+0xa8>
1170: ff e0 jmp rax
1172: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0]
1178: c3 ret
1179: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
1180: f3 0f 1e fa endbr64
1184: 80 3d 85 2e 00 00 00 cmp BYTE PTR [rip+0x2e85],0x0 # 4010 <ptrace@plt+0x2f40>
118b: 75 2b jne 11b8 <ptrace@plt+0xe8>
118d: 55 push rbp
118e: 48 83 3d 62 2e 00 00 cmp QWORD PTR [rip+0x2e62],0x0 # 3ff8 <ptrace@plt+0x2f28>
1195: 00
1196: 48 89 e5 mov rbp,rsp
1199: 74 0c je 11a7 <ptrace@plt+0xd7>
119b: 48 8b 3d 66 2e 00 00 mov rdi,QWORD PTR [rip+0x2e66] # 4008 <ptrace@plt+0x2f38>
11a2: e8 d9 fe ff ff call 1080 <__cxa_finalize@plt>
11a7: e8 64 ff ff ff call 1110 <ptrace@plt+0x40>
11ac: c6 05 5d 2e 00 00 01 mov BYTE PTR [rip+0x2e5d],0x1 # 4010 <ptrace@plt+0x2f40>
11b3: 5d pop rbp
11b4: c3 ret
11b5: 0f 1f 00 nop DWORD PTR [rax]
11b8: c3 ret
11b9: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
11c0: f3 0f 1e fa endbr64
11c4: e9 77 ff ff ff jmp 1140 <ptrace@plt+0x70>
11c9: f3 0f 1e fa endbr64
11cd: 55 push rbp
11ce: 48 89 e5 mov rbp,rsp
11d1: 48 89 7d e8 mov QWORD PTR [rbp-0x18],rdi
11d5: 48 89 75 e0 mov QWORD PTR [rbp-0x20],rsi
11d9: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18]
11dd: 0f b6 00 movzx eax,BYTE PTR [rax]
11e0: 0f b6 c0 movzx eax,al
11e3: 89 45 fc mov DWORD PTR [rbp-0x4],eax
11e6: 48 8b 45 e0 mov rax,QWORD PTR [rbp-0x20]
11ea: 0f b6 10 movzx edx,BYTE PTR [rax]
11ed: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18]
11f1: 88 10 mov BYTE PTR [rax],dl
11f3: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]
11f6: 89 c2 mov edx,eax
11f8: 48 8b 45 e0 mov rax,QWORD PTR [rbp-0x20]
11fc: 88 10 mov BYTE PTR [rax],dl
11fe: 90 nop
11ff: 5d pop rbp
1200: c3 ret
1201: f3 0f 1e fa endbr64
1205: 55 push rbp
1206: 48 89 e5 mov rbp,rsp
1209: 48 83 ec 20 sub rsp,0x20
120d: 48 89 7d e8 mov QWORD PTR [rbp-0x18],rdi
1211: 48 89 75 e0 mov QWORD PTR [rbp-0x20],rsi
1215: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18]
1219: 48 89 c7 mov rdi,rax
121c: e8 7f fe ff ff call 10a0 <strlen@plt>
1221: 89 45 fc mov DWORD PTR [rbp-0x4],eax
1224: c7 45 f0 00 00 00 00 mov DWORD PTR [rbp-0x10],0x0
122b: c7 45 f4 00 00 00 00 mov DWORD PTR [rbp-0xc],0x0
1232: eb 16 jmp 124a <ptrace@plt+0x17a>
1234: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc]
1237: 48 63 d0 movsxd rdx,eax
123a: 48 8b 45 e0 mov rax,QWORD PTR [rbp-0x20]
123e: 48 01 d0 add rax,rdx
1241: 8b 55 f4 mov edx,DWORD PTR [rbp-0xc]
1244: 88 10 mov BYTE PTR [rax],dl
1246: 83 45 f4 01 add DWORD PTR [rbp-0xc],0x1
124a: 81 7d f4 ff 00 00 00 cmp DWORD PTR [rbp-0xc],0xff
1251: 7e e1 jle 1234 <ptrace@plt+0x164>
1253: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x8],0x0
125a: eb 72 jmp 12ce <ptrace@plt+0x1fe>
125c: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
125f: 48 63 d0 movsxd rdx,eax
1262: 48 8b 45 e0 mov rax,QWORD PTR [rbp-0x20]
1266: 48 01 d0 add rax,rdx
1269: 0f b6 00 movzx eax,BYTE PTR [rax]
126c: 0f b6 d0 movzx edx,al
126f: 8b 45 f0 mov eax,DWORD PTR [rbp-0x10]
1272: 8d 0c 02 lea ecx,[rdx+rax*1]
1275: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
1278: 99 cdq
1279: f7 7d fc idiv DWORD PTR [rbp-0x4]
127c: 89 d0 mov eax,edx
127e: 48 63 d0 movsxd rdx,eax
1281: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18]
1285: 48 01 d0 add rax,rdx
1288: 0f b6 00 movzx eax,BYTE PTR [rax]
128b: 0f be c0 movsx eax,al
128e: 8d 14 01 lea edx,[rcx+rax*1]
1291: 89 d0 mov eax,edx
1293: c1 f8 1f sar eax,0x1f
1296: c1 e8 18 shr eax,0x18
1299: 01 c2 add edx,eax
129b: 0f b6 d2 movzx edx,dl
129e: 29 c2 sub edx,eax
12a0: 89 d0 mov eax,edx
12a2: 89 45 f0 mov DWORD PTR [rbp-0x10],eax
12a5: 8b 45 f0 mov eax,DWORD PTR [rbp-0x10]
12a8: 48 63 d0 movsxd rdx,eax
12ab: 48 8b 45 e0 mov rax,QWORD PTR [rbp-0x20]
12af: 48 01 c2 add rdx,rax
12b2: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
12b5: 48 63 c8 movsxd rcx,eax
12b8: 48 8b 45 e0 mov rax,QWORD PTR [rbp-0x20]
12bc: 48 01 c8 add rax,rcx
12bf: 48 89 d6 mov rsi,rdx
12c2: 48 89 c7 mov rdi,rax
12c5: e8 ff fe ff ff call 11c9 <ptrace@plt+0xf9>
12ca: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1
12ce: 81 7d f8 ff 00 00 00 cmp DWORD PTR [rbp-0x8],0xff
12d5: 7e 85 jle 125c <ptrace@plt+0x18c>
12d7: b8 00 00 00 00 mov eax,0x0
12dc: c9 leave
12dd: c3 ret
12de: f3 0f 1e fa endbr64
12e2: 55 push rbp
12e3: 48 89 e5 mov rbp,rsp
12e6: 48 83 ec 40 sub rsp,0x40
12ea: 48 89 7d d8 mov QWORD PTR [rbp-0x28],rdi
12ee: 48 89 75 d0 mov QWORD PTR [rbp-0x30],rsi
12f2: 48 89 55 c8 mov QWORD PTR [rbp-0x38],rdx
12f6: c7 45 e4 00 00 00 00 mov DWORD PTR [rbp-0x1c],0x0
12fd: c7 45 e8 00 00 00 00 mov DWORD PTR [rbp-0x18],0x0
1304: 48 c7 45 f0 00 00 00 mov QWORD PTR [rbp-0x10],0x0
130b: 00
130c: 48 8b 45 d0 mov rax,QWORD PTR [rbp-0x30]
1310: 48 89 c7 mov rdi,rax
1313: e8 88 fd ff ff call 10a0 <strlen@plt>
1318: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
131c: e9 c9 00 00 00 jmp 13ea <ptrace@plt+0x31a>
1321: 8b 45 e4 mov eax,DWORD PTR [rbp-0x1c]
1324: 8d 50 01 lea edx,[rax+0x1]
1327: 89 d0 mov eax,edx
1329: c1 f8 1f sar eax,0x1f
132c: c1 e8 18 shr eax,0x18
132f: 01 c2 add edx,eax
1331: 0f b6 d2 movzx edx,dl
1334: 29 c2 sub edx,eax
1336: 89 d0 mov eax,edx
1338: 89 45 e4 mov DWORD PTR [rbp-0x1c],eax
133b: 8b 45 e4 mov eax,DWORD PTR [rbp-0x1c]
133e: 48 63 d0 movsxd rdx,eax
1341: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
1345: 48 01 d0 add rax,rdx
1348: 0f b6 00 movzx eax,BYTE PTR [rax]
134b: 0f b6 d0 movzx edx,al
134e: 8b 45 e8 mov eax,DWORD PTR [rbp-0x18]
1351: 01 c2 add edx,eax
1353: 89 d0 mov eax,edx
1355: c1 f8 1f sar eax,0x1f
1358: c1 e8 18 shr eax,0x18
135b: 01 c2 add edx,eax
135d: 0f b6 d2 movzx edx,dl
1360: 29 c2 sub edx,eax
1362: 89 d0 mov eax,edx
1364: 89 45 e8 mov DWORD PTR [rbp-0x18],eax
1367: 8b 45 e8 mov eax,DWORD PTR [rbp-0x18]
136a: 48 63 d0 movsxd rdx,eax
136d: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
1371: 48 01 c2 add rdx,rax
1374: 8b 45 e4 mov eax,DWORD PTR [rbp-0x1c]
1377: 48 63 c8 movsxd rcx,eax
137a: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
137e: 48 01 c8 add rax,rcx
1381: 48 89 d6 mov rsi,rdx
1384: 48 89 c7 mov rdi,rax
1387: e8 3d fe ff ff call 11c9 <ptrace@plt+0xf9>
138c: 8b 45 e4 mov eax,DWORD PTR [rbp-0x1c]
138f: 48 63 d0 movsxd rdx,eax
1392: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
1396: 48 01 d0 add rax,rdx
1399: 0f b6 10 movzx edx,BYTE PTR [rax]
139c: 8b 45 e8 mov eax,DWORD PTR [rbp-0x18]
139f: 48 63 c8 movsxd rcx,eax
13a2: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
13a6: 48 01 c8 add rax,rcx
13a9: 0f b6 00 movzx eax,BYTE PTR [rax]
13ac: 01 d0 add eax,edx
13ae: 0f b6 d0 movzx edx,al
13b1: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
13b5: 48 01 d0 add rax,rdx
13b8: 0f b6 00 movzx eax,BYTE PTR [rax]
13bb: 0f b6 c0 movzx eax,al
13be: 89 45 ec mov DWORD PTR [rbp-0x14],eax
13c1: 48 8b 55 d0 mov rdx,QWORD PTR [rbp-0x30]
13c5: 48 8b 45 f0 mov rax,QWORD PTR [rbp-0x10]
13c9: 48 01 d0 add rax,rdx
13cc: 0f b6 00 movzx eax,BYTE PTR [rax]
13cf: 8b 55 ec mov edx,DWORD PTR [rbp-0x14]
13d2: 31 d0 xor eax,edx
13d4: 89 c1 mov ecx,eax
13d6: 48 8b 55 c8 mov rdx,QWORD PTR [rbp-0x38]
13da: 48 8b 45 f0 mov rax,QWORD PTR [rbp-0x10]
13de: 48 01 d0 add rax,rdx
13e1: 89 ca mov edx,ecx
13e3: 88 10 mov BYTE PTR [rax],dl
13e5: 48 83 45 f0 01 add QWORD PTR [rbp-0x10],0x1
13ea: 48 8b 45 f0 mov rax,QWORD PTR [rbp-0x10]
13ee: 48 3b 45 f8 cmp rax,QWORD PTR [rbp-0x8]
13f2: 0f 82 29 ff ff ff jb 1321 <ptrace@plt+0x251>
13f8: b8 00 00 00 00 mov eax,0x0
13fd: c9 leave
13fe: c3 ret
13ff: f3 0f 1e fa endbr64
1403: 55 push rbp
1404: 48 89 e5 mov rbp,rsp
1407: 48 81 ec 30 01 00 00 sub rsp,0x130
140e: 48 89 bd e8 fe ff ff mov QWORD PTR [rbp-0x118],rdi
1415: 48 89 b5 e0 fe ff ff mov QWORD PTR [rbp-0x120],rsi
141c: 48 89 95 d8 fe ff ff mov QWORD PTR [rbp-0x128],rdx
1423: 64 48 8b 04 25 28 00 mov rax,QWORD PTR fs:0x28
142a: 00 00
142c: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
1430: 31 c0 xor eax,eax
1432: 48 8d 95 f0 fe ff ff lea rdx,[rbp-0x110]
1439: 48 8b 85 e8 fe ff ff mov rax,QWORD PTR [rbp-0x118]
1440: 48 89 d6 mov rsi,rdx
1443: 48 89 c7 mov rdi,rax
1446: e8 b6 fd ff ff call 1201 <ptrace@plt+0x131>
144b: 48 8b 95 d8 fe ff ff mov rdx,QWORD PTR [rbp-0x128]
1452: 48 8b 8d e0 fe ff ff mov rcx,QWORD PTR [rbp-0x120]
1459: 48 8d 85 f0 fe ff ff lea rax,[rbp-0x110]
1460: 48 89 ce mov rsi,rcx
1463: 48 89 c7 mov rdi,rax
1466: e8 73 fe ff ff call 12de <ptrace@plt+0x20e>
146b: b8 00 00 00 00 mov eax,0x0
1470: 48 8b 4d f8 mov rcx,QWORD PTR [rbp-0x8]
1474: 64 48 33 0c 25 28 00 xor rcx,QWORD PTR fs:0x28
147b: 00 00
147d: 74 05 je 1484 <ptrace@plt+0x3b4>
147f: e8 2c fc ff ff call 10b0 <__stack_chk_fail@plt>
1484: c9 leave
1485: c3 ret
1486: f3 0f 1e fa endbr64
148a: 55 push rbp
148b: 48 89 e5 mov rbp,rsp
148e: 48 83 ec 30 sub rsp,0x30
1492: 89 7d dc mov DWORD PTR [rbp-0x24],edi
1495: 48 89 75 d0 mov QWORD PTR [rbp-0x30],rsi
1499: c7 45 e4 00 00 00 00 mov DWORD PTR [rbp-0x1c],0x0
14a0: 48 8d 05 5d 0b 00 00 lea rax,[rip+0xb5d] # 2004 <ptrace@plt+0xf34>
14a7: 48 89 45 e8 mov QWORD PTR [rbp-0x18],rax
14ab: 48 8d 05 5f 0b 00 00 lea rax,[rip+0xb5f] # 2011 <ptrace@plt+0xf41>
14b2: 48 89 45 f0 mov QWORD PTR [rbp-0x10],rax
14b6: 48 8b 45 f0 mov rax,QWORD PTR [rbp-0x10]
14ba: 48 89 c7 mov rdi,rax
14bd: e8 de fb ff ff call 10a0 <strlen@plt>
14c2: 48 c1 e0 02 shl rax,0x2
14c6: 48 89 c7 mov rdi,rax
14c9: e8 f2 fb ff ff call 10c0 <malloc@plt>
14ce: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
14d2: b9 00 00 00 00 mov ecx,0x0
14d7: ba 01 00 00 00 mov edx,0x1
14dc: be 00 00 00 00 mov esi,0x0
14e1: bf 00 00 00 00 mov edi,0x0
14e6: b8 00 00 00 00 mov eax,0x0
14eb: e8 e0 fb ff ff call 10d0 <ptrace@plt>
14f0: 48 83 f8 ff cmp rax,0xffffffffffffffff
14f4: 75 13 jne 1509 <ptrace@plt+0x439>
14f6: 48 8d 3d 2e 0b 00 00 lea rdi,[rip+0xb2e] # 202b <ptrace@plt+0xf5b>
14fd: e8 8e fb ff ff call 1090 <puts@plt>
1502: b8 00 00 00 00 mov eax,0x0
1507: eb 44 jmp 154d <ptrace@plt+0x47d>
1509: 81 7d e4 39 05 00 00 cmp DWORD PTR [rbp-0x1c],0x539
1510: 74 13 je 1525 <ptrace@plt+0x455>
1512: 48 8d 3d 1e 0b 00 00 lea rdi,[rip+0xb1e] # 2037 <ptrace@plt+0xf67>
1519: e8 72 fb ff ff call 1090 <puts@plt>
151e: b8 00 00 00 00 mov eax,0x0
1523: eb 28 jmp 154d <ptrace@plt+0x47d>
1525: 48 8b 55 f8 mov rdx,QWORD PTR [rbp-0x8]
1529: 48 8b 4d f0 mov rcx,QWORD PTR [rbp-0x10]
152d: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18]
1531: 48 89 ce mov rsi,rcx
1534: 48 89 c7 mov rdi,rax
1537: e8 c3 fe ff ff call 13ff <ptrace@plt+0x32f>
153c: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
1540: 48 89 c7 mov rdi,rax
1543: e8 48 fb ff ff call 1090 <puts@plt>
1548: b8 00 00 00 00 mov eax,0x0
154d: c9 leave
154e: c3 ret
154f: 90 nop
1550: f3 0f 1e fa endbr64
1554: 41 57 push r15
1556: 4c 8d 3d 3b 28 00 00 lea r15,[rip+0x283b] # 3d98 <ptrace@plt+0x2cc8>
155d: 41 56 push r14
155f: 49 89 d6 mov r14,rdx
1562: 41 55 push r13
1564: 49 89 f5 mov r13,rsi
1567: 41 54 push r12
1569: 41 89 fc mov r12d,edi
156c: 55 push rbp
156d: 48 8d 2d 2c 28 00 00 lea rbp,[rip+0x282c] # 3da0 <ptrace@plt+0x2cd0>
1574: 53 push rbx
1575: 4c 29 fd sub rbp,r15
1578: 48 83 ec 08 sub rsp,0x8
157c: e8 7f fa ff ff call 1000 <__cxa_finalize@plt-0x80>
1581: 48 c1 fd 03 sar rbp,0x3
1585: 74 1f je 15a6 <ptrace@plt+0x4d6>
1587: 31 db xor ebx,ebx
1589: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
1590: 4c 89 f2 mov rdx,r14
1593: 4c 89 ee mov rsi,r13
1596: 44 89 e7 mov edi,r12d
1599: 41 ff 14 df call QWORD PTR [r15+rbx*8]
159d: 48 83 c3 01 add rbx,0x1
15a1: 48 39 dd cmp rbp,rbx
15a4: 75 ea jne 1590 <ptrace@plt+0x4c0>
15a6: 48 83 c4 08 add rsp,0x8
15aa: 5b pop rbx
15ab: 5d pop rbp
15ac: 41 5c pop r12
15ae: 41 5d pop r13
15b0: 41 5e pop r14
15b2: 41 5f pop r15
15b4: c3 ret
15b5: 66 66 2e 0f 1f 84 00 data16 cs nop WORD PTR [rax+rax*1+0x0]
15bc: 00 00 00 00
15c0: f3 0f 1e fa endbr64
15c4: c3 ret
Patching
One way of solving this issue is by changing jmp 154d (e2 28) in machine code to nop; nop (90 90), so that there is no unconditional jump:
xxd -p anti_flag | tr -d \\n | sed s/eb28/9090/g | xxd -r -p > anti_flag_patched
Another way we can open the binary in Ghidra. All strings can be viewed by navigating to Windows > Defined strings

We can see the Well done!! string in the list. Hit CTRL + SHIFT + F to look at it’s cross-references and then click on the result.

At the end of the first block, we see it calling ptrace() and checking if the result is -1 . If this is true, the binary prints Well done!!! and exits.
However, the execution proceeds if it’s not being debugged. The function compares the RBP-0x1c variable with 0x539 (1337). It goes on and prints No flag for you if this is false, else calls another function.
It's likely that this function ends up printing the flag. As the program takes no input, we will have to manually set the variable to 1337 . Note: The function FUN_001013ff is a decryption routine and need not be reversed.
Let's use GDB to debug the binary. Add a breakpoint at ptrace and run the binary.
pwndbg> b ptrace
Breakpoint 1 at 0x10d0
pwndbg> r
Starting program: /home/xi/hackthebox/challenges/Anti Flag/anti_flag
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, ptrace (request=PTRACE_TRACEME)
at ../sysdeps/unix/sysv/linux/ptrace.c:30
30 ../sysdeps/unix/sysv/linux/ptrace.c: No such file or directory.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 0x0
*RBX 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
RCX 0x0
*RDX 0x1
RDI 0x0
RSI 0x0
*R8 0x70
*R9 0x1
*R10 0x4
R11 0x0
R12 0x0
*R13 0x7fffffffdd28 —▸ 0x7fffffffe0d7 ◂— 'SYSTEMD_EXEC_PID=1935'
*R14 0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2c0 —▸ 0x555555554000 ◂— 0x10102464c457f
R15 0x0
*RBP 0x7fffffffdc00 ◂— 0x1
*RSP 0x7fffffffdbc8 —▸ 0x5555555554f0 ◂— cmp rax, -1
*RIP 0x7ffff7ec48b0 (ptrace) ◂— sub rsp, 0x68
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
► 0x7ffff7ec48b0 <ptrace> sub rsp, 0x68
0x7ffff7ec48b4 <ptrace+4> lea r8d, [rdi - 1]
0x7ffff7ec48b8 <ptrace+8> mov qword ptr [rsp + 0x38], rsi
0x7ffff7ec48bd <ptrace+13> lea r10, [rsp + 8]
0x7ffff7ec48c2 <ptrace+18> mov qword ptr [rsp + 0x40], rdx
0x7ffff7ec48c7 <ptrace+23> mov qword ptr [rsp + 0x48], rcx
0x7ffff7ec48cc <ptrace+28> mov rax, qword ptr fs:[0x28]
0x7ffff7ec48d5 <ptrace+37> mov qword ptr [rsp + 0x28], rax
0x7ffff7ec48da <ptrace+42> xor eax, eax
0x7ffff7ec48dc <ptrace+44> lea rax, [rsp + 0x70]
0x7ffff7ec48e1 <ptrace+49> cmp r8d, 3
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdbc8 —▸ 0x5555555554f0 ◂— cmp rax, -1
01:0008│-030 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
02:0010│-028 0x7fffffffdbd8 ◂— 0x100000000
03:0018│-020 0x7fffffffdbe0 ◂— 0x0
04:0020│-018 0x7fffffffdbe8 —▸ 0x555555556004 ◂— '2asdf-012=14'
05:0028│-010 0x7fffffffdbf0 —▸ 0x555555556011 ◂— 0x2a23d90c4f35c0d0
06:0030│-008 0x7fffffffdbf8 —▸ 0x5555555592a0 ◂— 0x0
07:0038│ rbp 0x7fffffffdc00 ◂— 0x1
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x7ffff7ec48b0 ptrace
1 0x5555555554f0
2 0x7ffff7de3c8a __libc_start_call_main+122
3 0x7ffff7de3d45 __libc_start_main+133
4 0x55555555510e
When the breakpoint hits, enter finish to step out of the function. This should bring us back to the function where the comparison occurs.
pwndbg> finish
Run till exit from #0 ptrace (request=PTRACE_TRACEME)
at ../sysdeps/unix/sysv/linux/ptrace.c:30
0x00005555555554f0 in ?? ()
Value returned is $1 = -1
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*RAX 0xffffffffffffffff
RBX 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
*RCX 0x7ffff7ec490a (ptrace+90) ◂— cmp rax, -0x1000 /* 'H=' */
*RDX 0x0
RDI 0x0
RSI 0x0
*R8 0xffffffff
R9 0x1
*R10 0x0
*R11 0x286
R12 0x0
R13 0x7fffffffdd28 —▸ 0x7fffffffe0d7 ◂— 'SYSTEMD_EXEC_PID=1935'
R14 0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2c0 —▸ 0x555555554000 ◂— 0x10102464c457f
R15 0x0
RBP 0x7fffffffdc00 ◂— 0x1
*RSP 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
*RIP 0x5555555554f0 ◂— cmp rax, -1
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
► 0x5555555554f0 cmp rax, -1
0x5555555554f4 jne 0x555555555509 <0x555555555509>
0x5555555554f6 lea rdi, [rip + 0xb2e]
0x5555555554fd call puts@plt <puts@plt>
0x555555555502 mov eax, 0
0x555555555507 jmp 0x55555555554d <0x55555555554d>
0x555555555509 cmp dword ptr [rbp - 0x1c], 0x539
0x555555555510 je 0x555555555525 <0x555555555525>
0x555555555512 lea rdi, [rip + 0xb1e]
0x555555555519 call puts@plt <puts@plt>
0x55555555551e mov eax, 0
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
01:0008│-028 0x7fffffffdbd8 ◂— 0x100000000
02:0010│-020 0x7fffffffdbe0 ◂— 0x0
03:0018│-018 0x7fffffffdbe8 —▸ 0x555555556004 ◂— '2asdf-012=14'
04:0020│-010 0x7fffffffdbf0 —▸ 0x555555556011 ◂— 0x2a23d90c4f35c0d0
05:0028│-008 0x7fffffffdbf8 —▸ 0x5555555592a0 ◂— 0x0
06:0030│ rbp 0x7fffffffdc00 ◂— 0x1
07:0038│+008 0x7fffffffdc08 —▸ 0x7ffff7de3c8a (__libc_start_call_main+122) ◂— mov edi, eax
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5555555554f0
1 0x7ffff7de3c8a __libc_start_call_main+122
2 0x7ffff7de3d45 __libc_start_main+133
3 0x55555555510e
We change the value of rax to 1 to bypass the check and hit ni to step.
pwndbg> set $rax=1
pwndbg> ni
0x00005555555554f4 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 0x1
RBX 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
RCX 0x7ffff7ec490a (ptrace+90) ◂— cmp rax, -0x1000 /* 'H=' */
RDX 0x0
RDI 0x0
RSI 0x0
R8 0xffffffff
R9 0x1
R10 0x0
R11 0x286
R12 0x0
R13 0x7fffffffdd28 —▸ 0x7fffffffe0d7 ◂— 'SYSTEMD_EXEC_PID=1935'
R14 0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2c0 —▸ 0x555555554000 ◂— 0x10102464c457f
R15 0x0
RBP 0x7fffffffdc00 ◂— 0x1
RSP 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
*RIP 0x5555555554f4 ◂— jne 0x555555555509
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x5555555554f0 cmp rax, -1
► 0x5555555554f4 ✔ jne 0x555555555509 <0x555555555509>
↓
0x555555555509 cmp dword ptr [rbp - 0x1c], 0x539
0x555555555510 je 0x555555555525 <0x555555555525>
0x555555555512 lea rdi, [rip + 0xb1e]
0x555555555519 call puts@plt <puts@plt>
0x55555555551e mov eax, 0
0x555555555523 jmp 0x55555555554d <0x55555555554d>
0x555555555525 mov rdx, qword ptr [rbp - 8]
0x555555555529 mov rcx, qword ptr [rbp - 0x10]
0x55555555552d mov rax, qword ptr [rbp - 0x18]
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
01:0008│-028 0x7fffffffdbd8 ◂— 0x100000000
02:0010│-020 0x7fffffffdbe0 ◂— 0x0
03:0018│-018 0x7fffffffdbe8 —▸ 0x555555556004 ◂— '2asdf-012=14'
04:0020│-010 0x7fffffffdbf0 —▸ 0x555555556011 ◂— 0x2a23d90c4f35c0d0
05:0028│-008 0x7fffffffdbf8 —▸ 0x5555555592a0 ◂— 0x0
06:0030│ rbp 0x7fffffffdc00 ◂— 0x1
07:0038│+008 0x7fffffffdc08 —▸ 0x7ffff7de3c8a (__libc_start_call_main+122) ◂— mov edi, eax
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5555555554f4
1 0x7ffff7de3c8a __libc_start_call_main+122
2 0x7ffff7de3d45 __libc_start_main+133
3 0x55555555510e
Step for a couple of times should bring us to the comparison with 1337. We can manually set the variable and bypass this check as well
pwndbg> step
0x0000555555555509 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 0x1
RBX 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
RCX 0x7ffff7ec490a (ptrace+90) ◂— cmp rax, -0x1000 /* 'H=' */
RDX 0x0
RDI 0x0
RSI 0x0
R8 0xffffffff
R9 0x1
R10 0x0
R11 0x286
R12 0x0
R13 0x7fffffffdd28 —▸ 0x7fffffffe0d7 ◂— 'SYSTEMD_EXEC_PID=1935'
R14 0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2c0 —▸ 0x555555554000 ◂— 0x10102464c457f
R15 0x0
RBP 0x7fffffffdc00 ◂— 0x1
RSP 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
*RIP 0x555555555509 ◂— cmp dword ptr [rbp - 0x1c], 0x539
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x5555555554f0 cmp rax, -1
0x5555555554f4 jne 0x555555555509 <0x555555555509>
↓
► 0x555555555509 cmp dword ptr [rbp - 0x1c], 0x539
0x555555555510 je 0x555555555525 <0x555555555525>
0x555555555512 lea rdi, [rip + 0xb1e]
0x555555555519 call puts@plt <puts@plt>
0x55555555551e mov eax, 0
0x555555555523 jmp 0x55555555554d <0x55555555554d>
0x555555555525 mov rdx, qword ptr [rbp - 8]
0x555555555529 mov rcx, qword ptr [rbp - 0x10]
0x55555555552d mov rax, qword ptr [rbp - 0x18]
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7fffffffdbd0 —▸ 0x7fffffffdd18 —▸ 0x7fffffffe0a4 ◂— '/home/xi/hackthebox/challenges/Anti Flag/anti_flag'
01:0008│-028 0x7fffffffdbd8 ◂— 0x100000000
02:0010│-020 0x7fffffffdbe0 ◂— 0x0
03:0018│-018 0x7fffffffdbe8 —▸ 0x555555556004 ◂— '2asdf-012=14'
04:0020│-010 0x7fffffffdbf0 —▸ 0x555555556011 ◂— 0x2a23d90c4f35c0d0
05:0028│-008 0x7fffffffdbf8 —▸ 0x5555555592a0 ◂— 0x0
06:0030│ rbp 0x7fffffffdc00 ◂— 0x1
07:0038│+008 0x7fffffffdc08 —▸ 0x7ffff7de3c8a (__libc_start_call_main+122) ◂— mov edi, eax
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x555555555509
1 0x7ffff7de3c8a __libc_start_call_main+122
2 0x7ffff7de3d45 __libc_start_main+133
3 0x55555555510e
pwndbg> p $rbp-0x1c
$2 = (void *) 0x7fffffffdbe4
pwndbg> set *0x7fffffffdbe4=1337
pwndbg> c
Continuing.
HTB{y0u_trac3_m3_g00d!!!}
[Inferior 1 (process 177339) exited normally]
5 IRCWare
IRCWare is an easy Reversing challenge. Players will analyse a handwritten binary which connects to a backdoored IRC server.
Solution
Running the binary, it prints out a failure message. Using strace, we can see that it attempts a connection to 127.0.0.1:8000

As can be seen, the program is trying to connect to 127.0.0.1:8000:
connect(3, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused)
The program fails because there is nothing listening on that port. Let’s use nc for that, in another terminal:

Looks like we are connected to a server
Decompilation
Now in Ghidra, we can search for strings like USER or NICK and find this function via cross-references:

void FUN_00400349() {
char cVar1;
char cVar2;
byte bVar3;
byte bVar4;
long lVar5;
long lVar6;
ulong uVar7;
long lVar8;
byte *pbVar9;
char *pcVar10;
char *pcVar11;
byte *pbVar12;
char *pcVar13;
char *pcVar14;
lVar8 = 0x1000;
do {
lVar6 = -lVar8;
pcVar10 = (char *) (lVar6 + 0x6031a9);
if (*pcVar10 == '\0') {
return;
}
if (*pcVar10 == 'P') {
lVar5 = 7;
pcVar11 = pcVar10;
pcVar13 = "PING :";
do {
if (lVar5 == 0) break;
lVar5 = lVar5 + -1;
cVar1 = *pcVar11;
cVar2 = *pcVar13;
pcVar11 = pcVar11 + 1;
pcVar13 = pcVar13 + 1;
} while (cVar1 == cVar2);
if (lVar5 == 0) {
DAT_006021aa = 0x4f;
FUN_004002fb();
lVar8 = _DAT_00601010;
_DAT_00601010 = _DAT_00601010 + 1;
if (lVar8 == 0) {
FUN_004002fb();
FUN_004002fb();
FUN_004002fb();
}
return;
}
lVar5 = 0x18;
pcVar11 = pcVar10;
pcVar13 = "PRIVMSG #secret :@pass ";
do {
if (lVar5 == 0) break;
lVar5 = lVar5 + -1;
cVar1 = *pcVar11;
cVar2 = *pcVar13;
pcVar11 = pcVar11 + 1;
pcVar13 = pcVar13 + 1;
} while (cVar1 == cVar2);
if (lVar5 == 0) {
pbVar12 = (byte *) (lVar6 + 0x6031c0);
pcVar10 = "RJJ3DSCP";
pbVar9 = &DAT_00601147;
uVar7 = 0;
break;
}
lVar5 = 0x18;
pcVar11 = pcVar10;
pcVar13 = "PRIVMSG #secret :@exec ";
do {
pcVar14 = pcVar13;
if (lVar5 == 0) break;
lVar5 = lVar5 + -1;
pcVar14 = pcVar13 + 1;
cVar1 = *pcVar11;
cVar2 = *pcVar13;
pcVar11 = pcVar11 + 1;
pcVar13 = pcVar14;
} while (cVar1 == cVar2);
if (lVar5 == 0) {
if (_DAT_00601008 == 0) {
FUN_00400485(pcVar14, "Requires password", &DAT_006021a9, 0x12);
return;
}
DAT_0060108a = lVar6 + 0x6031c0;
FUN_00400592();
return;
}
lVar6 = 0x17;
pcVar11 = pcVar10;
pcVar13 = "PRIVMSG #secret :@flag";
do {
pcVar14 = pcVar13;
if (lVar6 == 0) break;
lVar6 = lVar6 + -1;
pcVar14 = pcVar13 + 1;
cVar1 = *pcVar11;
cVar2 = *pcVar13;
pcVar11 = pcVar11 + 1;
pcVar13 = pcVar14;
} while (cVar1 == cVar2);
if (lVar6 == 0) {
if (_DAT_00601008 == 0) {
FUN_00400485(pcVar14, "Requires password", &DAT_006021a9, 0x12);
return;
}
FUN_004004df(pcVar14,pcVar10);
FUN_00400485();
FUN_004004df();
return;
}
}
lVar8 = lVar8 + -1;
if (lVar8 == 0) {
return;
}
} while (true);
LAB_00400401:
bVar3 = *pbVar12;
*pbVar9 = bVar3;
if (((bVar3 == 0) || (bVar3 == 10)) || (bVar3 == 0xd)) {
if (uVar7 == 8) {
_DAT_00601008 = _DAT_00601008 + 1;
FUN_00400485(pcVar10, "Accepted", 8, 9);
} else {
LAB_00400466:
_DAT_00601008 = 0;
FUN_00400485(pcVar10, "Rejected", uVar7, 9);
}
return;
}
if (8 < uVar7) goto LAB_00400466;
bVar4 = bVar3;
if (((0x40 < bVar3) && (bVar3 < 0x5b)) && (bVar4 = bVar3 + 0x11, 0x5a < bVar4)) {
bVar4 = bVar3 - 9;
}
if (*pcVar10 != bVar4) goto LAB_00400466;
uVar7 = uVar7 + 1;
pbVar9 = pbVar9 + 1;
pbVar12 = pbVar12 + 1;
pcVar10 = (char *) ((byte *) pcVar10 + 1);
goto LAB_00400401;
}
If we analyze the code a bit deeper, the interesting part is at the bottom. We can rename some variables and change types to make the code more readable:
LAB_00400401:
b = *p_input_;
*p_input = b;
if (((b == '\0') || (b == '\n')) || (b == '\r')) {
if (i == 8) {
_DAT_00601008 = _DAT_00601008 + 1;
FUN_00400485(expected, "Accepted", 8, 9);
} else {
LAB_00400466:
_DAT_00601008 = 0;
FUN_00400485(expected, "Rejected", i, 9);
}
return;
}
if (8 < i) goto LAB_00400466;
_b = b;
if ((('@' < b) && (b < '[')) && (_b = b + 0x11, 'Z' < _b)) {
_b = b - 9;
}
if (*expected != _b) goto LAB_00400466;
i = i + 1;
p_input = p_input + 1;
p_input_ = p_input_ + 1;
expected = (char *) ((byte *) expected + 1);
goto LAB_00400401;
}
And also, the variable named expected is set to "RJJ3DSCP" some lines above.
Basically, we have a loop over the characters of a password, which are checked one by one. If after the operations, the result byte does not match with the expected one, the program will say "Rejected":

Decryption
"RJJ3DSCP" is not the password, it is the expected result of the byte operations applied on the password. These are the byte operations:
_b = b;
if ((('@' < b) && (b < '[')) && (_b = b + 0x11, 'Z' < _b)) {
_b = b - 9;
}
Instead of reversing the operations, I will write a bit of C code using the above algorithm and try to find which input bytes give the expected result "RJJ3DSCP":
#include <stdio.h>
void main() {
int i;
char b;
char _b;
char expected[8] = "RJJ3DSCP";
for (i = 0; i < 8; i++) {
for (b = 0; b < 0x7f; b++) {
_b = b;
if ((('@' < b) && (b < '[')) && (_b = b + 0x11, 'Z' < _b)) {
_b = b - 9;
}
if (_b == expected[i]) {
putchar(b);
break;
}
}
}
putchar('\n');
}


6 Sekure Decrypt
Sekure Decrypt is an easy Reversing challenge. Players will analyze a binary along with a core dump in order to extract secrets, then reimplement the program, fixing a bug in the code
We are given a binary called dec , the C source code (src.c) and core file (core)

Source code analysis
Since we have the source code, let’s analyze it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mcrypt.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
int encrypt(void* buffer, int buffer_len, char* IV, char* key, int key_len) {
MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
int blocksize = mcrypt_enc_get_block_size(td);
if( buffer_len % blocksize != 0 ) {
return 1;
}
mcrypt_generic_init(td, key, key_len, IV);
mcrypt_generic(td, buffer, buffer_len);
mcrypt_generic_deinit (td);
mcrypt_module_close(td);
return 0;
}
int decrypt(void* buffer, int buffer_len, char* IV, char* key, int key_len) {
MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
int blocksize = mcrypt_enc_get_block_size(td);
if( buffer_len % blocksize != 0 ){
return 1;
}
mcrypt_generic_init(td, key, key_len, IV);
mdecrypt_generic(td, buffer, buffer_len);
mcrypt_generic_deinit (td);
mcrypt_module_close(td);
return 0;
}
void* read_file(char* filename, int len) {
FILE *fp = fopen(filename, "rb");
void* data = malloc(len);
fread(data, 1, len, fp);
fclose(&fp);
return data;
}
Looking at the source code, we see that it encrypts and decrypts files using the mcrypt library.
It uses AES cipher to decrypt a file called flag.enc
int main(int argc, char* argv[]) // gcc src.c -o dec -lmcrypt -ggdb
{
char* IV = "AAAAAAAAAAAAAAAA";
char *key = getenv("KEY");
int keysize = 16;
char* buffer;
int buffer_len = 16;
void *ciphertext = read_file("flag.enc", buffer_len);
decrypt(ciphertext, buffer_len, IV, key, keysize);
printf("Decrypted contents: %s\n", ciphertext);
return 0;
}
The binary is compiled with debugging symbols, which means we can refer to variables and methods by their original names. The IV is constant, while the key is read from the environment variable named KEY. The flag.enc file is read and then passed to the decrypt() function. We aren’t given the flag.enc file, which means we’ll have to dump it from the core file.
We can load up the binary and core dump in GBD and use bt to look at the backtrace

7 Hissss
We have a binary called auth :

Decompilation
If we look at the strings of the binary, we will find a lot of references to Python:
.png)
Therefore, this binary is compiled from Python. Usually, the way to extract Python code is using https://github.com/extremecoders-re/pyinstxtractor/ to obtain bytecode and then https://github.com/zrax/pycdc to tranlste Python bytecode into source code
.png)
We find compiled python bytecode in the /auth_extracted/auth.pyc file.Let’s use https://github.com/rocky/python-decompile3 to reconstruct the source code.
.png)
The resulting source code is as follows:
.png)
The input is subjected to a few constrains which we need to solve:
.png)
We can use https://github.com/Z3Prover/z3 to solve it but I will just use ChatGPT lol