Signal Disruption via GNURadio

This weekend, I also spent some time looking into applied signal disruption. It is my firm belief that many security “professionals” talk too much shit about presumably easy things, but couldn’t change their MAC address without half an hour of Google. In my ongoing effort to avoid this, I spent some time trying some things out.

Remember kids, be ethical. Don’t be unethical. Thanks. Also happy Easter.

Unsurprisingly, building a generic jammer in GNURadio is rather easy (in practice: don’t forget to raise the sample rate because bladeRF won’t do 32k samples. 80k or no play):

To modify this to work on a Raspberry Pi (or similar handheld device) is an exercise in simplicity itself. This works on the principle of raising the noise floor: that is, typically, your computer’s WiFi baseband expects a signal similar to the following:

We simply overpower the signal with a random one of our own, to the point where the computer can no longer tell what’s a legitimate signal:

It is here that the power of the bladeRF device becomes apparent, with the device being able to comfortably disrupt a glorious 28Mhz of bandwidth around a central frequency.

After gaining the express written consent of everyone in my vicnity using my WiFi (and choosing a band I can’t see anyone else using), I then proceeded to test the effective range of this jamming, using GQRX on another laptop to detect to which point this would be effective. My test setup is as follows:

  • A bladeRF (the jamming device), using the above flow graph and a relative gain of 50 in gnuradio, using a low-gain omnidirectional 2.4Ghz antenna, purchased with the bladeRF.
    • It should be noted that the bladeRF has an extremely low transmit power (+6dBm), where a wifi router might transmit up to 20dBm.
    • It should also be noted that a commercial amplifier is available for the bladeRF (XB300) offering a tremendous +33dBm gain over 2.4Ghz.
    • The USRP B-series has significantly higher transmit power (10dbm). The prospect of using a B205-mini and a Raspberry Pi is tantalizing, to say the least.
    • It is apparently possible to raise this with a Low Noise Amplifier. I don’t have one, I wouldn’t know where to start with such a device.
  • A USRP B200 (the testing device), running gqrx to visually inspect the spectrum
  • An iPad (secondary testing device), using the interface to connect as usual
  • A laptop (secondary testing device, using iw’s scanning capability to detect the AP)

Some of my initial results (for brevity) are as follows:

  • At approximately 10M, with line of sight, jamming works. Devices almost instantly disconnect from WiFi.
  • At approximately 10M with two brick walls (within 5M of the broadcasting AP, with an iPad) between the jammer and the target, this no longer works. At this point, the SNR of the wifi connection is poor, but it’s a functioning connection.

To progress this, I’d also like to investigate the effectiveness of ad-hoc antennas, as well as the impact of various not-completely-random modes of signal disruption against traditional WiFi (as well as other low-powered devices) – there’s surprisingly little literature on the topic, even from overseas.

One day, I hope to be as excellent as this glorious gentleman:


The practical application of this are limitless – but the simplest is that in cases where you are attacking a system with a hardened WiFi stack, which ignores and reports active deauthentication (if you’re reading this – you know who you are, this one’s for you :P), you can still force the target to disconnect and re-authenticate.

Posted in Bards, Computers, Jesting | Tagged , | Leave a comment

Simple Packets via GNURadio

This weekend, I spent time learning about GNURadio and it’s applications, with a goal of building a generic packet-based (non-stream) messaging interface between SDR devices. While I was not entirely successful, I was able to fake this behaviour by manipulating a stream transmission. In this process, I also gained some understanding of the intricacies of GNURadio.

The hardware used in this process was a USRP B200 attached to a Linux system, and a BladeRF attached to a Windows system, sending traffic over a quiet part of the 2.4Ghz spectrum: however, this should work anywhere (just adjust frequency and sample rate, and fix the osmocom source and sink).

I will document my progress here for future reference.

Simple File Transfer

I began by simply transferring a file between one system and another.  We start by creating a file source block, with output format selected to byte. We then pass this through a Packet Encoder block, and then prepare for transmission via a GMSK modulator. We multiply the output complex number by 1.0 (todo: why?), and pass this via an osmocom sink. The flow graph looks something like this:

We can confirm this “works”, via both the FFT sink (showing power over frequency over time), as well as an independent GQRX.

The illustration above shows a vector source pointing to a variable, but this is functionally equivalent (and works as well).

To receive the file, we simply do the reverse: from an osmocom source, we multiply by complex 1.0, decode the packet, send it through a low pass filter (to remove noise from nearby frequencies), demodulate the data (GMSK demod), decode the packets and write to file:

A quick test confirms we can send and receive an arbitrary stream of data via GNURadio.

Message PDUs / Message Strobe

