Recon 00 :

just go to the website and add the robots.txt , it goes something like this :
https://hackycorp.com/robots.txt
and we found the key :
af9c328a-02b4-439d-91c6-f46ab4a0835b


Recon 01 :

Really?
it just too simple add some thing after the url that you know is BS. something like this :
https://hackycorp.com/opihrgweopuirgne
and then you got the key :
aeaee57f-2a82-41da-bc4c-d081c8cddfc8


Recon 02 :

Finally, some thing cool. for this level you should first see the refrences to learn what is the security.txt so when we see in the refrences it say that in most websites if its standard it most be in the address .well-known/security.txt, so we go for it:
https://hackycorp.com/.well-known/security.txt
and then we got the key for next level :
99685e30-7061-4ac0-83bf-4ccc0409faac


Recon 03 :

kind of tricky. first try was to try and go to the assets but there was not support any directory listing , for example if we visit this :
https://assets.hackycorp.com/img
we get access denied, so we should try to get other directory. after reading the code we see that there use this for there logo :
images/logo.png
so we tried this :
https://hackycorp.com/images/
we get a directory and there we have a file names key.txt so when we visit that we get the key for next level :
93790afa-6985-47fd-b564-aa7ba59ed6a9


Recon 04 :

for this level we use there hints to visit the /admin , so when we visit this url :
https://hackycorp.com/admin/
we get the key for next level :
ad1d44d6-ab73-4640-8291-c5bf2343e2a5


Recon 05 :

for this level we use some fuzzing tool. my favorite ffuf. and for the wordlist we visit this Seclist.
one of the wordlists under the fuzzing is common.txt and we use that, using this ffuf command :

ffuf -u https://hackycorp.com/FUZZ -w common.txt -mc 200,301,302

output of the code :

.well-known/security.txt [Status: 200, Size: 156, Words: 24, Lines: 4, Duration: 98ms]
admin                   [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 158ms]
images                  [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 109ms]
index.html              [Status: 200, Size: 16011, Words: 5888, Lines: 278, Duration: 119ms]
robots.txt              [Status: 200, Size: 121, Words: 14, Lines: 7, Duration: 117ms]
startpage               [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 109ms]
:: Progress: [4750/4750] :: Job [1/1] :: 135 req/sec :: Duration: [0:00:23] :: Errors: 0 ::

only directory we did not visit until not is startpage so we go to this url :
https://hackycorp.com/startpage/
and we get this key :
498621b0-17fe-4ebb-8324-3de7743fea51


Recon 06 :

in web servers can have multiple websites in them. a web server has only one IP then in that we server we can set multiple websites and how the web server open the right website for us? using header. if we send a request directly to the ip of the web server without any header web server show us the default page that we can call vhost too. for this first we need to find the IP address. we use this command :

dig hackycorp.com

then we get the IP :
51.158.147.132
and when we send a request to it :

curl http://51.158.147.132

we get this output :

<h1>Well done! You solved recon_06 </h1>
 
The key for this exercise is 5cf83b5d-eb6c-4eee-af6c-945f9aed8dfd

so the key is :
5cf83b5d-eb6c-4eee-af6c-945f9aed8dfd
we could just visit the http://51.158.147.132 in our browser, its the same thing.


Recon 07 :

like the past level but this time We bypass TLS certificate validation to reach the default TLS virtual host.-k lets you bypass TLS certificate checks, and a fake Host header forces the web server to fall back to its default virtual host after TLS is established.Because the certificate presented by the default vhost does not match the IP address, curl would normally abort the connection unless -k is used.
so for this we use this command :

curl -k https://51.158.147.132 -H "Host: random"

and output :

<h1>Well done! You solved recon_07</h1>
 
The key for this exercise is 23eafa56-6d55-4b78-8307-24e7dc2ce5e6

so the key is :
23eafa56-6d55-4b78-8307-24e7dc2ce5e6


Recon 08 :

for this level first we need to find the certificate then encode and find all the alt names and then try to connect to one of those alt names. lets go.
first we can find SSL using openssl but we need to decode it too so we use this command :

openssl s_client -connect hackycorp.com:443 -servername hackycorp.com \
  | openssl x509 -noout -ext subjectAltName
  • openssl s_client fetches the certificate

  • openssl x509 -text decodes it

  • -noout hides raw PEM output
    then we have this output :

depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R13
verify return:1
depth=0 CN = hackycorp.com
verify return:1
X509v3 Subject Alternative Name: 
    DNS:66177e3f25e3ea0713807b1dc5f0b9df.hackycorp.com, DNS:hackycorp.com, DNS:www.hackycorp.com

