{"id":2186,"date":"2016-02-07T19:20:44","date_gmt":"2016-02-07T19:20:44","guid":{"rendered":"https:\/\/zed.inguardians.com\/?p=2186"},"modified":"2019-02-07T20:15:30","modified_gmt":"2019-02-07T20:15:30","slug":"grc-transmission-analysis-getting-to-the-bytes","status":"publish","type":"post","link":"https:\/\/zed.inguardians.com\/blog\/grc-transmission-analysis-getting-to-the-bytes\/","title":{"rendered":"GRC Transmission Analysis: Getting To the Bytes"},"content":{"rendered":"
Post Author: Don C. Weber [Twitter:\u00a0@cutaway<\/a>] I have not picked up my\u00a0HackRF Jawbreaker<\/a>\u00a0in a while (Figure 0x0). Family and billable work trump side projects. Lucky for me\u00a0Tom Liston<\/a>\u00a0and I started teaching the\u00a0Assessing and Exploiting Control Systems<\/a>class which leverages the\u00a0Samurai Project’s Security Testing Framework for Utilities (SamuraiSTFU)<\/a>. I say \u201clucky\u201d because I have a few updates I want to work into the courseware that center around improving the\u00a0GNU Radio Companion (GRC)<\/a>\u00a0frequency analysis labs. Even with the SamuraiSTFU updates I still found myself busy. I kept putting this off until\u00a0Jay Radcliffe<\/a>\u00a0asked me to take another look at a radio capture he had grabbed from his insulin monitor\/pump setup. He wanted to see if we could use GRC pull the transmitted data out of the air and into a file as I had done a couple months before with RFcat.<\/p>\n Figure 0x0: HackRF Jawbreaker<\/p>\n Both of these projects had a similar issue: we were having difficulty moving from the captured radio transmission to actual demodulated data representing a \u201cpacket\u201d of bytes. There are several reasons for this predicament, but the biggest issue is the recent advances to GRC. The rapid development and growth of the GRC code over the last year has been staggering. All of my old GRC files use blocks that are listed as \u201cOld\u201d or the blocks that do not appear in the main GRC window at all. The most frustrating case, of course, is when the blocks don\u2019t appear at all because I have to try to remember what I was trying to accomplish a year ago. Imagine opening up a script you wrote a year ago (one you didn\u2019t really fully understand at the time) only to find out that fifty percent of the functions had been deleted, seemingly at random.<\/p>\n Another general issue related to proper signal processing is that each block has its own parameters that are specific to efficient processing of the signal into a demodulated state. For those of us who are not radio engineers and do not work with GRC every day, understanding these parameters is extremely difficult. If you don\u2019t understand exactly what they do, how can you know how some of these parameter values are obtained or modified? Let\u2019s face it, there is a LOT of math involved with frequency analysis and demodulation. Fortunately, tools like GRC exist to do the majority of the difficult math for us. However, many of these math functions require very specific values so that the results of the computations are accurate for the specific signals being analyzing.<\/p>\n Like everyone else, my family and billable work issues never let up. Thus, I found myself, as most of us do, working deep into the night on these \u201cside projects.\u201d Here are a few things I learned \u2013 by asking questions, reading blogs, using default settings, and (in true hacker fashion) guessing through trial-and-error.<\/p>\n Before we start, I have created a white paper for those people who are impatient, do not like the conversational tone of a blog post, or want to have this information in a document to read and pass around:Converting Radio Signals to Data Packets<\/a>. Additionally, for quick reference, I will be using a tool called\u00a0GRC Bit Converter<\/a>\u00a0to help analyze and print the captured data.<\/p>\n When using a HackRF or one of the many RTL-SDR dongles there is a large spike at the center frequency to which the radio has been tuned. This is the Direct Current (DC) spike (demonstrated using\u00a0SDR#<\/a>\u00a0in Figure 0x1), that occurs naturally in radios that have not specifically accounted for this spike via hardware \/ firmware. The HackRF team does a great job explaining why this occurs and what can be done with it in their website\u2019s\u00a0Frequently Asked Questions (FAQ)<\/a>.<\/p>\n Figure 0x0: HackRF Jawbreaker’s DC Spike<\/p>\n As described in the HackRF FAQ, the DC spike can simply ignore it. However, because I have had a hard time successfully demodulating the signals recently, I want my data to be as clean as possible (yes, I am probably a little naive, but learning this also method helps when I \u201cdo\u201d need it).<\/p>\n To avoid the DC Spike, I like to create my captures by leveraging the \u201cDC Offset\u201d method. Capturing with an offset is easy enough to understand and easy to accomplish with the currently available GRC blocks. The challenge here is to select an offset that moves our DC Spike outside of our source\u2019s transmitted signal while still staying within the bandwidth that is being captured. There are two methods can be leveraged to determine this offset. The first is to conduct data sheet analysis to determine the radio and devices capabilities. These documents will outline \u201cChannel Spacing.\u201d The channel spacing is the distance between the center frequencies of two transmission areas configurable by the radio. While this helps, and is often enough information to adjust for the DC Spike, the channel spacing is not necessarily related to the size of the transmission. We see this in Wi-Fi which has fourteen (14) channels but the transmission of a wireless adapter will engulf approximately six (6) of those channels. To compensate for this possibility I use spectrum analysis software, as shown in Figure 0x2.<\/p>\n Figure 0x2: DC Spike Inside TX Signal<\/p>\n The spectrum analyzer allows me to visually select a frequency in an area outside the transmission. Once I have selected a frequency, I note the distance between them and configure my GRC variable blocks appropriately. In this example I will add a variable block named \u201cchannel_spacing.\u201d This allows me to configure the Frequency Offset in another variable block, named \u201cfreq_offset\u201d, with the equation: “(channel_spacing \/ 2) * (channel_spacing * .1)<\/i>“. Dividing the channel spacing by two gives me the distance from the center frequency to the edge of the transmission. Using this number should move the DC Spike to the very edge of the transmission. Adding an additional 10 percent to this offset \u201cshould\u201d move it completely outside the transmission. Figure 0x3 demonstrates the \u201cfreq_offset\u201d variable block configuration and Figure 0x4 shows how it is implemented within the source block.<\/p>\n Figure 0x3: GRC “freq_offset” Variable Block Configuration<\/p>\n \n Figure 0x4: GRC “osmocom Source” Block Configuration<\/p>\n Once this is all configured, each of the blocks in the primary GRC window will display the computed values after doing the math for us. Each of these values is shown in Figure 0x5.<\/p>\n Figure 0x5: GRC Capture Configuration<\/p>\n When this GRC script is run the Top Block will display the location of DC spike in relation to the transmitted signal. Figure 0x6 shows how this will appear in a spectrum analyzer.<\/p>\n <\/center><\/p>\n Now that the DC Spike has been addressed (or not), I concentrate on processing the data transmission itself. The basic concept is to \u201czero in\u201d on the transmission and isolate it from any other signals. I used to do this using a Low Pass Filter (LPF) block (more on that in a moment). The LPF takes several parameters, and we can spend a lot of time delving into each of them. For brevity sake, I\u2019ll just explain the ones that I use the most.<\/p>\n The first variable I consider configuring is the \u201cDecimation\u201d parameter. Decimation provides a mechanism to modify the sampling rate of the incoming signal. My understanding is that Decimation is particularly valuable when taking a transmitted signal and modifying it for output as an audio signal. The best way to leverage this parameter is to use the same equation-method that we used to implement the frequency offset. Begin by specifying the input sampling rate, which is usually automatically identified by the \u201csample_rate\u201d variable block, and then dividing by the intended (a.k.a output) sampling rate. Configured the Decimation parameter with this equation will result in this block outputting our signal with our intended output sampling rate. For this current example, however, there is no need to modify the sampling rate. Therefore, I simply check to make sure this parameter is set to a value of \u201c1\u201d which indicates no change. Not decimating also helps avoid any issues associated with breaking the Nyquist\u2013Shannon sampling theorem rule. This rule simply states that a signal must be sampled at twice the data rate to avoid data lose.<\/p>\n The first value I actually change in this block is the \u201cWindow\u201d value. This parameter use to be one of those values that I left as the default: \u201dHamming\u201c. However, after watching Balint Seeber\u2019s talk about\u00a0\u201cBlind signal analysis with GNU Radio\u201d<\/a>\u00a0I realized that I needed to change this setting to \u201cBlackman.\u201d I don\u2019t exactly know how this improves the computations or the mathematics performed by the LFP, but I\u2019ll trust his judgment after listening to his radio experience.<\/p>\n Next, in order to actually isolate the transmission, I provide the appropriate values for \u201cSample Rate,\u201d \u201cCutoff Frequency,\u201d and \u201cTransition Width.\u201d Sample Rate is simply the incoming sample rate. Even if we are using Decimation to modify the output sample rate we use the incoming sample rate as the value for this variable. The \u201cCutoff Frequency\u201d (from what I understand) is the bandwidth (size) of the transmission extending out from the center frequency. We have already computed this value when we specified the \u201cChannel Spacing.\u201d Therefore, we can leverage the value already specified in the \u201cchannel_spacing\u201d variable block.<\/p>\n \u201cTransition Width\u201d is, to me, another one of those mystery parameters. I don\u2019t know specifically how to determine this value. Therefore, using common sense, I simply assume that the transmission signal is not always going to be exactly centered on our intended center frequency. Many things are going to impact our signal: weather, other signals, power lines, etc. Therefore our radio has to compensate for anomalies to ensure that \u201call\u201d of the signal is received. While there may be a very \u201cmathematical\u201d way to describe what this value does, I think of it as \u201cblurring\u201d what the radio considers to be the edge of the signal so that if there is atmospheric jitter the data will still be accessible. Using this logic, I figure that while creating a steep transition will isolate the center frequency very well, it will ultimately generate some signal and data loss at the edges. On the other hand, a slow transition may include too much extra signal and ruin our ultimate goal of signal isolation. So, how do I determine it? I guess and test. From my guessing and testing I have determine that setting the \u201cTransition Width\u201d to a value between forty (40) and fifty (50) percent of the channel spacing gets me the output signal that works the best in the follow-on demodulation blocks. Yes, you can do this using the math equation style mentioned previously. I usually just do the division in my head and input the value into a variable block.<\/p>\n Figure 0x7 shows the captured signal leveraging the following inputs for the LPF.<\/p>\n Figure 0x7: GRC Top Block Using Low Pass Filter<\/p>\n [<\/b>Dramatic Pause]<\/b>\u00a0<- cause I don\u2019t know any other way to dramatically pause in a blog post.<\/p>\n Look good?<\/p>\n [<\/b>Dramatic Pause]<\/b>\u00a0<- \/me sips a beverage<\/p>\n Okay, I\u2019m just going to say it. The signal in Figure 8 IS isolated. However, it is not located at the center of the FFT Plot. If we don\u2019t address this it will negatively impact the rest of our demodulation efforts. We need that signal centered. Right now it is centered on our DC Spike because we configured our radio to listen just outside of the transmission. Can we do it? Of course we can. We can leverage mathematics and configure a bunch of blocks to modify the output of the LPF block to compensate for our output. Or\u2026.we can use the \u201cFrequency Xlating FIR Filter\u201d (FXFF) block instead.<\/p>\n Stay with me, don\u2019t get angry. I needed to describe the LPF because in some instances you might need to use that block instead of the FXFF block. Also, the core variables that configure the LPF also properly configure the FXFF block. The FXFF has \u201cDecimation\u201d and \u201cSample Rate\u201d like the LFP and they are configured the same way. The FXFF block also leverages the \u201cCenter Frequency\u201d variable. This is the variable that re-centers the signal as adjusted for the DC Offset (in other words, if you didn\u2019t adjust to shift the DC Spike, this parameter should be left as zero (0)). What is left is the \u201cTaps\u201d parameter. I have no good explanation for the \u201cTaps\u201d parameter. However, learning from Dragorn\u2019s blog posts\u00a0\u201cPlaying with the<\/a>HackRF – Keyfobs\u201d<\/a>\u00a0I can see that it is related to accounting for the \u201cWindow,\u201d \u201cChannel Width,\u201d and \u201cTransition Width.\u201d Therefore I configure the Taps value, as shown in Figure 0x8, with the following equation: \u201cfirdes.low_pass(1, samp_rate, channel_spacing, channel_trans, firdes.WIN_BLACKMAN, 6.76).<\/i>\u201d Basically, the LPF wrapped up into one variable.<\/p>\n Figure 0x8: GRC FXFF Block Configuration<\/p>\n Running with this configuration we see, in Figure 0x9, that we have a transmission signal that is centered and ready for demodulation.<\/p>\n Figure 0x9: GRC Top Block Using FXFF Block<\/p>\n Now that I have asignal isolated, I can start working with it. This, for me, is also the area where it starts to get a little fuzzy on \u201cwhy\u201d we perform particular steps. I\u2019ll briefly describe what I know, but I recommend that you watch for\u00a0Mike Ossmann to post his radio classes<\/a>\u00a0(a by-product of his successful HackRF Kickstarter project). They should provide you with the specific mathematical reasoning behind each of the blocks necessary for demodulation \u2013 both for frequency-shift keying (FSK) and for amplitude-shift key (ASK) modulation. The basics are this: the \u201cComplex to Mag\u201d or \u201cComplex to Mag ^ 2\u201d blocks are used to demodulate ASK transmissions and the \u201cQuadrature Demod\u201d block is used to demodulate FSK transmissions (specifically 2FSK and GFSK).<\/p>\n The signals I am capturing for this example leverage GFSK modulation. This, however, begs the question: \u201cHow do you know this?\u201d Plainly, I know the device that is transmitting and capturing the transmissions.<\/p>\n What we are seeing in the previous images is the results of a Texas Instrument (TI) Chronos Watch communicating with the TI Chronos Dongle. The TI Chronos Dongle has a TI Chipcon CC1111 radio. The datasheet and even the source code for the dongle are available on TI\u2019s website. Often times, a radio\u2019s datasheet is sufficient to provide all of the information needed for demodulation. Having source code, however, is always better \u2013 because nearly every radio can be configured in a wide variety of ways. A vendor will configure the radios in their products to perform optimally for the device\u2019s primary functionality. Datasheets narrow the possibilities, while source code and radio configuration settings provide specifics. In the case of the TI Chronos Dongle, doing a quick review of the source code, provides the values used to configure the radio for interaction with the TI Chronos Watch (see Figure 0xa).<\/p>\n Figure 0xa: TI Chronos Dongle Source Code Radio Configuration Settings<\/p>\n Reviewing these settings, you will notice some of the parameter values that have been used to configure the previous block variables. Remember these settings \u2013 we will be coming back to this for additional parameter values as we progress. To continue on the \u201cpath to demodulation\u201d I am most interested in two of these values: the modulation type and the \u201cDeviation\u201d. The modulation, as mentioned before, is GFSK and therefore requires that we use the \u201cQuadrature Demod\u201d block for demodulation. This block needs to be configured with the Deviation value.<\/p>\n The actual parameter that needs to be updated is the \u201cGain\u201d value. The Gain parameter is preconfigured with the following equation: “samp_rate\/(2*math.pi*fsk_deviation_hz\/8.0)<\/i>“. To complete this we just need to create a \u201cfsk_deviation_hz\u201d variable block with the value \u201c32000<\/i>\u201d as defined by the Deviation value in the source code. While I am at it, I usually also define a \u201cdata_rate\u201d variable and update the \u201cfreq\u201d variable to be more precise. Figure 0xb shows these modifications with the addition of the \u201cQuadrature Demod\u201d and \u201cfsk_deviation_hz\u201d variable blocks.<\/p>\n Figure 0xb: GRC Quadrature Demod Configuration<\/p>\n As Figure 12 shows, the \u201cQuadrature Demod\u201d block has been configured to to output to a \u201cFile Sink\u201d block. I could have also output to another \u201cFFT\u201d block but the active demodulation will not be very interesting other than showing it is working. To actually \u201csee\u201d interesting demodulated signal it will take other wave analysis tools. But before we do, I should explain several things that need to be taken into consideration. The first is that capture files from radio transmissions can get very large, very fast. Capturing straight from the HackRF to a file with a sample rate of 1,000,000 will generate approximately one gigabyte every forty (40) seconds, and data size increases dramatically as you increase the sampling rate. For these instances you need to consider if your analysis machine is capable of writing to a hard drive fast enough to keep up with the data being captured. Often, if I am capturing straight to a file I will output to the \u201c\/dev\/shm\u201d directory which is provided by my Linux-based operating system. This is RAM Disk and it can be written faster than a hard drive (system dependent, of course). When post-processing a previously saved capture to demodulate the data, however, we don\u2019t need to worry too much about write speeds as long as we\u2019re careful to monitor file sizes so the hard drive does not become filled.<\/p>\n One side note: It is extremely importing to remember \u2013 for all capture files \u2013 information about our capture settings. Without knowing these settings, we will not know how to analyze or replay the data in the future. To address this, I always note all of the settings that are important for analysis in the capture file name. In this case I will be using the filename: \u201c\/tmp\/blog_demod_1e6_905.99e6_gfsk_76721_hackrf.cfile<\/i>\u201d I\u2019ll let you match these values to their appropriate configuration settings.<\/p>\n Hitting the run button will initiate the radio capture, and the transmission will be processed through the demodulator and output to a file. As it was the tool I was trained on I prefer viewing the resulting signal using\u00a0Baudline<\/a>. I could explain exactly how to pull the demodulated file into this tool but this has already been explained very well by Dragorn in his\u00a0Keyfob blog post<\/a>. Rather I am going to show, in Figure 0xc, the captured demodulated signal as seen in Baudline using the primary FFT and the Waveform display.<\/p>\n Figure 0xc: Demodulated Capture Displayed in Baudline<\/p>\n The signal displayed in the center window, the \u201cWaveform\u201d display, is what we are most interested in. The FFT that you\u2019re seeing behind it is actually a waterfall display that shows the demodulated signal over time where the data is \u201cgenerally\u201d represented by clumps of noise. The Waveform display shows the demodulated signal at a particular moment in time in relation to the primary FFT. Using Baudline in this manner allows me to analyze how the signal looks before it is passed onto the other GRC blocks that will be used to determine the actual \u201cones and zeros.\u201d That\u2019s right \u2013at this point the wave shown in the Waveform display should be the transmission\u2019s data. Figure 0xd is a closer look at this wave.<\/p>\n Figure 0xd: Demodulate Capture Displayed in Waveform Display<\/p>\n Reviewing this image using my training and experience I can tell three things:<\/p>\n Hardware radios actually do this \u201ccleaning\u201d process using the circuitry designed into the radio component. Radios implement a LPF after the demodulation before converting the transmission into data.<\/p>\n Therefore, to properly process this transmission I need to implement a LPF in the GRC script.<\/p>\n This part may generate a bit of confusion. Because I have no good explanation for the values that I select when creating the LPF that follows a demodulation block \u2013 it really is a trial-and-error process that I keep \u201ctweaking\u201d until the data \u201clooks right.\u201d<\/p>\n From the earlier explanation of the LPF parameters the \u201cCutoff Freq\u201d and \u201cTransition Width\u201d parameters (\u201cWindow\u201d should be updated to \u201cBlackman<\/i>\u201d) will need to be configured. For the \u201cCutoff Freq\u201d I usually start with a value of\u00a0100,000<\/i>\u00a0and then select a \u201cTransition Width\u201d about half of that value. Once configured, I capture the transmission again, or replay a previously captured transmission, to process it through the demodulator. I do this several times pulling the results into Baudline each time, reviewing the resulting signal, modifying the values, and then capturing again. This is repeated until I see a wave pattern with nice transitions that look like data. What does data look like? Figure 0xe shows this state which was accomplished by using\u00a080,000<\/i>\u00a0for the \u201cCutoff Freq\u201d and\u00a050,000<\/i>\u00a0for the \u201cTransition Width.\u201d<\/p>\n Figure 0xe: Demodulated Signal Run Through a LPF<\/p>\n Taking a closer look at this signal I can see that it is not centered on the X-axis. A good wave pattern, that is ready for processing by the next GRC blocks, will be centered. This may merely be a visual pet peeve of mine, but in my experience the following blocks successfully output the data when the wave is centered on the X-axis. Shifting this wave up (or down if need be) is simple by using mathematics. If I were to multiply each point on that wave by a number it will increase the amplitude of the wave pattern. In this case I don\u2019t need to increase the amplitude. I need to move each value \u201cup\u201d on within this display. Thus, instead of multiplying each point I add a constant value to each point. The increased value of the point is represented on the Y-axis and thereby shifts the wave up. In contrast, I can subtract a constant value from each point to shift it down. The actual value is determined via experimentation and observation and implemented using the \u201cAdd Constant\u201d block. The results of shifting this wave pattern by adding a constant value of\u00a06<\/i>\u00a0is shown in Figure 0xf.<\/p>\n Figure 0xf: Demodulated Signal Shifted Up to X-axis<\/p>\n <\/p>\n As I mentioned, I am not sure how important that last shifting step is in this whole process. But knowing \u201chow\u201d to manipulate the wave pattern without losing any data could help us in the future. For instance, if you know the data is being transmitted inverted (meaning a 0 is a 1 and a 1 is a zero) how could you manage it with these tools? Would multiplying by a negative constant help? Try it out.<\/p>\n Now that I have a nice clean demodulated signal I can move onto the next step. This step involves taking this wave signal, analyzing the highs and lows for a logical pattern, and then using that information to discern 0\u2019s from 1\u2019s. It is all in the mathematics, and GRC has it figured out for me. I start with two specific blocks: \u201cClock Recovery MM\u201d and \u201cBinary Slicer\u201d. The \u201cClock Recovery MM\u201d block does the magic of discerning highs and lows. The \u201cBinary Slicer\u201d marks the highs as a \u201c1\u201d and the lows as a \u201c0\u201d. Actually, it marks them as \u201c0x00\u201d or \u201c0x01\u201d which I will need to manage, later. For this all to work I need to concentrate on configuring the \u201cClock Recovery MM\u201d block correctly.<\/p>\n The \u201cClock Recovery MM,\u201d shown in Figure 0x10, has some REALLY scary looking parameters (cause math is hard). Fortunately, I took Mike Ossmann\u2019s training course and I don\u2019t worry too much about them \u2013 they\u2019re actually fairly easy. When I drop the block into the GRC script, it is set with a bunch of default settings for its parameters. As per Mike, do not touch \u201cGain Omega,\u201d \u201cMu,\u201d \u201cGain Mu,\u201d or \u201cOmega Relative Limit\u201d \u2013 leave them as the default values. I\u2019ve never changed them and I have always been told to leave them alone. Someday I may learn a need to modify them \u2013 but not today. Today I only need to concentrate on the \u201cOmega\u201d parameter. This parameter also comes set to a default value: “samp_per_sym*(1+0.0)<\/i>“. Oh, look, a variable name. Looks like it wants me to set up a variable block with the name \u201csamp_per_sym\u201d which equates to \u201cSamples Per Symbol.\u201d<\/p>\n Figure 0x10: GRC Clock Recovery MM Block Configuration<\/p>\n I do not have the actual value for \u201cSamples Per Symbol,\u201d yet. But I do have the values necessary to compute this value. The value for \u201csamp_rate\u201d is actually \u201cSamples per Second\u201d. For this capture that is\u00a01,000,000<\/i>\u00a0samples per second. The \u201cData Rate\u201d from the radio configuration file is actually \u201cSymbols Per Second.\u201d I have already added this as the \u201cdata_rate\u201d variable with the value:\u00a076721.191<\/i>. Simple mathematics helps me create a \u201cSamples Per Symbol\u201d parameter by dividing the \u201cSamples Per Second\u201d parameter by the \u201cSymbols Per Second\u201d parameter. The \u201cPer Second\u201d values will cancel each other out and I am be left with \u201c1,000,000 \/ 76721.191<\/i>\u201d which is the value for \u201csamples per symbol.\u201d Creating a \u201csamp_per_sym\u201d variable block with the entry \u201cint(samp_rate \/ data_rate)<\/i>\u201d is what I want to do and is shown in Figure 0x11. This will automatically calculate the \u201cSamples Per Symbol\u201d and make it an integer for the \u201cClock Recover MM\u201d block.<\/p>\n Figure 0x11: GRC “samp_per_sym” Variable Block<\/p>\n With the variables for the \u201cClock Recovery MM\u201d block configured we can have it identify the 0\u2019s and 1\u2019s for us. But we need a place for these to go. Therefore, another \u201cFile Sink\u201d block is in order. I usually just write this to the \u201c\/tmp<\/i>\u201d directory and give it an extension of \u201c.dat<\/i>\u201d. Figure 0x12 shows the current GRC setup.<\/p>\n Figure 0x12: GRC with Clock Recovery MM To Extract Data<\/p>\n <\/p>\n Running with the \u201cClock Recovery MM\u201d and \u201cBinary Slicer\u201d blocks will provide me the demodulated data I want. Figure 0x13 shows how this data looks when I review the contents of the output file using the \u201cxxd\u201d command.<\/p>\n Figure 0x13: Demodulated Data Viewed Using “xxd”<\/p>\n <\/p>\n As mentioned, it is a file full of 0\u2019s and 1\u2019s, literally. What I need to do now is basically squash each one of those lines into a byte. The first line \u201c0101 0101 0101 0101 0101 0101 0101 0101\u201d actually translates to \u201c0b1111111111111111\u201d or \u201c0xff\u201d. The line starting at offset 0x30 is \u201c0101 0101 0101 0101 0001 0100 0100 0101\u201d or \u201c0b1111111101101011\u201d or \u201c0xff6b\u201d.<\/p>\n This output looks very promising, but anything can spit out 0\u2019s and 1\u2019s. How do I know if this is actually the data I want? Excellent point, and I will tell you that what you see in Figure 20 is very possibly just noise floating through the air.<\/p>\n You see, the \u201cClock Recovery MM\u201d block did exactly what I told it to do. It looked at the incoming signal, made an estimation as to whether that signal was high or low, passed it to the \u201cBinary Slicer\u201d which converted \u201cHigh\u201d and \u201cLow\u201d into \u201c1\u201d and \u201c0\u201d. However, as with anything, there is a lot more noise out there than there is actual signal. I have not told any GRC block how it can tell the difference between the signal I want, the signal from another radio, or just noise in the air. Also, even if a block does understand that it is receiving actual data, which bit is that bit in the byte? The Most Significant Bit? The third bit from the Least Significant Bit? Always remember \u2013 in radio, the data receive is just raw data\u2026 it could be anything from the data I want to noisy garbage. I need to take a long, hard look at the raw data output by GRC and the \u201cClock Recover MM\u201d to see if I can make sense of it.<\/p>\n Luckily, we are programmers at heart, right? Well, I am a scripter anyway. It might take a little while, but anybody who has made it this far into this blog post will probably know how to take a file, grab each raw \u201cdata\u201d byte, and squash it into a \u201creal\u201d data byte. For those of you who cannot, or do not have the time, I have written \u201cgrc_bit_converter.py\u201d as seen in Figure 0x14.<\/p>\n Figure 0x14: Processing Radio Data using “bit_convert.py”<\/p>\n The \u201cgrc_bit_converter.py\u201d script allows me to process the data output created by the \u201cClock Recovery MM\u201d block in several ways. If I run the tool with the default settings it will start at the beginning of the file, pull out the first 250 bytes, and prints the results in \u201craw data\u201d and \u201cdata byte\u201d format. The script considers these 250 bytes to be a packet and continues to process all packets until the end of the file. Each of these packets is marked with a packet number for easy identification. The \u201cOccurrences\u201d value shows how many packets contained the exact same data which will be very useful once we find actual transmissions. Of course the packet size variable is configurable, but for now I will leave this setting with the default value.<\/p>\n Now that I have pulled some \u201cdata\u201d from the transmission I need to think about how that data will be formatted so that I can search through the converted information. Most radios (not all, but most) will begin a transmission with some type of \u201cpreamble\u201d followed by a SyncWord. Preambles are generally a series of high to low transitions. When viewed in binary these will appear as \u201c0b1010101010101010\u201d or \u201c0xaaaa\u201d. The number of preamble bytes depends on the radio and how it is configured. As the tool does not know exactly which bit is the first bit (or if the transmitted data has been inverted) the preamble may appear as \u201c0b0101010101010101\u201d or \u201c0x5555\u201d. The job of a preamble is to let the radio know that incoming data is on the way and that it that should get ready to process it. The job of a SyncWord is to tell the radio where the actual data packet begins. It can also be used as a designator between two different networks. Any value can be picked for the SyncWord with the obvious exceptions being those that closely resemble a preamble. The most common that I have come across is \u201c0xd391\u201d (look back at Figure 16 and see if you can find this value in the waveform). Like the preamble I need to think about how this might appear in a data file. I can easily do this using iPython and shifting the bits to the left one bit at a time. Figure 0x15 shows that if the sync word is “0xd391” it may actually appear as “0xa722”, “0x4e44”, or “0x9c88” when I am reviewing the bits of a data transmission.<\/p>\n Figure 0x15: SyncWord Shifted By One, Two, and Three Bits<\/p>\n <\/p>\n With this knowledge I can now search the parsed data for transmitted data packets. For this exercise I have decided to just output the converted data to \u201cless\u201d and then search for the known SyncWord “0xd391” using \u201cd3\\\\x91<\/i>\u201d. Figure 0x16 shows the results of this search and one of the transmitted packets.<\/p>\n Figure 0x16: SyncWord Search In Data Output by “grc_bit_conveter.py”<\/p>\n To me, this definitely looks like a data packet. I can confirm this with collaborating information by looking back at the source code for the TI Chronos Dongle. The source code specifically states that the Preamble count is two (2) which is equal to four (4) bytes. The Preamble of this packet is \u201c\\xaa\\xaa\\xaa\\xaa<\/i>\u201d which is also four (4) bytes. It states that the Sync mode is configured to detect 30 bits of a 32 bit sync word. The SyncWord of this packet is \u201c\\xd3\\x91\\xd3\\x91<\/i>\u201d which is 32 bits. It states that the packet length is variable and defined by the first byte after the SyncWord. The first byte after the SyncWord is \u201c\\x0f<\/i>\u201d which equates to fifteen (15). From the end of the length byte I can count out fifteen bytes and I are left with two bytes before the bit stream reverts to all 1\u2019s or 0xff. These last two bytes are the Cyclic Redundancy Check (CRC) for the packet which, according to the source code, has been enabled.<\/p>\n Finally, I have a packet of data. I can output this data to a file, go through it and manually or with a script to pull out the data of interest, and begin my analysis. When information is limited this is exactly what I will do. But in this case I have a lot of information about the transmission. Heck, even with just this raw data I should be able to make some logical assumptions to perform the next steps: marking the data packet when it is captured using GRC. If I do it correctly the data in our output file will be marked exactly where packets begin.<\/p>\n Marking packets in GRC is accomplished using the \u201cCorrelate Access Code\u201d block. This block will take two values: \u201cAccess Code\u201d and \u201cThreshold\u201d. The Access Code is a sequence of bits (0\u2019s and 1\u2019s) that indicates the beginning of a packet. This block will use this value and monitor the data passing out of the \u201cBinary Slicer\u201d block. If it sees this sequence of bits in the byte stream it will mark the next bit it processes by flipping the second bit of the byte. Remember, the information coming out of the \u201cBinary Slicer\u201d is a full byte of data for each 0 and 1 in the binary data stream. By flipping the second bit of this byte the byte is converted from a \u201c0\u201d or \u201c1\u201d to a \u201c2\u201d or \u201c3,\u201d respectively. This data can still be analyzed and converted as the Least Significant Bit is not modified. The \u201cThreshold\u201d variable merely indicates the number of bits that can be \u201cdifferent\u201d than the actual value provided in the \u201cAccess Code\u201d. This is done in case an incoming packet is slightly corrupted but can still be processed. It allows the radio to leverage other means to manage transmission errors. Figure 0x17 shows the \u201cCorrelate Access Code\u201d configured with the “0xd391d391<\/i>” bit sequence and a \u201cThreshold\u201d of two (2) as indicated in the source code. Had I not known the SyncWord I could have used the binary value for the Preamble.<\/p>\n Figure 0x17: Correlate Access Code Configured with 0xd391d391<\/p>\n As mentioned, the \u201cCorrelate Access Code\u201d block processed the data exiting the \u201cBinary Slicer\u201d block. Figure 0x18 shows the placement of these blocks so that the output it directed into a data file.<\/p>\n Figure 0x18: GRC Configured with the Correlate Access Code Block<\/p>\n After capturing the transmissions with this GRC configuration I can analyze the data as I did before. Starting with a quick review using \u201cxxd\u201d I can search for a value of\u00a002<\/i>\u00a0or\u00a003<\/i>\u00a0to see if I have any marked packets. Figure 0x19 shows one of these packets.<\/p>\n Figure 0x19: Marked Packet Viewed Using “xxd”<\/p>\n Now that I have marked packets I know it is worth processing the data. As before I will use \u201cgrc_bit_converter.py\u201d because this script has an option to detect the packet markers provided by the \u201cCorrelate Access Code\u201d block. It also has the ability to modify the size of the packet printed to the screen. Figure 0x20 shows the first packet detected using these markers and printing a packet size of 18 which includes the length byte and the CRC. Reviewing this output quickly, I can see that it matches the criteria that I found in the previous analysis of these packets.<\/p>\n Figure 0x20: Marked Data Output by “grc_bit_conveter.py”<\/p>\n <\/p>\n Excellent, now I have packets for processing. With a little more time and effort I could take what I have here, strip out the GRC GUI components, and start building a Software Define Radio script to check, display, an interact with packets. This GRC configuration will work for the TI Chronos Watch, but will it work for other, similar, devices as well. Basically, the TI Chronos Watch is the control. Now I need a test subject. Fortunately I have been provided one by Jay Radcliffe\u2019s\u00a0question to the GNU-Radio discussion list<\/a>. I worked with Jay and he provided me with a slightly different capture using the DC Offset method.<\/p>\n To get rolling with a transmission capture file I merely added a \u201cFile Source\u201d and \u201cThrottle\u201d block. These blocks read the data from a file and throttle the data as it is passed to the rest of the GRC blocks. Throttling is performed so that the following blocks see the data at the captured rate, rather than just a straight data dump that would over-load the program. In this case the capture rate is 500,000 samples per second and the DC Offset is 200,000 Hz. The signal is being transmitted on 903 MHz using GFSK modulation. Figure 0x21 shows this capture from which I will try and determine the Channel Width.<\/p>\n Figure 0x21: Transmission on 903 MHz Captured with .2 MHz Offset<\/p>\n <\/p>\n The captured transmission is close to the left-edge of the maximum capturing bandwidth as defined by the sampling rate. Although close it does look like Jay captured the full channel width. But, because it is right on the edge, I do have to be careful with my configuration settings for \u201cChannel Spacing\u201d and \u201cChannel Transition\u201d so that I do not specify an area outside of the captured bandwidth (I\u2019m not sure how GRC will handle it if I did). Using the Frequency scale it looks like the \u201cChannel Spacing\u201d goes from\u00a0902,950,000<\/i>\u00a0to\u00a0903,100,000<\/i>\u00a0Hz giving me a\u00a0150,000<\/i>\u00a0Hz channel width. Staying inside this range we will set the \u201cChannel Spacing\u201d to\u00a0100,000<\/i>\u00a0and the \u201cChannel Transition\u201d to\u00a050,000<\/i>. These values are used to update the FXFF parameters. The results of this configuration update can be seen in Figure 0x22.<\/p>\n <\/p>\n Figure 0x22: Transmission Filtered Using FXFF Block<\/p>\n From Jay\u2019s GNU Radio posting I know that the Deviation for this transmission is\u00a016,500<\/i>\u00a0Hz and the data rate is\u00a019,200<\/i>\u00a0Symbols Per Second. The Deviation value is used to update the \u201cfsk_deviation_hz\u201d block. Once this block is configured configured I can pass the filtered data through the \u201cQuadrature Demod\u201d block and start my analysis of the demodulated signal using Baudline. From this analysis (and trying a bunch of different values until it worked) I got the \u201cCutOff Freq\u201d and \u201cTransition Width\u201d values for the \u201cLow Pass Filter\u201d block I will use after the \u201cQuadrature Demod\u201d block. These values are\u00a025,000<\/i>\u00a0and\u00a010,000<\/i>\u00a0respectively (this is a huge difference from the previous settings for a very similar radio and I do not know why, but it works). Figure 0x23 shows the resulting wave pattern as displayed in Baudline.<\/p>\n Figure 0x23: Demodulated Signal From Captured Transmission<\/p>\n From this image the wave form appears to need to be shifted down slightly. I ran a quick test of the data output before and after shifting this wave form and output data did appear to be different. Next, the \u201cAdd Constant\u201d block was configured with a constant value of negative six (-6<\/i>) to shift the wave pattern down. Visual review of Figure 0x23 determined that this transmission only sends the SyncWord once. Therefore I modified the \u201cCorrelate Access Code\u201d so that it marked a packet every time that it found the SyncWord “0xd391”. This data was output to a file and the \u201cgrc_bit_converter.py\u201d script was used to check for marked packets. Review of this data showed that some packets appear to have a consistent length of eighty (80) bytes. Figure 0x24 shows some of the packets output by the script.<\/p>\n Figure 0x24: iMarked Packets Displayed using “grc_bit_converter.py”<\/p>\n <\/p>\n Capturing transmissions with GRC is fairly easy once you have the proper equipment and the software installed. Understanding how to manipulate the transmissions captured using GRC is a bit more difficult. Demodulating the transmissions down to the actual data being transmitted is even more difficult. Notice, however, that I did not say \u201cimpossible.\u201d There is plenty of information out there for conducting signal analysis. Some of this information is difficult to understand and much of it glosses over most of the important techniques and configuration settings. The information out there is extremely helpful but it only contains pieces of the puzzle. The great thing, however, is that the radio hacking community is growing very rapidly. Unfortunately not all of these people are talking, yet. Hopefully we will see more examples and tutorials soon. I am also hoping that this blog post helped fill some of the gaps and will, in turn, inspire others to do the same.<\/p>\n If you are looking for training on radio analysis then I highly recommend you watch Mike Ossmann and his HackRF project. Mike usually gives one or two classes a year and they contain a more in-depth understanding of radio transmissions. Everything I have provided in this blog post was born of that training and my experiences that have resulted from it.<\/p>\n As I mentioned at the beginning, Tom and I are teaching the \u201cAssessing and Exploiting Control Systems with SamuraiSTFU<\/a>” when Justin Searle is swamped or just needs a break. You can check out the SamuraiSTFU website for training dates and you will most likely see me in Houston and Amsterdam soon. I will be working all of this material into the course to augment what is already there. This will allow students to do everything we have outlined here with their own TI Chronos Watch setup provided by the classes hardware kit.<\/p>\n InGuardians<\/a>\u00a0– for helping me through this post and countless other things Go forth and do good things.<\/p>\n <\/p>\n <\/p>\n","protected":false},"excerpt":{"rendered":" Post Author: Don C. Weber [Twitter:\u00a0@cutaway] Date Published: 15 May 2014 I have not picked up my\u00a0HackRF Jawbreaker\u00a0in a while (Figure 0x0). Family and billable work trump side projects. Lucky for me\u00a0Tom Liston\u00a0and I started teaching the\u00a0Assessing and Exploiting Control Systemsclass which leverages the\u00a0Samurai Project’s Security Testing Framework for Utilities (SamuraiSTFU). I say \u201clucky\u201d because […]<\/p>\n","protected":false},"author":7,"featured_media":2202,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[67],"tags":[93,88,9,87,92],"_links":{"self":[{"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/posts\/2186"}],"collection":[{"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/comments?post=2186"}],"version-history":[{"count":2,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/posts\/2186\/revisions"}],"predecessor-version":[{"id":2221,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/posts\/2186\/revisions\/2221"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/media\/2202"}],"wp:attachment":[{"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/media?parent=2186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/categories?post=2186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zed.inguardians.com\/wp-json\/wp\/v2\/tags?post=2186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}
\nDate Published: 15 May 2014<\/p>\n<\/a><\/p>\n
Managing Direct Current Spike<\/h2>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
Isolating The Transmission<\/h2>\n
\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
Actual Demodulation<\/h2>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
\n
<\/a><\/p>\n
<\/a><\/p>\n
Counting the Bits<\/h2>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
Analyzing Demodulated Data<\/h2>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
Marking The Packet<\/h2>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
Testing The Control<\/h2>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
Conclusion<\/h2>\n
Acknowledgements<\/h3>\n
\nMike Ossmann<\/a>\u00a0– for being a leader, innovator, and teacher
\nJustin Searle<\/a>\u00a0– for trusting me and pushing me into new areas
\natlas<\/a>\u00a0– for being a mentor and a peer
\nJean-Michel Picod<\/a>\u00a0– for helping me get my GRC legs back under me<\/p>\n