Skip to main content

Command Palette

Search for a command to run...

Part I: Triaging Blueborne From Stripped Binary

Updated
7 min read
Part I: Triaging Blueborne From Stripped Binary
A

I am an experienced Vulnerability Researcher and Security Architect with 16+ years of experience in various verticals and horizontals, be it consumer electronics, semiconductors, automotive or other. Having started in software engineer in low-level embedded devices from writing applications to kernel drivers on various operating systems and then moving to my real calling i.e. hacking. Love to stick to the older golden days of game hacking, BBS, shareware, phreaking, phrack, virus era, metal music, cheats and many more such cool stuff from the underground. I wear many hats from time to time as necessary - but I also love to help people and organizations to deal with the core cybersecurity issues and not provide them a checklist with a presentation. Opinions and posts on my site are purely my own and do not reflect my work.

I remember back when I was working with a major Infotainment supplier in a very then recently formed security team, one of the agenda for us was to check if something that comes up online as a security blog/vulnerability/hack/talk etc and map that to our existing portfolio of devices and the software stacks they might use. It was easier said than done, as most of the companies including ours did not have a detailed centralized inventory of what our products were using in software stacks or hardware so that we can run a couple of search queries and find which product in development and field were affected, so stuff had to be done manually. And then we got a signal for a set of vulnerabilities affecting the Bluetooth Stack and Kernel probably used by millions if not billions
Blueborne vulnerabilities and Exploits from Armis are really cool and probably they were found out by years of source code audit and experimentation and there were several vulnerabilities, 8 to be precise ! According to Armis, around 8.2 billion devices would be affected !!

  • 1. Linux​ ​kernel​ ​RCE​ ​vulnerability​ ​-​ ​CVE-2017-1000251

  • 2. Linux​ ​Bluetooth​ ​stack​ ​(BlueZ)​ ​information​ ​Leak​ ​vulnerability​ ​-​ ​CVE-2017-1000250

  • 3. Android​ ​information​ ​Leak​ ​vulnerability​ ​-​ ​CVE-2017-0785

  • 4. Android​ ​RCE​ ​vulnerability​ ​#1​ ​-​ ​CVE-2017-0781

  • 5. Android​ ​RCE​ ​vulnerability​ ​#2​ ​-​ ​CVE-2017-0782

  • 6. The​ ​Bluetooth​ ​Pineapple​ ​in​ ​Android​ ​-​ ​Logical​ ​Flaw​ ​CVE-2017-0783

  • 7. The​ ​Bluetooth​ ​Pineapple​ ​in​ ​Windows​ ​-​ ​Logical​ ​Flaw​ ​CVE-2017-8628

  • 8. Apple​ ​Low​ ​Energy​ ​Audio​ ​Protocol​ ​RCE​ ​vulnerability​ ​-​ ​CVE-2017-14315

In this article/series we will focus on the first two -​ CVE-2017-100025 and ​CVE-2017-1000251

​CVE-2017-1000251 is a information leak vulnerability so i thought it should be relatively possible to find in the binary where the vulnerability is present as we have all the details related to the code, the patch and exact versions of the software, namely Bluez version 5.46. The source code patch is available here in version 5.46
With that being said, generally there are two ways to find out if this affects you -

  1. You have an inventory or SBOM of the products with the software’s used inside it with versions of all the libraries, stacks, vendor stacks (generally no) etc

  2. Find out from the binary blog? What?

In the first case, if you have this then you are a pro otherwise you are in the same queue as majority of vendors.
In the second one, when people build stuff, its generally good to optimize the code and remove the symbols from the builds to ensure less size, as the processor don’t care if you have symbols or not, all it care is binary code and stripping a binary or library from its symbols and debug information for production devices that are shipped is a good practice. When you want some debug ability let’s say during development you need to know where your shit crashed and with some logs would be good. But this causes a problem to track something that is in the field if it’s pure binary data -
Now to identify if Blue Borne is part of your device stack or not is based on the above two approaches. Therefore, for an investigation team like a Product Security Team, it would be important that they analyse all the assets to look for something that looks like Blue borne purely from stripped binary data and this is how it looks.

Stripped-Binary-Decompilation

Now, what the flying fuck is this, said Tyson Benson one day.

How can someone not so experienced with reverse engineering look for something like this a multitude of stripped and packed code throughout a set of products portfolios?