From there, my research (and by research I mean Google) showed that I could presumably use the “Message Passing” interface to translate messages. Beginning from Dr. Aaron Scher’s example here, I attempted to glue this on to my existing flow graph, replacing the source with a Message Strobe, presumably converted to bytes:

  • Using a Message Strobe function to send a message every 500 ms
  • Create a tagged stream with an output format of byte
  • Build a header, and repack at a 1:8 compression rate (i.e. each bit is now represented as one byte in the output)
  • Treat this as a stream, pass it by GMSK modulation and send, as if it were a file.

Unfortunately, while an FFT sink showed that *some* signal was coming out of the GMSK modulator, a stream receive on the other end (to file) did not show the expected data. For reference, my flow graph was similar to the below:

On further research, it appears that this is not the intent of the message passing interface: instead, it is intended for use as “commands” to send around your flow graph: for example, if you receive a signal above a certain strength, retune your SDR Device to another frequency (via a “Message”). This will no doubt be useful later – I’m thinking jamming-resistant SDR.

It should be noted here that a quirk of the UI is apparent: the “repack bits” block actually requires a length tag to function correctly, but even if you set it, it’s not shown in the graphical view of the flow graph.

Modifying the Vector Source

After a few hours of learning about the Message interface, I attempted to solve this problem by utilising the file transfer code above, and simply modifying the Vector Source to transmit different data. This could be done by directly modifying the Python generated by gnuradio, to introduce a new thread created as the top block is initialized, which modifies the data used by the vector source:

This vector represents a simple custom packet format:

  • The first four bytes are a static header, consisting of the bytes 1, 2, 3 and 4
  • The next byte is the length of the packet data
  • The next byte is a packet ID. The receiver should reject packets with ID’s it’s seen before.
  • The next four bytes are the packet data. This is variable length.
  • The next and last four bytes are a footer, consisting of the bytes 5, 6, 7 and 8.

To receive this, we simply modify the file receive script, with a custom Python sink:

The flow graph is extremely simple, with the only change to accomodate the new packet sink:

This works, but causes overflows on the receiver. I suspect this is due to the Python message sink being too slow: that is, it takes too long to process messages, so the hardware’s receive buffer fills, and it “drops packets”.

I believe I can optimize this via a Vector sink, and using gnuradio’s “Probe” mechanism to constantly poll the value of the resultant Vector, leaving gnuradio to do the heavy lifting of data transfer.

I will continue to improve this work and document my progress.

Posted in Bards, Computers, Jesting | Tagged | Leave a comment

Writeups – Slumdog Millionaire, Purple Posse Market, Matroichka 1,2 (Nuit du Hack Quals)

Last weekend, I had the pleasure of once more participating in the Nuit du Hack qualifier CTF. Similar to last year, I found this to be an enjoyable event, even though my lack of skill and focus meant I was not able to solve many challenges. As always, I will document some of the interesting challenges I encountered.

I should note that from here, I will make an attempt to tackle web-based challenges, as this is an area that I am particularly and notably weak in.

Without further ado:

Matroichka 1

As last year, a four-part matroichka reverse engineering challenge was presented in this year’s CTF. You can download the original binary (as well as an unpacked Part 2) here.

I began my analysis by loading step1.bin into IDA Pro. The first challenge was a string comparison check, with a few distraction functions (“mmm”, “you” and “touch”). The core of the functionality is here:

A quick breakpoint at 0x4007A0  reveals two things:

  • Our input string is reversed, and;
  • The “target” string is Tr4laLa!!!

Running the program with an argument of “!!!aLal4rT” (appropriately escaped, of course) quickly revealed the second part of the binary, which is detailed below.

Matroichka 2

This binary is included with the download for Matroichka 1. Alternatively, just run Matroichka 1 with the correct flag, and this binary will be printed on stderr.

Again, I began my analysis by loading this binary into IDA Pro. This revealed a far more complex binary than the first:

Judging by the structure of the program, this did not appear to be an angr-style solve, so I delved further into the program. After some analysis, the structure of the program became clear:

  • Firstly, the program checked if argv[0] was “./step2.bin”. This would prevent the program from running correctly under gdb, as well as if it was incorrectly named.
  • Then, the program utilised a strange chained block cipher (utilizing simple XOR) along with some signal handler trickery to check the key.

Firstly, in order to overcome the argv[0] check, it was sufficient to re-write argv[0] at program execution, with the following steps:

  • break *0x4007CC
  • set {char[12]} $rax = “./step2.bin”
  • c
  • break *0x400879

Following this check, the program then checked if the first character of the flag (entered in argv[1]) was “W” (at 0x40085C). From here, the real “meat” of the program begins:

Immediately noticeable is the use of signal() to install a signal handler, as well as the unusual use of the “cmovz” instruction to select which signal handler is installed (either 400AC6 or 400AD0).

