Friday, July 3, 2015

increase soundcloud cache

tl;dr: i can't link to the apk because i'm not getting banned for you. you can repeat these steps yourself if you're interested. i can't stop anyone from posting a link in the comments. sorry!


soundcloud used to let you cache a lot of songs for offline listening. then they took it away. i'm half sure they have some reason for doing it that has vaguely to do with money dollars. but, hey, when you have a nice feature and you take it away, peeps get mad. the mad peeps are here: (warning, internet drama)

many users recommend downloading 2.8.3, which you can find in the crybaby fest linked above. personally, i'm not content rolling with an ancient version like some bucolic hillbilly. nah. i must break the latest version and get all those sweet sweet features.

compare old and new

i reckoned the best way to find where the cache was controlled would be to compare 2.8.3 and 2.8.4, where it changed. maybe there was just a setting somewhere they changed, or a number was reduced from "big" to "tiny". here's how i did it:

  1. acquire 2.8.3 and 2.8.4. former was in link above, latter was from play store. i used this extension to download from play
  2. convert apks to jars with enjarify
  3. use latest jd-gui to get java for whole app (file -> save all sources)
  4. use diff -rq <dir1> <dir2> to get a sense of what changed
  5. give up on diff inspection because delta was huge
  6. randomly search for "cache" in 2.8.3
thank you soundcloud, for not obfuscating your app at all. it was much easier to find what i was looking for with class and variable names. it takes about an hour to setup proguard such that you still get debugging symbols, but hey, whatever, right?

found some likely places for cache control in 2.8.3, but it looked like there was an api rewrite between 2.8.3 and 2.8.4, so even if i found it, it wouldn't help me, because none of that code was used in later versions.

enjarify is supposed to be this snazzy new dex -> java class conversion tool. the results were "meh". i'm sure it's going to be very good eventually, and i have more faith in the professionalism of the devs of enjarify than, say, other devs.

educated guess searching

started searching around for the word "cache". there's quite a lot of caching going on. i poked around a few files that looked like they were just setting up LRU caches for something, and those looked promising, but then i found: Lcom/soundcloud/android/playback/CacheConfig;.


public class CacheConfig

  // ~524 megs
  static final long MAX_SIZE_BYTES = 524288000L;

  // ~63 megs, aka "fuck you lol"
  static final long MIN_SIZE_BYTES = 62914560L;

  public static long getCacheSize(@Nullable String country) {
    if ((ScTextUtils.isBlank(country)) || (Locale.US.getCountry().equalsIgnoreCase(country))
        || (Locale.GERMANY.getCountry().equalsIgnoreCase(country))
        || (Locale.FRANCE.getCountry().equalsIgnoreCase(country))
        || (Locale.UK.getCountry().equalsIgnoreCase(country))) {
      return MIN_SIZE_BYTES;

    return MAX_SIZE_BYTES;


boom sha ka la ka. this must be it. if you're in the US, Germany, France, or UK, you get burned with a tiny, micro cache. here's what the fix looks like:
.method public static getCacheSize(Ljava/lang/String;)J
    .registers 3
    .param p0    # Ljava/lang/String;
        .annotation build Landroid/support/annotation/Nullable;
        .end annotation
    .end param

    .line 15
    # return "totally random" number, 555555
    const-wide/32 v0, 0x4fb10040
    return-wide v0

    invoke-static {p0}, Lcom/soundcloud/android/utils/ScTextUtils;->isBlank(Ljava/lang/String;)Z
    # ...

unfortunately, this creates new problems. as soon as you modify the code, you have to update the dex. if you update the dex, you break the signature and have to resign. if you resign, it breaks facebook logins, and probably some other stuff, because they uses signatures to generate a token that identifies which app is trying to do the login. luckily, antilvl knows how to handle spoofing signatures.

Monday, December 8, 2014

Simplify - Android Deobfuscator / Decryptor

Here it is:
I'd build you a jar, but there have been a lot of commits recently, and you'll probably want to build it yourself.

It decrypts most types of string encryption and can remove some types of obfuscation, especially code that doesn't actually do anything.

This may be all you want to know. But this has got me thinking about optimization and deobfuscation, so continue on if you're into that sort of thing.

App obfuscation and string encryption are getting more popular, and they can be annoying as fuck. But, fundamentally, obfuscators just apply a set of rules to code, and the rules aren't that complex, because complex is really hard. It's just a thin layer of changes added on top. Intuitively, this means a general solution for undoing the changes probably takes a little more effort to undo than it did to conceive the original rules. So no matter how bad things get for crackers, it should always be possible to make a tool to fix things up.

In the PC scene, obfuscators are more evolved, but so are the deobfuscators. Just look at the feature list on this: It's a deobfuscator and an unpacker, plus it supports a huge list of stuff.

There are a few tools like this for Android, but they are not nearly as complex (yet). Time for bullet points!
Simplify deobfuscates by virtually executing an app and analyzing the execution afterwards. So if there is an encrypted string that gets decrypted at run time, Simplify will see the encrypted, see it passed to the decryption method, and see it get get decrypted. And after it knows the value, it can remove the encrypted value and the decryption method call as redundant and replace it with a 'const-string' instruction with the decrypted literal.

It's not all the way cooked yet, but the idea is solid, and there are some interesting issues github page I'd quite like to see implemented. One of them is deobfuscating reflection.

Also, anyone who takes the time to create issues on github and follow through with closing them when they're resolved, is probably more than a little obsessive. Should be fun to watch.

Saturday, September 20, 2014

Things Look Different

After a bunch of people told me how much the black background + white text was murderizing their eyes, I decided a bunch of people didn't appreciate my enlightened aesthetic sensibilities. Today's blog layout change to a white background + black text is in no way me admitting I was wrong.


Unpacking APKProtect, Bangcle, LIAPP, Qihoo

Android packers getting more common, and if you're doing any significant amount of reversing, you're bound to come across one. While any serious reverser should 1.) familiarize themselves with how they work,  2.) unpack a few by hand, and 3.) write their own tool, it's always nice to kick back and pull something off the shelf. Or, at least, learn how someone else is doing it.

