Google loves easter eggs. It loves them so much, in fact, that you could find them in virtually every product of theirs. The tradition of Android easter eggs began in the very earliest versions of the OS (I think everyone there knows what happens when you go into the general settings and tap the version number a few times).
But sometimes you can find an easter egg in the most unlikely of places. Thereâs even an urban legend that one day, a programmer Googled âmutex lockâ, but instead of search results landed on foo.bar, solved all tasks and landed a job at Google.
The same thing (except without the happy ending) happened to me. Hidden messages where there definitely couldnât be any, reversing Java code and its native libraries, a secret VM, a Google interview â all of that is below.
One boring night I factory-reset my phone and got to setting it up again. First things first, a fresh Android install asked me to log into the Google account. And I wondered: how does the process of logging into Android even work? And the night suddenly became less boring.
I use PortSwiggerâs Burp Suite to intercept and analyze network traffic. The free Community version is enough for our purposes. To see the https requests we first need to install PortSwiggerâs certificate onto the device. As a testing device I picked an 8-year-old Samsung Galaxy S with Android 4.4. Anything newer than that and you might have issues with certificate pinning and stuff.
In all honesty, thereâs nothing particularly special with Google API requests. The device sends out information about itself and gets tokens in response⦠The only curious step is a POST request to the anti-abuse service.
After the request is made, among numerous very normal parameters there appears an interesting one, named droidguard_result. Itâs a very long Base64 string:
DroidGuard is Googleâs mechanism for detecting bots and emulators among real devices. SafetyNet, for example, also uses DroidGuardâs data. Google has a similar thing for browsers, too â Botguard.
But whatâs that data? Letâs find out.
What generates that link (www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI) and what inside Android makes this request? After a short investigation, it turned out that the link, in this exact form, is located inside one of Google Play Servicesâ obfuscated classes:
As weâve already seen in Burp, POST requests on this link have Content-Type â application/x-protobuf (Google Protocol Buffers, Googleâs protocol for binary serialization). Itâs not json, though â itâs difficult to uncover what exactly is being sent.
Protocol buffers work like this:
We have two ways to decode protobuf messages. The first one is to use a protobuf analyzer and try to recreate the original description of .proto files. The second is to rip out the protoc-generated classes out of Google Play Services, which is what I decided to do.
We take Google Play Servicesâ .apk file of the same version thatâs installed on the device (or, if the device is rooted, just take the file straight from there). Using dex2jar we convert the .dex file back into .jar and open in a decompiler of choice. I personally like JetBrainsâ Fernflower. It works as a plugin to IntelliJ IDEA (or Android Studio), so we simply launch Android Studio and open the file with the link weâre trying to analyze. If proguard wasnât trying too hard, the decompiled Java code for creating protobuf messages could just be copy-pasted into your project.
Looking at the decompiled code, we see that Build.* constants are being sent inside the protobuf message. (okay, that wasnât too hard to guess).
But unfortunately, in the serverâs reply all protobuf fields turned into alphabet soup after obfuscation. But we can discover whatâs in there using an error handler. Hereâs how data coming from the server is checked:
Apparently, thatâs how fields were called before obfuscation: byteCode, vmUrl, vmChecksum and expiryTimeSecs. This naming scheme already gives us some ideas.
We combine all the decompiled classes from Google Play Services into a test project, rename them, generate test Build.* commands and launch (imitating any device we want). If someone wants to do it himself, hereâs the link to my GitHub.
If the request is correct, the server returns this:
Step 1 complete. Now letâs see whatâs hidden behind the vmUrl link.
The link leads us directly to an .apk file, named after its own SHA-1 hash. Itâs rather tiny â only 150KB. And itâs quite justified: if itâs downloaded by every single one of the 2 billion Android devices, thatâs 270TB of traffic on Googleâs services.
Essentially,
The
To get a rough idea of whatâs going on inside
Then the
Itâs not hard to do. Weâll use smali/baksmali â assembler/disassembler for .dex files. After using it, classes.dex turns into a bunch of .smali files. The
Then we use backsmali to build it all back into .dex, and then we convert it into .jar. At the end we get a .jar file that we can use in our project â here it is, by the way.
The entire DroidGuard-related section is a couple of strings long. The most important part is to download the byte array we got in the previous step after addressing the anti-abuse service and hand it off to the
Now we can use Android Studioâs profiler and see what happens during DroidGuardâs work:
The initNative() native method collects data about the device and calls Java methods
Fortunately, analyzing the native library isnât any more difficult that doing it with .dex and .jar files. Weâd need an app similar to Hex-Rays IDA and some knowledge of either x86 or ARM assembler code. I chose ARM, since I had a rooted device lying around to debug on. If you donât have one, you could take an x86 library and debug using an emulator.
An app similar to Hex-Rays IDA decompiles the binary into something resembling C code. If we open the
Doesnât look too promising. First we need to make a couple of preliminary steps to transform that into something more useful. The decompiler doesnât know anything about JNI, so we install Android NDK and import the jni.h file. As we know, the first two parameters of a JNI method are
If we have enough patience to trace the byte array received from the anti-abuse server, weâll be⦠disappointed. Unfortunately, thereâs no simple answer to âwhatâs happening here?â. Itâs pure, distilled byte code, and the native library is a virtual machine. Some AES encryption sprinkled on top and then the VM reads the byte code, byte by byte, and executes commands. Every byte is a command followed by operands. There arenât many commands, only around 70: read int, read byte, read string, call Java method, multiply two numbers, if-goto etc.
I decided to go even further and figure out the structure of the byte code for this VM. Thereâs another problem with the calls: sometimes (once every couple weeks) thereâs a new version of the native library where byte-command pairs are scrambled. It didnât stop me and I decided to recreate the VM using Java.
What the byte code does is do all the routine work on collecting info about the device. For example, it loads a string with the name of a method, gets its address through dlsym and executes. In my Java version of the VM I recreated only 5 or so methods and learned to interpret the first 25 commands of the anti-abuse serviceâs byte code. On the 26th command the VM read another encrypted string from the byte code. It suddenly turned out that itâs not a name of another method. Far from it.
I told my findings on the email I found. To make results a little more impressive, I automated the analysis process a little bit. The thing is, strings and byte arrays are stored in the byte code encrypted. The VM decodes them using constants inlined by the compiler. Using an app similar to Hex-Rays IDA you could extract them pretty easily. But with every new version constants change and itâs fairly inconvenient to always extract them manually.
But Java-parsing the native library proved surprisingly simple. Using jelf (a library for parsing ELF files) we find the offset of the
In the end I got an app that emulated the entire DroidGuard process: makes a request to the anti-abuse service, downloads the .apk, unpacks it, parses the native library, extracts the required constants, picks out the mapping of VM commands and interprets the byte code. I compiled it all and sent it off to Google. While I was at it, I started preparing for a move and searched Glassdoor for an average salary at Google. I decided to not agree to anything less than six figures.
The answer didnât take long. An email from a member of the DroidGuard team simply read: âWhy are you even doing this?â
âBecause I canâ â I answered. A Google employee explained to me that DroidGuard is supposed to protect Android from hackers (you donât say!) and it would be wise to keep the source code of my DroidGuard VM to myself. Our conversation ended there.
A month later I received another email. The DroidGuard team in Zurich needed a new employee. Was I interested in joining? Of course!
There are no shortcuts to get into Google. All my contact could do was forward my CV to the HR department. After that I had to go through the usual bureaucratic rigmarole and a series of interviews.
Thereâs a lot of stories out there about Google interviews. Algorithms, Olympiad tasks and Google Docs programming arenât my thing, so I started my preparations. I read through the âAlgorithmsâ course of Coursera dozens of times, solved hundreds of tasks on Hackerrank and learned to get around a graph in both dimensions with my eyes closed.
Two months went by. To say I felt prepared would be an understatement. Google Docs became my favorite IDE. I felt like I knew everything there is to know about algorithms. Of course, I knew my weaknesses and realized I probably wouldnât pass the series of 5 interviews in Zurich, but going to the programmerâs Disneyland for free was a reward in and of itself. The first step was a phone interview to weed out the weakest of candidates and not waste times of Zurich developers on in-person meetings. The day was set, the phone rangâ¦
⦠and I immediately failed my first test. I got lucky â they asked a question Iâve seen on the internet before and have already solved. It was about serializing a string array. I offered to code strings in Base64 and save them through a divider. The interviewer asked me to develop a Base64 algorithm. After that the interview turned into sort of a monologue, where the interviewed explained to me how Base64 works and I tried to remember bit operations in Java.
3 days after the call I got an email saying they donât want to interview me further. And thatâs how my communication with Google ended.
Why there are messages in DroidGuard asking to chat, I still have no idea. Probably just for stats. The guy I wrote to in the first place told me that people actually write there, but the frequency varies: sometimes they get 3 replies in a week, sometimes 1 a year.
I believe there are easier ways to get an interview at Google. After all, you could just ask any of the 100,000 employees (though not all of them are developers, admittedly). But it was a fun experience nonetheless.
But sometimes you can find an easter egg in the most unlikely of places. Thereâs even an urban legend that one day, a programmer Googled âmutex lockâ, but instead of search results landed on foo.bar, solved all tasks and landed a job at Google.
Reconstruction
The same thing (except without the happy ending) happened to me. Hidden messages where there definitely couldnât be any, reversing Java code and its native libraries, a secret VM, a Google interview â all of that is below.
DroidGuard
One boring night I factory-reset my phone and got to setting it up again. First things first, a fresh Android install asked me to log into the Google account. And I wondered: how does the process of logging into Android even work? And the night suddenly became less boring.
I use PortSwiggerâs Burp Suite to intercept and analyze network traffic. The free Community version is enough for our purposes. To see the https requests we first need to install PortSwiggerâs certificate onto the device. As a testing device I picked an 8-year-old Samsung Galaxy S with Android 4.4. Anything newer than that and you might have issues with certificate pinning and stuff.
In all honesty, thereâs nothing particularly special with Google API requests. The device sends out information about itself and gets tokens in response⦠The only curious step is a POST request to the anti-abuse service.
After the request is made, among numerous very normal parameters there appears an interesting one, named droidguard_result. Itâs a very long Base64 string:
DroidGuard is Googleâs mechanism for detecting bots and emulators among real devices. SafetyNet, for example, also uses DroidGuardâs data. Google has a similar thing for browsers, too â Botguard.
But whatâs that data? Letâs find out.
Protocol Buffers
What generates that link (www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI) and what inside Android makes this request? After a short investigation, it turned out that the link, in this exact form, is located inside one of Google Play Servicesâ obfuscated classes:
public bdd(Context var1, bdh var2) {
this(var1, "https://www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI", var2);
}
As weâve already seen in Burp, POST requests on this link have Content-Type â application/x-protobuf (Google Protocol Buffers, Googleâs protocol for binary serialization). Itâs not json, though â itâs difficult to uncover what exactly is being sent.
Protocol buffers work like this:
- First we describe the structure of the message in a special format and save it into a .proto file;
- Then we compile .proto files, and the protoc compiler generates source code in a chosen language (in Androidâs case itâs Java);
- Finally, we use the generated classes in our project.
We have two ways to decode protobuf messages. The first one is to use a protobuf analyzer and try to recreate the original description of .proto files. The second is to rip out the protoc-generated classes out of Google Play Services, which is what I decided to do.
We take Google Play Servicesâ .apk file of the same version thatâs installed on the device (or, if the device is rooted, just take the file straight from there). Using dex2jar we convert the .dex file back into .jar and open in a decompiler of choice. I personally like JetBrainsâ Fernflower. It works as a plugin to IntelliJ IDEA (or Android Studio), so we simply launch Android Studio and open the file with the link weâre trying to analyze. If proguard wasnât trying too hard, the decompiled Java code for creating protobuf messages could just be copy-pasted into your project.
Looking at the decompiled code, we see that Build.* constants are being sent inside the protobuf message. (okay, that wasnât too hard to guess).
...
var3.a("4.0.33 (910055-30)");
a(var3, "BOARD", Build.BOARD);
a(var3, "BOOTLOADER", Build.BOOTLOADER);
a(var3, "BRAND", Build.BRAND);
a(var3, "CPU_ABI", Build.CPU_ABI);
a(var3, "CPU_ABI2", Build.CPU_ABI2);
a(var3, "DEVICE", Build.DEVICE);
...
But unfortunately, in the serverâs reply all protobuf fields turned into alphabet soup after obfuscation. But we can discover whatâs in there using an error handler. Hereâs how data coming from the server is checked:
if (!var7.d()) {
throw new bdf("byteCode");
}
if (!var7.f()) {
throw new bdf("vmUrl");
}
if (!var7.h()) {
throw new bdf("vmChecksum");
}
if (!var7.j()) {
throw new bdf("expiryTimeSecs");
}
Apparently, thatâs how fields were called before obfuscation: byteCode, vmUrl, vmChecksum and expiryTimeSecs. This naming scheme already gives us some ideas.
We combine all the decompiled classes from Google Play Services into a test project, rename them, generate test Build.* commands and launch (imitating any device we want). If someone wants to do it himself, hereâs the link to my GitHub.
If the request is correct, the server returns this:
00:06:26.761 [main] INFO d.a.response.AntiabuseResponse â byteCode size: 34446
00:06:26.761 [main] INFO d.a.response.AntiabuseResponse â vmChecksum: C15E93CCFD9EF178293A2334A1C9F9B08F115993
00:06:26.761 [main] INFO d.a.response.AntiabuseResponse â vmUrl: www.gstatic.com/droidguard/C15E93CCFD9EF178293A2334A1C9F9B08F115993
00:06:26.761 [main] INFO d.a.response.AntiabuseResponse â expiryTimeSecs: 10
Step 1 complete. Now letâs see whatâs hidden behind the vmUrl link.
Secret APK
The link leads us directly to an .apk file, named after its own SHA-1 hash. Itâs rather tiny â only 150KB. And itâs quite justified: if itâs downloaded by every single one of the 2 billion Android devices, thatâs 270TB of traffic on Googleâs services.
DroidGuardService
class, being part of Google Play Services, downloads the file onto the device, unpacks it, extracts .dex and uses the com.google.ccc.abuse.droidguard.DroidGuard
class through reflection. If thereâs an error, then DroidGuardService
switches from DroidGuard back to Droidguasso. But thatâs another story entirely.Essentially,
DroidGuard
class is a simple JNI wrapper around the native .so library. The native library's ABI matches what we sent in the CPU_ABI
field in the protobuf request: we can ask for armeabi, x86 or even MIPS.The
DroidGuardService
service itself doesnât contain any interesting logic for working with the DroidGuard
class. It simply creates a new instance of DroidGuard
, sends it the byteCode from the protobuf message, calls a public method, which returns a byte array. This array is then sent to the server inside the droidguard_result parameter.To get a rough idea of whatâs going on inside
DroidGuard
we can repeat the logic of DroidGuardService
(but without downloading the .apk, since we already have the native library). We can take a .dex file from the secret APK, convert it into .jar and then use in our project. The only issue is how the DroidGuard
class loads the native library. The static initialization block calls the loadDroidGuardLibrary()
method:static
{
try
{
loadDroidGuardLibrary();
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
Then the
loadDroidGuardLibrary()
method reads library.txt (located in the root of the .apk file) and loads the library with that name though the System.load(String filename)
call. Not very convenient for us, since weâd need to build the .apk in a very specific way to put library.txt and the .so file into its root. It would be much more convenient to keep the .so file in the lib folder and load that through System.loadLibrary(String libname)
. Itâs not hard to do. Weâll use smali/baksmali â assembler/disassembler for .dex files. After using it, classes.dex turns into a bunch of .smali files. The
com.google.ccc.abuse.droidguard.DroidGuard
class should be modified, so that the static initialization block calls the System.loadLibrary("droidguard")
method instead of loadDroidGuardLibrary()
. Smaliâs syntax is pretty simple, the new initialization block looks like this:.method static constructor <clinit>()V
.locals 1
const-string v0, "droidguard"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
return-void
.end method
Then we use backsmali to build it all back into .dex, and then we convert it into .jar. At the end we get a .jar file that we can use in our project â here it is, by the way.
The entire DroidGuard-related section is a couple of strings long. The most important part is to download the byte array we got in the previous step after addressing the anti-abuse service and hand it off to the
DroidGuard
constructor:private fun runDroidguard() {
var byteCode: ByteArray? = loadBytecode("bytecode.base64");
byteCode?.let {
val droidguard = DroidGuard(applicationContext, "addAccount", it)
val params = mapOf("dg_email" to "[email protected]", "dg_gmsCoreVersion" to "910055-30",
"dg_package" to "com.google.android.gms", "dg_androidId" to UUID.randomUUID().toString())
droidguard.init()
val result = droidguard.ss(params)
droidguard.close()
}
}
Now we can use Android Studioâs profiler and see what happens during DroidGuardâs work:
The initNative() native method collects data about the device and calls Java methods
hasSystemFeature(), getMemoryInfo(), getPackageInfo()
⦠thatâs something, but I still donât see any solid logic. Well, all that remains is to disassemble the .so file.libdroidguard.so
Fortunately, analyzing the native library isnât any more difficult that doing it with .dex and .jar files. Weâd need an app similar to Hex-Rays IDA and some knowledge of either x86 or ARM assembler code. I chose ARM, since I had a rooted device lying around to debug on. If you donât have one, you could take an x86 library and debug using an emulator.
An app similar to Hex-Rays IDA decompiles the binary into something resembling C code. If we open the
Java_com_google_ccc_abuse_droidguard_DroidGuard_ssNative
method, weâll see something like this:__int64 __fastcall Java_com_google_ccc_abuse_droidguard_DroidGuard_initNative(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
...
v14 = (*(_DWORD *)v9 + 684))(v9, a5);
v15 = (*(_DWORD *)v9 + 736))(v9, a5, 0);
...
Doesnât look too promising. First we need to make a couple of preliminary steps to transform that into something more useful. The decompiler doesnât know anything about JNI, so we install Android NDK and import the jni.h file. As we know, the first two parameters of a JNI method are
JNIEnv*
and jobject (this)
. We can find out the types of other parameters from DroidGuardâs Java code. After assigning the correct types, meaningless offsets turn into JNI method calls:__int64 __fastcall Java_com_google_ccc_abuse_droidguard_DroidGuard_initNative(_JNIEnv *env, jobject thiz, jobject context, jstring flow, jbyteArray byteCode, jobject runtimeApi, jobject extras, jint loggingFd, int runningInAppSide)
{
...
programLength = _env->functions->GetArrayLength)(_env, byteCode);
programBytes = (jbyte *)_env->functions->GetByteArrayElements)(_env, byteCode, 0);
...
If we have enough patience to trace the byte array received from the anti-abuse server, weâll be⦠disappointed. Unfortunately, thereâs no simple answer to âwhatâs happening here?â. Itâs pure, distilled byte code, and the native library is a virtual machine. Some AES encryption sprinkled on top and then the VM reads the byte code, byte by byte, and executes commands. Every byte is a command followed by operands. There arenât many commands, only around 70: read int, read byte, read string, call Java method, multiply two numbers, if-goto etc.
Wake up, Neo
I decided to go even further and figure out the structure of the byte code for this VM. Thereâs another problem with the calls: sometimes (once every couple weeks) thereâs a new version of the native library where byte-command pairs are scrambled. It didnât stop me and I decided to recreate the VM using Java.
What the byte code does is do all the routine work on collecting info about the device. For example, it loads a string with the name of a method, gets its address through dlsym and executes. In my Java version of the VM I recreated only 5 or so methods and learned to interpret the first 25 commands of the anti-abuse serviceâs byte code. On the 26th command the VM read another encrypted string from the byte code. It suddenly turned out that itâs not a name of another method. Far from it.
Virtual Machine command #26Thatâs strange. A virtual machine have never talked to me before. I thought that if you start to see secret messages directed to you, youâre going crazy. Just to make sure I was still sane, I ran a couple hundred of different answers from the anti-abuse service through my VM. Literally every 25-30 commands there was a message hidden within the byte code. They often repeated, but below are some unique ones. I edited the email addresses, though: each message had a different address, something like «[email protected]», with the tag being unique for each one.
Method invocation vm->vm_method_table[2 * 0x77]
Method vmMethod_readString
index is 0x9d
string length is 0x0066
(new key is generated)
encoded string bytes are EB 4E E6 DC 34 13 35 4A DD 55 B3 91 33 05 61 04 C0 54 FD 95 2F 18 72 04 C1 55 E1 92 28 11 66 04 DD 4F B3 94 33 04 35 0A C1 4E B2 DB 12 17 79 4F 92 55 FC DB 33 05 35 45 C6 01 F7 89 29 1F 71 43 C7 40 E1 9F 6B 1E 70 48 DE 4E B8 CD 75 44 23 14 85 14 A7 C2 7F 40 26 42 84 17 A2 BB 21 19 7A 43 DE 44 BD 98 29 1B
decoded string bytes are 59 6F 75 27 72 65 20 6E 6F 74 20 6A 75 73 74 20 72 75 6E 6E 69 6E 67 20 73 74 72 69 6E 67 73 20 6F 6E 20 6F 75 72 20 2E 73 6F 21 20 54 61 6C 6B 20 74 6F 20 75 73 20 61 74 20 64 72 6F 69 64 67 75 61 72 64 2D 68 65 6C 6C 6F 2B 36 33 32 36 30 37 35 34 39 39 36 33 66 36 36 31 40 67 6F 6F 67 6C 65 2E 63 6F 6D
decoded string value is (You're not just running strings on our .so! Talk to us at [email protected])
[email protected]: Don't be a stranger!Am I the Chosen One? I thought that it was time to stop messing with DroidGuard and talk to Google, since they asked me so.
You got in! Talk to us at [email protected]
Greetings from [email protected] intrepid traveller! Say hi!
Was it easy to find this? [email protected] would like to know
The folks at [email protected] would appreciate hearing from you!
What's all this gobbledygook? Ask [email protected]⦠they'd know!
Hey! Fancy seeing you here. Have you spoken to [email protected] yet?
You're not just running strings on our .so! Talk to us at [email protected]
Your call is very important to us
I told my findings on the email I found. To make results a little more impressive, I automated the analysis process a little bit. The thing is, strings and byte arrays are stored in the byte code encrypted. The VM decodes them using constants inlined by the compiler. Using an app similar to Hex-Rays IDA you could extract them pretty easily. But with every new version constants change and itâs fairly inconvenient to always extract them manually.
But Java-parsing the native library proved surprisingly simple. Using jelf (a library for parsing ELF files) we find the offset of the
Java_com_google_ccc_abuse_droidguard_DroidGuard_initNative
method in the binary, and then using Capstone (a disassembling framework with bindings for various languages, including Java) we get assembler code and search it for loading constants into registries.In the end I got an app that emulated the entire DroidGuard process: makes a request to the anti-abuse service, downloads the .apk, unpacks it, parses the native library, extracts the required constants, picks out the mapping of VM commands and interprets the byte code. I compiled it all and sent it off to Google. While I was at it, I started preparing for a move and searched Glassdoor for an average salary at Google. I decided to not agree to anything less than six figures.
The answer didnât take long. An email from a member of the DroidGuard team simply read: âWhy are you even doing this?â
âBecause I canâ â I answered. A Google employee explained to me that DroidGuard is supposed to protect Android from hackers (you donât say!) and it would be wise to keep the source code of my DroidGuard VM to myself. Our conversation ended there.
Interview
A month later I received another email. The DroidGuard team in Zurich needed a new employee. Was I interested in joining? Of course!
There are no shortcuts to get into Google. All my contact could do was forward my CV to the HR department. After that I had to go through the usual bureaucratic rigmarole and a series of interviews.
Thereâs a lot of stories out there about Google interviews. Algorithms, Olympiad tasks and Google Docs programming arenât my thing, so I started my preparations. I read through the âAlgorithmsâ course of Coursera dozens of times, solved hundreds of tasks on Hackerrank and learned to get around a graph in both dimensions with my eyes closed.
Two months went by. To say I felt prepared would be an understatement. Google Docs became my favorite IDE. I felt like I knew everything there is to know about algorithms. Of course, I knew my weaknesses and realized I probably wouldnât pass the series of 5 interviews in Zurich, but going to the programmerâs Disneyland for free was a reward in and of itself. The first step was a phone interview to weed out the weakest of candidates and not waste times of Zurich developers on in-person meetings. The day was set, the phone rangâ¦
⦠and I immediately failed my first test. I got lucky â they asked a question Iâve seen on the internet before and have already solved. It was about serializing a string array. I offered to code strings in Base64 and save them through a divider. The interviewer asked me to develop a Base64 algorithm. After that the interview turned into sort of a monologue, where the interviewed explained to me how Base64 works and I tried to remember bit operations in Java.
If anyone at Google is reading this
Guys, youâre bloody geniuses if you got there! Seriously. I canât imagine how one can clear all the obstacles they put in front of you.
3 days after the call I got an email saying they donât want to interview me further. And thatâs how my communication with Google ended.
Why there are messages in DroidGuard asking to chat, I still have no idea. Probably just for stats. The guy I wrote to in the first place told me that people actually write there, but the frequency varies: sometimes they get 3 replies in a week, sometimes 1 a year.
I believe there are easier ways to get an interview at Google. After all, you could just ask any of the 100,000 employees (though not all of them are developers, admittedly). But it was a fun experience nonetheless.