In a nutshell:

  • for each letter of our input:
    • if it’s even, subtract it’s value from the next character, mod 256 (and replace the next character with this)
    • if it’s odd, add it’s value to the next character, mod 256 (and replace the next character with this)

Following this, a static block of data (divided up into dwords) is then chain XOR’ed with 0xDEADBEEF: that is, 0xDEADBEEF is the xor key for the first block, the xor’ed first block is the xor key of the second block, and so forth. This slightly enciphered block is then compared with our mutated input (as above).

Due to the predictable nature of this algorithm (and that we know the first character of the key, “W”), we can quickly derive a Python script to work backwards: that is, we first reproduce the XOR code, and then we work backwards to derive what each character of the flag is.

You can download the solution script here.

Slumdog Millionaire

This challenge was presented as a web challenge, along with an associated Python file, which you can download here.

The website appeared to represent a lottery website: you could enter a set of random numbers, and the site would tell you if you guessed correctly or incorrectly (and print the correct set of numbers). The Python file above provided the algorithm behind the lottery game:

The algorithm appears to have a single point of failure: that is, the random number generator is seeded once – once you know the random number, the actual number generation isn’t very random.

The attack against this is a simple brute force search against the random seed used: given one set of winning numbers, we can easily determine the random seed, and thus predict the next set of numbers.

You can download the brute force solution script here.

Purple Posse Market

This challenge was presented as a raw web challenge, appearing to represent a legitimate web business. The purpose of the challenge was to determine the administrator’s IBAN number (think bank account):

After browsing the site for a few moments, we hit gold with a contact form:

Experience says that this is a cross-site scripting challenge: I quickly spin up a bucket, and try submitting a few contact forms. After a few tries (input filtering?), we get lucky, and end up with an administrator cookie:

From here, it is simple to read the /admin site with an administrator cookie, and retrieve the administrator’s IBAN number, for an easy 200 [?] points:

As always, I’d like to thank the Nuit du Hack organisers for putting together another enjoyable event, and I particularly look forward to solving the remainder of the Matroichka challenge, as time permits (level 3 is a fork-based mindfuck).

See you all in the ASIS CTF this weekend.

Posted in Bards, Computers, Jesting | Leave a comment

Some (more) thoughts on community…

A week ago, I had the unique privilege of declaring the second Great Purge of the Platypus Initiative. Among the other Australian information security communities, this concept is unique to us – a time when all “idle” accounts are deleted from our Slack channel, and if they have access, our other resources.

To give an idea of the scale of this exercise:

Of a community of just over 200, 68 is a sizeable number to remove. Why do we do this to ourselves?

The Platypus Initiative was created as a highly participatory environment, where we help each other build knowledge.

Just over a year ago, I had the pleasure of taking part in creating the first iteration of the Platypus Initiative, a small group by the name of Let’s Just Hack Shit. Initially, this group was intended to bring together like-minded individuals who could work together in pursuit of pure technical goals, all together contributing their specialist knowledge for the betterment of our members.

We distinguished ourselves from other communities by this mantra alone: that is, where other groups often tried to be everything to everyone, we focussed on technical excellence above all else, applying ourselves to the arduous trek of self-improvement.

All were expected to participate – at the time, we agreed among ourselves that we would put time and effort into bettering ourselves, as opposed to sitting in a presentation, intellectual begging bowl in hand, only to forget everything as we drunk ourselves senseless by the evening’s end: as was the tradition in the local information security scene.

let’s learn how to apt-get install shit again~~~

It is with some pride that I look back upon that time, when we were but a handful in number, and our chat channels filled with technical content to some extent.

In growing, we have become complacent. In embracing community, we have forgotten the ideals which brought us together.

Over the past year, it has become increasingly apparent that we have strayed from this initial ideal. Personally, I think this is a natural result of the growth we have experienced – as we have grown, we have diversified our interests, and now serve more as community organisers rather than technical drivers.

If I had to search for a word to describe this condition – “complacency” is the first that comes to mind. In growing, we became lazy and idle, and unable to drive the technical content so sorely lacking locally. In embracing community, we have begun to sit on our laurels.

… my name is ozymandias, king of kings …

This is not “wrong”, per se: merely disappointing. We are still doing better than the hilarious intellectual tick-box exercise that passes for commercial penetration testing nowdays. Someone complained to me earlier in the week that commercial penetration testing did not allow him to “learn” – if you want to really learn about infosec beyond a certain, unspoken limit while pentesting in Australia, go home and jerk off instead.

To be clear, I’m not implying there’s no good pentesting teams in Australia. There’s some good places to work, but extremely few manage to (or have a need to!) push the envelope. Nor am I implying that people don’t have a desire to learn – ultimately, Australia suffers from a problem of scale, where there is simply no requirement to push beyond the established norms of industry.