For this reason, I'd like to share with you the provocatively named android-unpacker from strazzere. Nothing says "i write c code" like a blunt and unambiguous project title!

From the readme, it already supports a few popular unpackers:
  • Bangcle (SecNeo)
  • APKProtect
  • LIAPP (preprelease demo)
  • Qihoo

Thursday, March 20, 2014

jadx - Dex to Java decompiler

there's a new decompiler on the block. it targets dex directly, rather than java class bytecode, so it doesn't rely on dex2jar. i'm pleased by it's performance so far, and it's worth checking out:
  • it's mostly a cli, with a simple, "experimental" gui.
  • it takes dex or jar files as input
  • it can make a control flow graph.
  • output is configurable -- you can chose to have "simple" branching, where it wont try to be smart about how it decompiles conditionals and loops. this can actually be much easier to read than jd-gui's pervasive "while(true) //a bunch of stuff" constructs.

GitHub page curiously lacking in GUI money-shot

Thursday, February 13, 2014

Native Protection & Mono by Nihilus

another interesting tutorial from Nihilus. here's the description from the guide:
this tutorial covers a basic understanding of the Mono/Xamarin for Android, specifically how C#/.NET is used lately to protect games and, who knows, even malwares.
here's the link:!jpwkTY4J!eXzXCngQAPlUjVvJtiSzEbSxqEv8EbYmMqaLTFxF01Q (updated 5/21/2015)

  i was not aware of this ability to run mono code on android and found it interesting.

related to this, wine is on the way for android. this could get interesting.

Wednesday, February 12, 2014

zerdei's luyten, a worthwhile jd-gui alternative

if you use dex2jar + jd-gui and you find the results less than satisfying, that's normal. jd-gui hasn't been updated in at least 100 years. methods often fail to compile and blocks of code are sometimes omitted.

luyten, by deathmarine, which you can get here: is a front end for procyon, a java decompiler. procyon+luyten has a higher success rate for decompiling methods in my experience, and has higher fidelity output, though it's more verbose. the UI isn't that great, but this pull request by zerdei includes several noteworthy improvements:

feel free to clone and build the jar yourself, but if you're lazy, and somewhat trusting, i built this for you!!K95RlRiB!ak2DWRxC2DgPYDic0eDpQibAuGtIoFZGtU67GzyjEjM