My Authors
Read all threads
Okay, so I've been taking a look at #TraceTogether over the weekend, to see what I could find. This is still very preliminary, but since there's a lot of chatter about it, I decided to write something up on whatever I have so far.
First, a disclaimer: I've not had a lot of time to look at it (weekend time is spent with the kids), and I have limited experience looking at Android apps, especially modern ones.
I also only did a static analysis as that's what I'm better at, and I didn't want to spend a day setting up a phone for dynamic analysis.
So, a lot of what I'm saying might be wrong, or partially wrong; I'm putting this up on Twitter so people can correct me on any mistakes!
Oh, and it seems they just released an updated version. I'll look at it later.
They've also announced that they're going to open source the code, which is great news. And while I'm going to continue reversing just because it's what I like to do, it'd be useful to audit the source as well, once it is out.
On to the details. Like I said, I only did a static analysis. I used apktool and JEB (@jebdec) to open up the sg.gov.tech.bluetrace APK. AndroidManifest seems normal, nothing weird there.
In JEB, there are several classes, mostly UI related. Code was written in kotlin; means it'll look messier when decompiled to Java. There's a package gov.tech.bluetrace.streetpass, which has some database code, and is probably where the records are kept. KIV.
What I did notice immediately, though, was many obfuscated classes. I'll talk more about this later.
So anyway, I decided to first verify something that a lot of people have been wondering about: does the app collect location info? @GovTechSG has sumpah-ed that it doesn't, but better double check.
I grepped for any part of the code that uses LocationManager. Not many hits.
getLastKnownLocation() was called a few times though, but after a quick look, they were false positives.
One was to check latitude and longitude to determine sunrise and sunset timings, and turn on night mode. (srsly)
The other was to gather info for analytics. They're using Snowplow, which I'm not familiar with. I've not verified how the info is gathered or sent out.
Now, you could consider this a problem, but i think it's kind of standard issue in many apps nowadays? Also I've heard from people who've used frida to hook on getLastKnownLocation() that it doesn't seem to be called that often.
Next, the obfuscation. This was more than I'm used to seeing (but maybe I'm just not up to speed). Besides renaming classes and packages, it also messes up the call graph by using a function that dynamically dispatches method calls based on some string values.
The function, which I've renamed 'obfcall', does some convoluted maths on its 3 arguments before deriving a string (v8_5), which is the name of the class to be loaded using Class.forName(). Since class names have been obfucated, this string is just a few characters long.
The same is done for the method name, and finally the method is called, with arguments whose values are mostly derived from the arguments to obfcall().
From some cursory research, the obfuscator I'm looking at is probably DexGuard, a commercial version of ProGuard.
Now, obfuscation can be defeated. It's possible to reconstruct the call graph and determine what the function being called for each invocation of obfcall() is. But, it's hella irritating, and will take a while. I've decided not to spend time reversing that.
(It's also a lot easier to use dynamic analysis to resolve the function calls, which I'm not doing yet.)
Unfortunately, a lot of the core functionality of TraceTogether seems to be in the obfuscated region, and blocked by the aforementioned obfuscation techniques. For example, the function called on boot is protected by the obfcall() function.
One of my goals reversing #TraceTogether was to get some assurance that it wasn't doing anything odd. There was that Iranian coronavirus app that appeared to be spyware; could this be the same? Personally, I doubt so, but I can't confirm that without undoing the obfuscation.
TraceTogether also comes with a native library, libb.so. I had a look at it in IDA, and it uses obfuscation as well, mostly on strings. For example, the string "/proc/%d/status" is obfuscated using a kind of substitution cipher based on the previous character.
Now, to be honest, if I were tasked to do an audit on an app that looked this way, at this point I'd tell the customer to wait, till I managed to reverse it more thoroughly. But in present circumstances, if a regular person asked me if they should install it, I'd still say yes.
Why? Well, mostly faith that the people who put this together are not lying. I also think they'd be kind of dumb to subject an app to this level of global scrutiny if there was something questionable within it.
Furthermore, if you're a regular Singaporean: 1. the govt is probably not so interested in you that they'd want to backdoor your phone, and 2. you probably have Parking.sg or SingPass mobile installed, in which case you're already pwned, it's not going to make a diff
And the benefits of many people using #TraceTogether outweigh the possible risk it might hold. COVID-19 is a big deal.
But if you have legit reason to worry about the government monitoring your phone, then yeah I wouldn't laugh at you for playing it safe for now. (Note: posting copious amounts of anti-PAP tirades on EDMW/reddit doesn't count as a legit reason)
Now that TraceTogether is being open sourced, and that third party clients are encouraged, there's even less reason to be suspicious.
That being said, I do feel that the obfuscation in #TraceTogether is unnecessary and unhelpful. Especially if you're going to open source it; things like DexGuard are meant to protect intellectual property, so why use it for code you're going to release?
I took a look at .Parking.sg, and it doesn't appear to obfuscate any of the code. Maybe the specific team in GovTech that developed TraceTogether just likes to obfuscate by default?
I would really recommend they release a new version without obfuscation, even after the source is available. That way, 3rd party auditors can verify that the Play Store version matches up with the source and doesn't contain anything weird. That would put all worries to rest.
Finally, I still have one other concern about #TraceTogether, which is how secure it is. The app implements a BLE server that listens for requests from other phones, and parses them. Any chance of SweynTooth-style attacks compromising nearby phones running TraceTogether?
This is what I'm focusing on now. Will update when I find out more. If the source is out by then I'll probably switch to reading it instead.
Ok that's it, I'm going to bed.
Decided to give a summary for this part: @GovTechSG isn't lying. #TraceTogether doesn't save your location, or send it to a server. But it has an analytics component that might, in particular scenarios (e.g. when the app crashes).
Frank L. here did some reversing of the app too, and went deeper into the database and storage components. medium.com/@frankvolkel/t…
Missing some Tweet in this thread? You can try to force a refresh.

Enjoying this thread?

Keep Current with zerotypic

Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!