this URL looks interesting 66177e3f25e3ea0713807b1dc5f0b9df.hackycorp.com so we send a request to it :

curl https://66177e3f25e3ea0713807b1dc5f0b9df.hackycorp.com

we get this output :

<h1>Well done! You solved   recon_08</h1>
 
The key for this exercise is: 1763ec4f-8467-47f7-9a80-6de93a1a2253

and the key is :
1763ec4f-8467-47f7-9a80-6de93a1a2253


Recon 09 :

This level is easy. objective is very clear we should check the header.
so we use this curl command :

curl -I https://hackycorp.com
  • -I is mean we send a HEAD request, with this we only get the header, what we want.
    the output is this :
HTTP/1.1 200 Connection established
 
HTTP/1.1 200 OK
Server: nginx
Date: Sat, 03 Jan 2026 10:19:52 GMT
Content-Type: text/html
Content-Length: 16011
Last-Modified: Tue, 31 Mar 2020 03:12:16 GMT
Connection: keep-alive
ETag: "5e82b510-3e8b"
pentesterlab_recon_09: 99d0738b-1e52-4a00-8885-b15894b2c79e
Accept-Ranges: bytes

so the key is :
99d0738b-1e52-4a00-8885-b15894b2c79e


Recon 10 :

this one is kind of tricky, it says that in subdomain that gives us has the key in color red.
it suggest a tool that they dont work really. beucase of that i had this idea to write a python code that go to every subdomain and donwload the logo.png , they put the key on that and after check the downloaded logoes we could find our key. this is our code :

import requests
from pathlib import Path
 
# Generate hosts
hosts = [f"0x{i:02x}.a.hackycorp.com" for i in range(256)]
 
output_dir = Path("logos")
output_dir.mkdir(exist_ok=True)
 
for host in hosts:
    url = f"http://{host}/logo.png"
    try:
        r = requests.get(
            url,
            timeout=5,
            verify=False,
            proxies={"http": "", "https": ""}
        )
        print(f"{host} -> {r.status_code} {r.headers.get('Content-Type')}")
        if r.status_code == 200 and "image" in (r.headers.get("Content-Type") or ""):
            file_path = output_dir / f"{host}.png"
            file_path.write_bytes(r.content)
            print(f"[+] Saved {file_path}")
    except requests.RequestException as e:
        print(f"[!] {host} failed: {e}")

so when we find the red images we can extract the key :
483f8b15-e4a8-4387-b052-4b2204c7eb69


Recon 11 :

for this level we need to find out a vhost that has no DNS resolve. for this first we can use ffuf to find the right vhost in host header then we can access it. the lesson of this lab is You can bypass DNS resolution entirely by manipulating the Host header.
but first look at this :

❯ curl https://hackycorp.com -H "Host: random.hackycorp.com"
<h1>Well done! You solved recon_07</h1>
 
The key for this exercise is 23eafa56-6d55-4b78-8307-24e7dc2ce5e6

as you can see many header would return this for recon lab seven so we should filter this out. for this goal we use -fr in ffuf this would accept a regex and filter that out.
so our command is this :

ffuf -w SecLists/Discovery/Web-Content/common.txt -u https://hackycorp.com -H "Host: FUZZ.hackycorp.com" -fr recon_07

and the output :

 :: Method           : GET
 :: URL              : https://hackycorp.com
 :: Wordlist         : FUZZ: /home/parhamf/owasp/wordlist/SecLists/Discovery/Web-Content/common.txt
 :: Header           : Host: FUZZ.hackycorp.com
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Regexp: recon_07
________________________________________________
 
ADMIN                   [Status: 200, Size: 108, Words: 12, Lines: 4, Duration: 98ms]
Admin                   [Status: 200, Size: 108, Words: 12, Lines: 4, Duration: 102ms]
admin                   [Status: 200, Size: 108, Words: 12, Lines: 4, Duration: 106ms]
www                     [Status: 200, Size: 16011, Words: 5888, Lines: 278, Duration: 102ms]
:: Progress: [4750/4750] :: Job [1/1] :: 116 req/sec :: Duration: [0:00:42] :: Errors: 0 ::
 

so when we send request to each of the admins we get same response :

curl https://hackycorp.com -H "Host: admin.hackycorp.com"
<h1>Well done! You solved recon_11 </h1>
 
The key for this exercise is e4599fa9-1cc4-4916-a394-ce455a954d86

