Reverse engineering has always held an aura of mystery making it an intimidating field to venture into. The act of uncovering hidden vulnerabilities in embedded systems, particularly 0-day vulnerabilities, is often regarded as a luxury and privileged pursuit. Shambles aims to transform this experience by making embedded systems reverse engineering child's play.
Shambles aims to empower individuals to quickly and easily uncover vulnerabilities in IoT/ICS products. It streamlines and enhances the discovery and validation of 0-day vulnerabilities in embedded systems, eliminating the need for users to possess expert-level knowledge or extensive reverse engineering experience.
Fundamentally, Shambles stands as an advanced integrated toolkit used for dissecting the binary code of embedded systems. Thereby, Shambles is a comprehensive suite of in-house applications which provide functionalities, spanning from unpacking, decompiling, and disassembling to generating static pseudocode vulnerability, to a fully-fledged firmware emulation kernel, a debugger, and much more. All these diverse capabilities seamlessly converge within a unified tool. Consequently, the resultant culmination, Shambles, emerges as an all-encompassing and holistic solution for reversing and discovering vulnerabilities in embedded systems.
For context, as of August 2023, I discovered
107 0-day vulnerabilities in less than
200 hours and wrote working RCE POCs for
49 of them. At the time of publishing this number will likely be in the hundreds. About
~30% have been reported to vendors - so there's still plenty to find/report! These are vulnerabilities in IoT devices, mainly routers, cameras, and firewalls of big brands we all know and love. The majority of these flaws were Command Injections, BOF/DOS, and bypassing CVEs vendor patches; which are vulnerabilities Shambles excels at identifying 😊.
At the time of writing, the easiest way to get early access to Shambles is by joining our Discord (https://discord.gg/wxJMRm8Hyg) and reading the
faq-readme section. To stay up to date with releases and developments follow H4k and Boschko on Twitter.
As a disclaimer, it's important to mention that I maintain an informal affiliation and relationship with Lian Security, the company behind Shambles. This connection can be best described as a healthy blend of friendship and business partnership. Our mutual goal is to pave the way for a future where Shambles becomes accessible to a broader audience. We strive to redefine the landscape of reverse engineering by concentrating on simplifying the process of discovering vulnerabilities.
I hold a deep passion for the success of Shambles. My sincere hope is that the IoT/RE community recognizes its value, embraces its potential, and utilizes it to discover and responsibly disclose zero-day vulnerabilities, thus contributing to making the internet safer. Observing Shambles flourish within this community would bring immense gratification. I wholeheartedly believe that Shambles possesses enormous potential to empower both new and experienced researchers and enthusiasts, enabling them to delve into the domain of embedded systems, bolster online security, and create a positive impact on the cybersecurity landscape.
Let's talk about the company behind Shambles. It has been developed by a skilled team of 12 engineers at Lian Security for well over two years now. They're responsible for software such as SHAMBLES, INCINERATOR, and FLEGIAS covering everything from software to hardware, basic operations and maintenance, product UI design, and so on.
Kindly note, and be mindful that that Lian Security is a company based in China, along with everything that entails. The people behind their products are talented security professionals just like the rest of us. Most of them have worked at F100 and extremely respected information security and research companies. I personally believe it would be a shame to deprive ourselves of their talent, research, hard work, and dedication to a framework based off of regional biases.
The team plans to make public, and open source some seriously fantastic research. Such as Implementation of obfuscation detection by Text Classification, and NAND memory dump analysis.
Let's get started! I'll be showcasing most of the features that Shambles has to offer and how I personally use them to uncover vulnerabilities in a sequential fashion. There are a lot of features that I won't be delving into. However, if you want to see more Lian Security has a really great blog on how to reproduce CVE-2019-10999 in Shambles.
Shambles is available on
Linux systems and supports the following firmware architectures
MIPS/ARM/PPC/RISC-V with plans to integrate
intel x86 in future releases. There are ways for large organizations to obtain Shambles on-premise, and Lain Security is also exploring the possibility, and is open to the idea of selling bulk API calls to companies and vendors 😊.
Under the hood, the reverse-engineering core of Shambles is the Reactor engine which is used to decompile the instruction sets of
MIPS/ARM/PPC/RISC-V processors and
Electron is used for the frontend,
Java is used for the kernel portion, and
GO is used for the backend and API server.
There are two ways to get Firmware analyzed. The first is through the Shambles desktop interface and the second is via their cloud web-based portal. The latter allows you to upload the firmware and have it statically analyzed through the portal below.
Personally, I upload the majority of my firmware through this cloud portal. Once the firmware is uploaded, and analyzed you'll obtain general information and the sum of static analysis findings.
Before we go any further you might be seeing the number of potential vulnerabilities observed and be like
To be honest so did I at first. After using Shambles you'll come to realize that its fidelity is extremely high. Most of these BOFs have to be chained with other primitives and oftentimes you won't have control over the registers. Nevertheless, don't dismiss the number presented by the analysis it's genuinely quite accurate and precise. The thing to remember is that the primary difference between Shambles and tools like IDA PRO, for example, lies in its efficiency in vulnerability excavation and reducing unnecessary manual review.
Another feature I quickly want to shine some light on is the cloud report generator. I think having the ability to download such a report provides great value to vendors.
The report gives you a good overview of binaries that might need some cleaning up and refactoring. It also includes any known CVEs the binaries you're using may have. Overall, not a bad thing to have and be aware of if you're a vendor.
I find myself mainly using the desktop client on Windows.
Once this firmware is uploaded through the cloud app it can be retrieved in the desktop application
Browser All view as seen below. It goes without saying that you only have visibility to the firmware your
In the future, for an added layer of security, Lian Security will implement a two-way certificate validation feature for public cloud users. This will ensure that the files uploaded and generated by the users can only be accessed by the users themselves, and they can use their own certificates to encrypt their account directories. Even though their current implementation is quite safe.
In the desktop application,
Clone to Local does exactly what you think it does. Once a firmware is cloned it can be opened with Shambles. Here is the second place where you can upload firmware to get analyzed which gets uploaded to Shambles Cloud, and unpacked, analyzed, fuzzed, etc.
Once the firmware has been cloned locally, double-click it in the
Local Firmware List to obtain the view below.
There is a lot of information in the
Firmware Info tab. We won't go into every single feature but the
File Password feature I think it's nice. Shambles identifies instances of hard-coded credentials in the application firmware.
You do have the ability to crack these passwords using Shambles Cloud, but you might be better off doing this locally. Lastly,
Key Information is always interesting. Private keys and certificates could give you further insight into whatever you're reversing. And if you have the physical machine open up some MITM avenues.
On the right-hand side, you'll have the following
Virtual Machine tabs.
These are the suspected vulnerabilities that were picked up by analysis.
High, Medium, and Low are simply statically derived metrics based off of some fidelity metrics. I personally find most of my command injections in the
Low Vulnerability section. This is something I've showcased in the past and you often see me look into this section during my live streams, so don't disregard low and medium severity. It's not an impact qualifier.
Expanding any of these high, medium, or low tabs will provide you with the binary of interest and the number of detections/alerts they generate. When I say alert think of it as a "suspicion of a vulnerability".
If we click on
/sbin/ncc2 which has ~244 alerts, or potential vulnerabilities. By expanding the drop downs we can get a quick view of where it believes the issues are. This is great for quickly parsing and identifying a funky
memset, etc. I personally use it to prioritize functions I find interesting.
What's fun with Shambles is that it provides you with the pointer to the function that the static analysis or triggered on. As seen below Shambles believes there's a potential BOF in the
sub_49f280 function because of the following operation
strcpy(&var118, get_entry_value_by_name(p1, p2, "nextPage")) which makes a lot of sense if the buffer for
var118 is tiny and we can pass input through a
nextPage parameter. Personally, this allows me to quickly weed out what are and quickly actionable vulnerable functions, and which aren't.
You can simply double-click it to be brought to its disassembled view.
The color coding used is defined in the picture below.
By going to the ASM view of the function and hitting
TAB we can obtain the pseudocode, which feels a lot like it and looks much nicer than IDA/Ghidra.
As mentioned previously, I won't be able to show every Shambles feature I find amazing. But I do want to shine some light on their being a really well-built search tool (
Alt+T to spawn) Using it is a huge time-save and is one of the best I've used.
Through the search, you're provided with the ASM view. But there's also the strings view, import view (functions imported by the analyzed binary), export view (program's entry point for execution), segment view (segments present in the binary), and hex view.
So let's have a look at whether or not Shambled found a valid vulnerability.
nextPage parameter does in fact appear to be vulnerable to a buffer overflow when the string returned by
get_entry_value_by_name(p1, p2, "nextPage") is longer than
strcpy might write past the end of the
var118 buffer, causing a buffer overflow.
To prove a point, we are also going to look at a command injection that was discovered in the
Low Vulnerability section. There is actually also a buffer overflow in this function. Oftentimes when you have a BOF you also have a command injection.
This is a bit of a longer function, all you need to know is that the function takes in 3 parameters.
The function then calls
get_entry_value_by_name three times, passing
ddnsPassword respectively. This is going to be the input we control and pass to the
ddns_check.c endpoint via the
after assigning some values to some variables and doing some checks the code then calls
__system function with a formatted command string. This function under the hood executes a system command of
/bin/sh onto the
noip2 binary seen below.
Our provided input will be "injected" into the
%s format string since it is intended for our passing string argument that represents a command to be executed. This looks extremely promising.
For context, these two vulnerabilities took approximately 5-7 minutes each to identify, locate, and make sense of through Shambles. How can we make this process even faster? The answer is with Artificial Intelligence!
Version 1.2.2 Lain Security added the AI Assistant to Shambles! Before if the pseudocode was confusing you'd copy everything into ChatGPT and ask it to make sense of it for you. Or you'd spend 15 minutes slowly working through functions. Shambles AI assistant is there to help make your life easy.
Located right under the Virtual Machine side panel, let's see what the AI Assistant says about our buffer overflow in the
Its analysis is quite spot on. And I'm sure we all can see the value in such a feature. In many ways, it's a better description and analysis than I gave you guys previously regarding
sub_49f280. There are a lot more ideas and exploit paths to validate. And for those of us who do this late at night with a few 青岛啤酒 beers in our system, the Detailed Interpreter makes life so much better with easy-to-follow pseudocode commenting as seen below.
Now that we have two potential vulnerabilities, we want to validate their legitimacy. Normally this is where you'd pull out your janky unmaintained Ubuntu 18.04 with a shaky FirmAE or QEMU environment and hope nothing breaks. With Shambles there's no need to stress or worry! We're able to emulate our firmware and validate our vulnerabilities by using the Shambles built-in dynamic emulator!
In the official documentation, it's often referred to as
dynamic simulation mode but we'll call it setting up the Virtual Machine (VM) mode which will contain all the application functions in static analysis. Shambles VM mode is a built-in operating environment that provides and enables the firmware to run dynamically. You can perform operations such as debugging, hooking, monitoring, and editing the firmware.
To be able to access and create a VM you must click on the dropdown arrow as seen below to switch from
Blue -> Green, green being the VM mode a state achieved after synchronizing the interfaces.
To enter the synchronization interface click
Sync Emulator seen below.
When the firmware synchronization is complete, you can see that the color of the firmware name in the Mode switch changes (turns green).
After entering Dynamic simulation a.k.a VM mode for this firmware you'll be able to create a virtual machine for it. As seen in the steps below.
If you've ever emulated firmware you'll know you often have to make modifications to
httpd.conf. In Shambles, you will typically have to change the hardcoded boot IP to
0.0.0.0 for the emulation to work properly. At times you'll also have to kill the webservers (
bao, etc.,) pid and restart it manually from within the SSH console which we will soon see. Here is a good Shambles article with commonly seen emulation debugging (to easily translate, append
.translate.goog after TLD (
.com) of the page).
If we have to make changes to the files of the Virtual Machine we'd have to do it through the static terminal as seen below. This can only be accessed in VM mode.
Once all the changes have been made, refresh the filesystem, and start the virtual machine. For this firmware, no modifications needed to be made for it to be emulated properly. We can go ahead and start the machine by clicking the play button.
Once we start the VM, a new panel will open containing verbose error messages, the boot processes, general tasking, logging, and output from the device's usage. After running this for a few seconds, we will want to see if the router started properly. We'll be able to see all of this by starting an SSH shell inside of Shambles to the emulated firmware by clicking the button seen below.
This will be a live interactive shell spawned from the emulated firmware as a mount flash from which an SSH will spawn.
Now we have an SSH shell on the running firmware being emulated we can check to see if the proper daemons have started and make sure the required processes are working fine. As seen below the router is up and running without any hiccups.
Our goal now is to validate our vulnerability with a tool such as Caido or Burp Suite. To do so we'll want to access the router through our browser. To achieve this we'll have to set up port forwarding. Here is a diagram of how the routing needs to flow.
As seen above port forwarding is not complicated. The virtual machine runs on a cloud host, so it is necessary to forward the network of the virtual machine first, and then establish a connection with the user's local machine. We will only want to forward port
80 for our router. So we will add a forward rule as seen below.
Here we are mapping port
80 which is webserver port inside of the VM to port
10040 in the
Setting panel. We then need to head over to the
Local Forward panel.
Then all we have to do is start the forward.
Voila! We've successfully emulated the firmware and can start interacting through the UI.
Now that everything is running smoothly we'll focus back on validating our two suspected vulnerabilities. We'll start off with the stack-based buffer overflow. Again we are sending a
canclePing action to
ping.ccp with a
nextPing value greater than
260 characters long.
Sending such a request crashes the application. If you try to send the request again you won't be able to since the initial BOF crashed the server which is basically an unauthenticated DOS BOF.
We can see from the main VM panel the system killed the
ping process causing the router to DOS due to it segfaulting as a result of our POST request of
canclePing with malicious
nextPage input. We can see from the image below that the stack is overwritten with
0x41 which is hexadecimal for
This BOF brakes the application completely so all we have to do is reboot the VM to get it working again.
I won't be covering this bug via the Shambles debugger. However, I can say I have absolutely no complaints about it. It does everything a debugger needs to do and more.
Now let's go ahead and validate the command injection vulnerability. We're invoking everything through the
doCheck function where our vulnerable input parameters are
ddnsUsername and our malicious input is going to be
;/bin/ps>/www/BlogDemoCommandInjection_Username.txt; respectively using
; as a command delimiter to escape the binary that's being run by
/bin/sh which is
Once our POST request is sent to the application, we can use Shambles SSH shell to validate that these files were created and contain
4316 bytes, the output of the
Moreover, we can see from the VM console log it's complaining that certain arguments weren't found. This is really useful for times when you're debugging or trying to get the proper syntax or escape for command injection.
Since we wrote the file to the webroot we're able to view our file in the browser as well.
Another class of vulnerability I've enjoyed discovering with Shambles is what I'd call "patch bypasses". I think it's more widely known as "patch diffing"; the process of cross-comparing the vulnerable and fixed versions of a product.
Exploiting old 0-day security patches is a great opportunity to learn and understand how vendors go about remediating vulnerability classes. I've come to realize that their implementations/fixes are often rushed and quite flawed. Typically, you would use awesome tools like BinDiff to accomplish this, however, Shambles offers a similar solution built in that I quite enjoy using.
To use this feature you must upload both firmware versions, the patched and the vulnerable one.
Once loaded into Shambles you'll have an expanded
Firmware Info now containing a
Similar Graph section as seen below.
You can have as many nodes as you have cloned instances of the modified firmware. Once you hit
Compare you'll be presented with the following view.
You can expand whatever package or binary you want to get additional information on. This includes but is not limited to functions that have changed as seen in the view below.
You can step into any of these and see the assembly changes.
Therefore it goes without saying, you can hit
TAB to obtain pseudocode to start understanding the patch.
This might not look powerful. However, once you start hunting for authentication bypass and start referring to old 0-day bypass you'll come to fully appreciate and use this functionality. For a dynamic demonstration of this feature check out H4kb4n's tweet 😃
A great way to enhance Shambles is through custom detection. Shambles has an engine called BinQL which allows you to create detection rules to further assist you in vulnerability discovery.
BinQL findings are appended to the
ELF Vulnerability Info findings which are potential vulnerabilities initially identified through Shambles basic vulnerability detection functions. As the name could have implied, you might think that it's an adaptation of CodeQL spun around for binary file retrieval. However, it isn't, BinQL is a custom truly proprietary innovation. BinQL is fully cloud-base. Therefore, once your uploaded firmware finished unpacking, BinQL can automatically carry out its detection processes. Custom detections can be formulated through the
Plugin menu seen below.
The reason you would use BinQL is because different vendors and firmware use different functions which can be vulnerable and not completely natively ingested by Shambles. Such as
exec_cste, etc., As mentioned, there are numerous input and output functions some unique to certain firmware, it is impractical for Shambles to natively identify and collect them all, as different devices may use different ones.
In other words, BinQL allows users to define templates for input and output functions which helps Shambles perform more customized checks and validations.
High level; BinQL works by reverse engineering the data flow at the Intermediate Representation (IR) level. By simulating its execution, the engine assesses if the user's input can modify the stack content, execute system commands, or perform file read/write operations. Obtaining user input is typically achieved by detecting common user input functions, such as
get_value, etc., Moreover, to determine if modifications to the stack are possible, Shambles look for functions like
memcpy, etc., which are defined in binql as output functions.
Once you open the binary of interest, select
Plugin -> Vulnerability -> Analysis the following web page will spawn.
Here is where you can enter your BinQL detection rules. These are rules you'd customize for the current binary. Once your rules are generated, click
Submit and your rules will submit to the cloud detection server where the status will display the status of cloud detection and cannot be resubmitted while running.
Here's how the detection rules work.
|Name of the function protocol
|Type of the return value
-1: IGNORE, current value type can be ignored
0: OP_PRINTF_FORMAT, current value type is output format
1: OP_IN, current value type is tainted input
2: OP_OUT, current value is tainted output
3: OP_SCANF_FORMAT, current value type is input format
4: BUFFER_LENGTH, current value type is buffer-related length
|Types of all parameters. Possible values are the same as above
|String used for matching
|Type of the current function
0: The current function serves as an input source
1: The current function can execute commands
2: The current function may cause buffer overflow
3: The current function is related to file access
We've previously identified that
get_entry_value_by_name can lead to a stack based buffer overflow. Ultimately it has the chance of passing user-provided input which may get pushed to the stack. We're looking to identify instances like these.
v1 = get_entry_value_by_name(p1, p2, "fromLan");
v41 = get_entry_value_by_name(p1, p2, "ddnsPassword");
v61 = get_entry_value_by_name(v1, v3, "WlanValue");
To accomplish this we must first understand what
get_entry_value_by_name(p1, p2, p3); means. So that we can assign the proper BinQL retValues which is extremely important. So,
get_entry_value_by_name is defined in
libleopard.so and named
get_entry_by_name finds the position of the
p3 in the
p1, this is not a stack overflow itself, but when the return value is used, there possibility that it will be pushed to a variable with an overflowable stack base. So the return value which is from the first parameters is referred to as
tainted output. The first parameter of this function will be referred to as
tainted input. The function
get_entry_value_by_name is a function produces input that can lead to a stack overflow. So it is an
input function. Therefore the BinQL configuration would be the following.
"paramList":[1, 4, -1],
Therefore, our query to further identify interesting
get_entry_value_by_name in the
ncc2 binary will be with the query below.
Server status is finished shambles
ELF Vulnerability Info panel will have the updated BinQL queried content.
To better help you understand BinQL we've provided a few examples as it can be a little confusing to first-time users. First, let's look at an example of marking
int * web_get(int *a1, int *key, int a3, int a4, int a5);
web_get is used to read parameters from the HTTP protocol. The first parameter is a pointer to all data, and the second parameter is the key of the data to be read. The return value is the required
tainted output value. The matching method is
web_get. Therefore our BinQL config will be in the following JSON format.
Now lets look at an example of marking
FILE * popen(const char *command, const char *type);
popen can execute commands. The first parameter is the
tainted input parameter, and the other parameters can be ignored. The matching method is
Lastly let's look at an example of marking
tainted input, and
char *strncpy(char *dest, char *src, int n);
strncpy can cause buffer overflow if used improperly. The first parameter is
tainted output, the second parameter is
tainted input, and the third parameter is the
length to be copied. The matching method is
After using BinQL, depending on the function protocol you've generated detection rules for you can expect to see a drastic increase in identified vulnerabilities.
That's it for now 🎉 you've made it to the end! There's A LOT of features and amazing quality-of-life hacks that I didn't cover. Make sure to join the Lian Security Discord to obtain early access to Shambles! If you want to see Shambles in action go watch me on Twitch!
I hope you liked the blog post. Check out https://liansecurity.com/ and all their products & offerings their engineers are genuinely top shelf.
Expect a lot more Shambles in future blog posts. Again I can't stress enough how massive of a time-save Shambles has been. The finalized pricing model will soon be official and stable. If you have questions or want to learn more about the tool send us a message on Discord or to me directly on Twitter and I'll pass on your questions or concerns.
Follow me on Twitter I sometimes post interesting stuff there too.
Thank you for reading!