September 4, 2026
Spookypass HTB Challenge
So, the Spookypass is a entry level easy challenge available in HTB for learning begineer friendly reverse engineering problem. So, lets…
By Binoydev
4 min read
So, the Spookypass is a entry level easy challenge available in HTB for learning begineer friendly reverse engineering problem. So, lets dive into it. What the problem is? and what it is telling us at first?
(Note: It's a very easy problem the writeup can be written in 500 words but I will keep it a bit lengthy because as a beginner in cybersecurity we shouldn't only follow a guide book to reach the conclusions we have to figure out how things really work in every field so for in reverse engineering I will follow the basic methodology of cybersecurity and also try to explain the process and the contents. Thank you.)
Challenge scenario:
All the coolest ghosts in town are going to a Haunted Houseparty — can you prove you deserve to get in?
This the problem statement. And there is also given a zipped file which contains our challenge file.
So, we have two choice eighter we can Download it from the gui directly or we can connect our pc with the htb openvpn by tunneling our network with htb network to access and download its content,
from our terminal.
So, lets go back to our challenge. After downloading the file, what we can see first its a zip file. So, as basic skill what we do, we first unzip it.
unzip the_zip_file_nameunzip the_zip_file_nameIt will ask for the password, for that simply go to the challenge page in htb website then you can see there is a key icon just simply click it will save the password in your clipboard, then just past it then press enter. It will now extract the content from the zip file. Now, type 'ls' command to see the content in your present directory. You can see the challenge folder or directory now. Now, shift to the directory with 'cd directory_name' . Now, you can see the file name 'pass'. As basic skill what we do, we first get a proper overview of it. For that the 1st command we use is,
┌──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ file pass
pass: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3008217772cc2426c643d69b80a96c715490dd91, for GNU/Linux 4.4.0, not stripped┌──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ file pass
pass: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3008217772cc2426c643d69b80a96c715490dd91, for GNU/Linux 4.4.0, not strippedNow, for solving the problem we need to understand specific detail about the file.
ELF 64-bit LSB PIE executable, x86-64, dynamically linked, not strippedELF 64-bit LSB PIE executable, x86-64, dynamically linked, not strippedThese are the things we have to understand to go further.
Important information:
1. ELF
→ It is a Linux binary.
We know we can use these commands and tools:
gdb
objdump
ghidra
radare2
nm
stringsgdb
objdump
ghidra
radare2
nm
strings2. 64-bit x86–64
→ It is a 64-bit binary.
Important for exploitation:
- Registers are:
RAX
RBX
RIP
RSP
RBPRAX
RBX
RIP
RSP
RBP- Addresses are 8 bytes.
Example:
0x4011960x4011963. LSB
→ Little Endian.
When writing addresses in exploits, bytes are reversed.
Example:
Address:
0x4011960x401196Stored as:
96 11 40 0096 11 40 004. PIE enabled
→ Addresses are randomized.
Because of ASLR:
Before:
win() = 0x401196win() = 0x401196After running:
win() = 0x555555555196win() = 0x555555555196For exploitation:
- Need an address leak
- Cannot directly jump to fixed addresses
5. Dynamically linked
→ Uses external libraries.
Example:
printf()
puts()
strcmp()
system()printf()
puts()
strcmp()
system()come from:
libc.so.6libc.so.6Important for Pwn:
- libc leaks
- ret2libc attacks
- finding gadgets
6. Interpreter
/lib64/ld-linux-x86-64.so.2/lib64/ld-linux-x86-64.so.2→ The program uses Linux's dynamic loader to start.
Usually not important for solving.
7. Not stripped
→ The binary still contains function names.
This is very useful.
You may see:
main
check_password
win
validatemain
check_password
win
validateinstead of:
sub_401200
sub_401300sub_401200
sub_401300Makes RE (reverse engineering) easier.
Then for further information about the challenge we use 'checksec'. Now, What is checksec? Why it is used for? what can we find by using it? these are the common question we faced. So, simply I will write about it.
checksec is a tool used in binary exploitation (pwn), reverse engineering, and security analysis to check what security protections (mitigations) are enabled in a compiled Linux executable (ELF binary). When you get a CTF pwn binary, the first thing you usually do is run checksec because it tells you how the binary is protected and what exploitation techniques may work.
┌──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ checksec --file=pass
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 31 Symbols No 0 2 pass┌──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ checksec --file=pass
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 31 Symbols No 0 2 passYou can check the details also in internet what each details means. So, I will now skip it because it is getting too long as a beginner friendly ctf problem. The details I am adding here to get basic knowledge about reverse and PWN challenges.
So, in my case after checking the file info by the file command I usually open the file to see its content. By
cat passcat passIt will give use the output full of garbage value, which can't be readable. Then we use next command to make it human readable form. By using strings command,
strings passstrings passOutput
──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ strings pass
/lib64/ld-linux-x86-64.so.2
fgets
stdin
puts
__stack_chk_fail
__libc_start_main
__cxa_finalize
strchr
printf
strcmp
libc.so.6
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u3UH
Welcome to the
[1;3mSPOOKIEST
[0m party of the year.
Before we let you in, you'll need to give us the password:
s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5
Welcome inside!
You're not a real ghost; clear off!
;*3$"
GCC: (GNU) 14.2.1 20240805
GCC: (GNU) 14.2.1 20240910
main.c
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
puts@GLIBC_2.2.5
stdin@GLIBC_2.2.5
_edata
_fini
__stack_chk_fail@GLIBC_2.4
strchr@GLIBC_2.2.5
printf@GLIBC_2.2.5
parts
fgets@GLIBC_2.2.5
__data_start
strcmp@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
_end
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@GLIBC_2.2.5
_init
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.got.plt
.data
.bss
.comment──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ strings pass
/lib64/ld-linux-x86-64.so.2
fgets
stdin
puts
__stack_chk_fail
__libc_start_main
__cxa_finalize
strchr
printf
strcmp
libc.so.6
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u3UH
Welcome to the
[1;3mSPOOKIEST
[0m party of the year.
Before we let you in, you'll need to give us the password:
s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5
Welcome inside!
You're not a real ghost; clear off!
;*3$"
GCC: (GNU) 14.2.1 20240805
GCC: (GNU) 14.2.1 20240910
main.c
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
puts@GLIBC_2.2.5
stdin@GLIBC_2.2.5
_edata
_fini
__stack_chk_fail@GLIBC_2.4
strchr@GLIBC_2.2.5
printf@GLIBC_2.2.5
parts
fgets@GLIBC_2.2.5
__data_start
strcmp@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
_end
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@GLIBC_2.2.5
_init
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.got.plt
.data
.bss
.comment"Before we let you in, you'll need to give us the password: s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5 Welcome inside!"
Here we discover a secret string and info s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5 which is giving hint of password by this we can get access to inside. For confirming it we need to now run the file
for that we have to see 1st is the file is executable or not
for that you can check by "ls -alps". By that you can see the file permission if it has "rx" both permission you just run it by typing.
./pass./passIf the file only has 'r' permission means it only has read permission you have to modify it to get 'x' executable file. For that we can type
chmod +x passchmod +x passNow it has both read and executable permission. Now you have to run it. By
┌──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ ./pass
Welcome to the SPOOKIEST party of the year.
Before we let you in, you'll need to give us the password: s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5
Welcome inside!
HTB{un0bfu5c4t3d_5tr1ng5}┌──(dev㉿kali)-[~/Htb/Spookypass/rev_spookypass]
└─$ ./pass
Welcome to the SPOOKIEST party of the year.
Before we let you in, you'll need to give us the password: s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5
Welcome inside!
HTB{un0bfu5c4t3d_5tr1ng5}So, this is the flag . HTB{un0bfu5c4t3d_5tr1ng5}