so the key is :
e4599fa9-1cc4-4916-a394-ce455a954d86


Recon 12 :

its a simple level the lesson is In load-balanced systems, inconsistencies are vulnerabilities — and repetition reveals them.
so its good to some times send multiple requests.
after sending some

curl http://balancer.hackycorp.com/

we get this :

<h1>Well done! You solved recon_12 </h1>
 
The key for this exercise is 29e5c97c-7230-46ae-937c-6c56ff33b84f

and the key is :
29e5c97c-7230-46ae-937c-6c56ff33b84f

if you don’t want to send the curl manually you can use this :

for i in $(seq 0 10); do curl http://balancer.hackycorp.com/ ;done

Recon 13 :

for this level we need to find TXT record, its a kind of DNS record. for this we can use dig command :

dig TXT key.z.hackycorp.com

in the output we can see this :

;; ANSWER SECTION:
key.z.hackycorp.com.	7194	IN	TXT	"9f883f22-6ea5-4631-bbe8-95841ad63f56"

we can use +short in the dig command to directly get the key :
9f883f22-6ea5-4631-bbe8-95841ad63f56


Recon 14 :

this level is DNS zone transfer (AXFR).
if an authoritative DNS server allows AXFR to anyone, you can dump the entire zone (A, NS, MX, TXT, etc.) in one request — instant recon and often flags in TXT records.
A DNS zone is a portion of the DNS namespace that is managed by a specific authoritative DNS server.
AXFR (Authoritative Zone Transfer) is a DNS operation used to transfer the entire DNS zone from one DNS server to another.
This domain is vulnerable because its authoritative DNS server allows unrestricted AXFR, leaking the entire DNS zone to anyone on the internet.

we can use this command :

dig axfr z.hackycorp.com @z.hackycorp.com
  • dig — DNS query tool.
  • axfr — request a full zone transfer (AXFR).
  • z.hackycorp.com — the DNS zone you want to dump.
  • @z.hackycorp.com — query this authoritative DNS server (use its name/IP as the server).

output :

; <<>> DiG 9.18.39 <<>> axfr z.hackycorp.com @z.hackycorp.com
;; global options: +cmd
z.hackycorp.com.    604800  IN  SOA  ns1.hackycorp.com. ns1.hackycorp.com. 2 604800 86400 2419200 604800
z.hackycorp.com.    604800  IN  NS   z.hackycorp.com.
z.hackycorp.com.    604800  IN  A    51.158.147.132
key.z.hackycorp.com. 604800 IN  TXT  "9f883f22-6ea5-4631-bbe8-95841ad63f56"
recon_14.z.hackycorp.com. 604800 IN TXT "e5fce970-6d94-43c1-bdd5-a06c2b235f9c"
z.hackycorp.com.    604800  IN  SOA  ns1.hackycorp.com. ns1.hackycorp.com. 2 604800 86400 2419200 604800
;; XFR size: 6 records

we can use +short in the dig command to directly get the key :
e5fce970-6d94-43c1-bdd5-a06c2b235f9c


Recon 15 :

This level is the next step of the previous one. It’s still about DNS zone transfers, but with an important twist: internal zones.
A public DNS server can sometimes be tricked into leaking internal DNS zones if it is authoritative for them or misconfigured.
Even though a zone is called internal (int), it does not automatically mean private.
If:

  • a publicly reachable nameserver
  • is authoritative for an internal zone
  • and allows AXFR
    then anyone can dump that internal zone.
    This domain is vulnerable because a public authoritative DNS server allows unrestricted AXFR on an internal zone, leaking internal infrastructure data.
    for this level we can use this command :
dig axfr int @z.hackycorp.com

int — the internal DNS zone name
others are the same as the previous level.
the output is :

; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> axfr int @z.hackycorp.com
;; global options: +cmd
int.			604800	IN	SOA	int. internals. 2 604800 86400 2419200 604800
int.			604800	IN	NS	int.
int.			604800	IN	A	127.0.0.1
recon_15.int.		604800	IN	TXT	"b55b45a8-63b1-42f7-bd12-a36219ff883d"
int.			604800	IN	SOA	int. internals. 2 604800 86400 2419200 604800
;; Query time: 102 msec
;; SERVER: 51.158.147.132#53(z.hackycorp.com) (TCP)
;; WHEN: Tue Jan 06 13:39:43 +0330 2026
;; XFR size: 5 records (messages 1, bytes 229)

so they key is :
b55b45a8-63b1-42f7-bd12-a36219ff883d