Now here is a sane compiled from source with symbols versions of the same stub

Decompilation-When-We-Have-Symbols

Imagine how much easier would it be triage this if only we had debug symbols - In some cases, you took this from someone else, and he deleted all the symbols before sending it to you and in other you might still have them if this was part of some random team from your company.

Triaging this when you are symbol blind seems like a mission for the IMF !!

But wait - then how do you actually triage this ?

Let me take a diversion here to show you how compiler plays tricks on you when you want to load some binaries in Ghidra and try to find it where the hell is that stub function ?

I started to build out an environment to compile Bluez 5.46 from source code and after running into some compiler warnings and error of the kind like redefinition of function in some files on the newest ubuntu, i found the newest include files from Libc defined some functions differently that were used in this version of BlueZ - idk whatever , so i decided to use Ubuntu 16.04 as some guy used this to build an exploit for these vulnerabilities, hence i switched to a server version of Ubuntu 16.04 and the shit compiled out of the box.
Cool, who really configures the codebase when you are just playing around, so i let it build with default options. Then loaded the built object code for the src/bluetoothd-sdpd-request.o in ghidra and to my surprise the function(service_search_attr_req) where the vulnerability exists would’t show up in the function listing — why ? I had no idea. This is probably should have been intuitive for me but not one of my best days. So i went a little deeper.
The actual code where the vulnerability resides according to Armis’s documentation looks something like this so the function service_search_attr_req must be there in the file src/sdpd-request.c

Actual-Code - Can you spot/guess the vulnerability ?

The function after compiling matched on below files as one would expect, specifically the object file src/bluetoothd-sdpd-request.o

But it does’’t show up in readelf symbols, nm or any other tools including Ghidra.

After seeing this i was like wow - generally, this function is part of the compiler optimization hence the function got removed or something else happened ?

Ghost Input: Compiler optimizations have killed more RE’s in an hour than titanic !

The solution is simple, the compiler optimized this and in-lined this function within the same file from where this is called depending on level of optimization, this is completely terrible when reverse engineering as it is hard to understand where is what and is a point of confusion and this is most probably how it will be in production release version, in-lined, optimized, and stripped of any debug info to give you a hint. As this is an exercise, lets simplify this a little bit.
We recompile the code but with no optimization so that the service_search_attr_req is visible as a separate function and we can create a call graph.

./configure CFLAGS="-O0 -fno-inline -g"

Once we have the object file with no compiler optimizations, things look a little better and we can find the function now because we told the compiler to ignore optimization. This should have been picked up by me earlier.

So based on the data from Armis, lets try to prepare a Path to reach this function purely initially from the debug version binary file and then with stripped binary file as it will be in production - good for you if it has debug (some)symbols in production.

If with debug symbols a small call tree would look like this -

The start of Process request with its address - 0×00101a7a

Similarly for handle internal request at 0×101d56

and also for handle_request at 0×101e1f

Therefore taking stuff from debug versions to compare the symbols and functions from the not optimsed compiled object file refer to the same function calling tree - Yay ! as seen from below

Could this mean there is a way to do this ? Probably yes, here we recompiled our codebase to show us independent functions stub so we can better trace in Ghidra. May be using this method, you can probably pin point if your older compiled binary based shit is valid or not for a given vulnerability.
Knowing a vulnerability and the path it takes can be used effectively to somehow counter “Are we affected with this godforsaken bug ?”, the above method is very trivial when done manually and only takes an hour or so for an experienced researcher doing stuff manually.

Relying on addresses is not a good way, as a small change will change these offsets.

It is totally possible that other methods to do this exists and are much better, maybe someone would have made a plugin for Ghidra or Binja for this idk. Please note we have not covered how to trace when the compiler optimizations are in place and functions are in-lined, perhaps we will do it in the next article.
The lingering question still remains, will this help the not-so-reverse-engineery analyst Tyson B pinpoint, confirm and triage this purely from a binary.

Stay Tuned for Part II.

Note: For professional queries and projects, reach out to me at abhijit.lamsoge@outlook.com

Title image and Tyson’s(He looks much better than this guy) image is generated by AI.

Ghidra Punisher

Part 1 of 1

Here we will cover some interesting items from Ghidra when used in a professional settings and advanced Ghidra Reversing Write Ups and Unknowns