I do, however, mean to say that people simply neglect to try. Cool projects are happening out there, all it requires is a willingness to apply themselves and a base knowledge of programming (i.e. C, or “low-level systems programming” in today’s parlance, once known as “regular programming” or “high-level languages”).

Still, while I don’t have a solution, my message is not one of hopelessness:

It is time we refocused the community again – we grow together, or we suffer slow death-by-no-content like everyone else.

For those of you who have been with us through the two Great Purges we’ve had so far, this line will be familiar to you. It is the third and final pillar of our Great Purge strategy: that is, in proactively removing idleness from our ranks, we give ourselves opportunity to refocus, and reapply ourselves.

Unfortunately, this approach doesn’t scale. Such Great Purges are often announced with some fanfare, and for a week or so, technical content comes to the fore once more – before everyone resettles into their comfort zone.

Most importantly, this includes us – and among organisers of communities, stagnation is death.

To me, it is time we looked beyond our local communities for a more sustainable solution, and in doing so, challenge ourselves and our achievements. As Platypus – as a community, by pooling resources, we have given ourselves the ability to do this – whether this be internet-based collaboration (RIP. Platypus Facts Show) or hopefully flying people into Australia to speak in coming years. If anything gives me hope, it’s this.

As for the here and now – the meager handful of you willing to make sacrifices in order to reach for technical excellence, let’s take this opportunity to refocus ourselves and strive ever onwards.

As for everyone else, may you take this opportunity to reflect, and consider the possibilities open to you, if you were to reach beyond the scope of what your day job would have you do.

See you all at BSides.


Posted in Bards | Tagged | Leave a comment

Writeups – Shane and the Binary Files, MI6 (Pragyan CTF)

Over the past few weeks, numerous side projects (including starting lecturing for the COMP6443 course at UNSW, as well as attempting to unravel the fucking magic carpet ride that is OpenBTS) have significantly reduced the time I’ve been able to spend playing CTFs. This weekend, I was happy to at least participate in the Pragyan CTF.

I have documented two of the challenges I was able to complete in the time allocated. Without further ado:

Shane and the Binary Files

This challenge was presented as an archive, containing three Java class files. You can download this here.

Upon unzipping the archive, we are met with three Java .class files. These are obfuscated to a trivial degree, and could be decompiled using jd-gui. The most interesting code was found in nq2eige2ig2323f.class:


This appeared to show as simple comparison test – that is, the user entered a “key”, and if it matched the program’s expectation, it would print out the flag (or at least something useful) We could emulate this condition by placing the “win” condition into an empty Java application. A few moments of Java later, and we have the flag:


You can download the final Java solution used here.


This challenge was presented as an executable file, which you can download here. Furthermore, we were provided with a ciphertext, which we were to decrypt. This was as follows:

"26 25 30 28 22 25 20 23 21 29 22 24 26 23 21 26 27 20 28 22 25 23
 30 29 23 28 24 20 21 26 25 20 23 27 23 29 25 22 23 26 27 29 24 23
 30 21 25 24 26 20 24 22 21 30 26 20 25 24 21 23 27 29 26 22 20 21
 23 22 30 26 29 26 28 27 22 20 27 29 26 30 28 27 26 23 29 21 22 25
 27 24 21 29 25 24 20 25 23 22 30 28 27 29 25 20 24 21 23 20 23 21
 29 26"

Upon initial inspection, it is clear that not all is as it seems – this is a Linux executable bash script, rather than a Windows executable. On further inspection, this appears to unpack and install a piece of Ruby code. By commenting out the installation operation, we are able to retrieve the Ruby script, reverse_1.rb:


For me, this was an interesting challenge, as I have minimal experience with Ruby, having used it a grand total of once previously. As such, I began Googling various bits of Ruby syntax in order to understand the code.

At this point, a helpful hint from our comrades at CaptureTheSwag shortened the process – the code was from StackOverflow, and was being used without attribution.

This helped put context around the code. A little bit of Googling later, and I understood the concept it was trying to implement:


In a nutshell, the code would:

  • xor each character by 61 (decimal 61, not the usual 0x61)
  • “partition” the resulting number, using only numbers between 20 and 30
  • print out all the integer partitions together

From a decryption standpoint, the challenge would be to automatically determine how many numbers made up one partitioned character – especially considering that in certain circumstances, there could be multiple options. Given the time constraint, I built a Python script which allowed me to manually try various combinations until I got the flag:


You can download the Python script here.

I’d like to thank the Pragyan CTF organisers for hosting this event, and while it could be argued that the clues for this event were too cryptic / the challenges did not “lead the player through” a logical sequence (evidenced by the extremely low – near 10% – solve rate of most challenges), I enjoyed solving some of these challenges nonetheless.

See you in the 0CTF qualifiers in two weeks 🙂

Posted in Bards, Computers, Jesting | Tagged , | Leave a comment