Recon 16 :

for this level we need to find the bind version that used by the DNS server. for this level we use this command :

dig @<server_ip> version.bind CH TXT

for finding the host IP address we use dig , we did it before so we directly use the IP in the command.

dig @51.158.147.132 version.bind CH TXT

the output :

; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @51.158.147.132 version.bind CH TXT
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2017
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available
 
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 001143b4d569e181f8296ef2695ce12cad9ea60786392ae8 (good)
;; QUESTION SECTION:
;version.bind.			CH	TXT
 
;; ANSWER SECTION:
version.bind.		0	CH	TXT	"4e5e76e1-728a-49be-aea8-4591ba11e588"
 
;; AUTHORITY SECTION:
version.bind.		0	CH	NS	version.bind.
 
;; Query time: 87 msec
;; SERVER: 51.158.147.132#53(51.158.147.132) (UDP)
;; WHEN: Tue Jan 06 13:47:16 +0330 2026
;; MSG SIZE  rcvd: 132

we can use the +short too, the key is :
4e5e76e1-728a-49be-aea8-4591ba11e588


Recon 17 :

easy. search hackycorp github on google then you have the organization profile and then go to the test1 repository and you can find the last developer name and you got the key :
d0fad5ef-ebb2-467c-8868-34e3cf4878b4
the github link : https://github.com/hackycorp/test1


Recon 18 :

when you go organization profile in people tab there is one developer in there public repository you can see a test repository then when you open in it, in the TEST file you can see they key :
80cb2045-c8bf-4357-8931-a28dd0f3fbb9


Recon 19 :

for this level we need to check .patch url for the git commit hash.
go to the repo7 in the commits open all of them and add .patch at the end then you see a page.
in the second commit .patch page :
you can see a different email :

From 98b4472d5e46af145968345b262bc930c4b8c6e3 Mon Sep 17 00:00:00 2001
From: Hacky Dev <9590c69b-f9d0-469d-9475-827bf0e1126e@hackycorp.com>
Date: Wed, 18 Nov 2020 10:49:08 +1100
Subject: [PATCH] Another test
 
---
README.md | 1 +
1 file changed, 1 insertion(+)
 
diff --git a/README.md b/README.md
index 0527e6b..33d0227 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
This is a test
+This is a another test

and there is you key :
9590c69b-f9d0-469d-9475-827bf0e1126e


Recon 20 :

easy. just go to repo3 check the branches and there is your key :
08be82ba-e5fd-4fae-b2c2-272a18d31f80


Recon 21 :

this time as the previous level you go to repo4 and then in the other branch you can see a file names KEY in that you have the key :
a60b4aee-642a-483b-9262-ccfc2ed46f0d


Recon 22 :

for this level the manual way is too hard , too many commits and files. we can make it lot easier.
first clone the repo :

git clone https://github.com/hackycorp/repo9.git

the go to the repo9 using cd repo9.
now lets play, we can use this git command to check which files has been deleted.

git log --diff-filter=D --summary

result of this command :

commit e8fec2d079cf9bfdf782a9ce4aab8ae8ce947548
Author: Hacky Dev <dev@hackycorp.com>
Date:   Wed Nov 18 11:11:56 2020 +1100
 
    Another test
 
 delete mode 100644 KEY.txt

so we found the file name and the commit that file has been deleted now easily we can access the file using this command :

git show "e8fec2d079cf9bfdf782a9ce4aab8ae8ce947548^":"KEY.txt"

there is one catch here the ^ mean find the file from parent commit we use that because the gives the command by log command is the commit that file is deleted so if we want the key in that commit its not there its in the parent comment.
and we have this key :
3ee505c2-8aa9-4d5e-810e-921778dce1e6


Recon 23 :

check the commits and in one of them there is the message and in that we have the key :
5c75cfe9-52dd-475b-8cfa-7ffc492abeca


Recon 24 :

check the page code you can see the assets would load from this url :
assets.hackycorp.com
so open this link now :
assets.hackycorp.com/key.txt
and there it is you have the key :
e94ab8a5-b0c1-4559-8bc7-cae2e53b10e0


Recon 25 :

for this level you need a aws account if you like me cant have an aws account directly use this key :
ff360948-c048-4f0c-a302-e806c50192d9


Recon 26 :

check out the source of the page and in the script.js you can find the key, the url :
view-source:https://assets.hackycorp.com/js/script.js
and the key :
d6b75269-97a3-44de-be32-fff0dd55e7ef