
O Google adora ovos de páscoa. Ele ama tanto que você pode encontrá-los em quase todos os produtos da empresa. A tradição dos ovos de Páscoa no Android se estende desde as primeiras versões do sistema operacional (acho que todo mundo sabe o que acontecerá se você clicar na linha com a versão do Android várias vezes nas configurações).
Mas também acontece que os ovos de Páscoa são encontrados nos lugares mais inesperados. Existe até uma lenda: uma vez que o programador google “mutex lock” e, em vez dos resultados da pesquisa, chegaram à página
foo.bar , resolveram todos os problemas e conseguiram um emprego no Google.
Aqui está a mesma história incrível (só que sem um final feliz) aconteceu comigo. Mensagens ocultas onde elas certamente não podem estar, código Java reverso e bibliotecas nativas, uma máquina virtual secreta, uma entrevista no Google - tudo isso sob o corte.
Droidguard
Em uma noite entediante, fiz um reset de fábrica e comecei a reconfigurar o smartphone. Primeiro de tudo, o Android novo pediu para eu entrar na minha conta do Google. "Interessante, mas como acontece o registro e o login no Android?", Pensei. A noite deixou de ser lânguida.
Para interceptar e analisar o tráfego, eu uso o Burp Suite do PortSwigger. Uma versão comunitária gratuita será suficiente. Para que possamos ver solicitações https, primeiro você precisa instalar um certificado do PortSwigger no dispositivo. Para os testes, encontrei nas minhas caixas um Samsung Galaxy S de oito anos com Android 4.4 a bordo. Se você tiver algo mais atualizado, poderá ter problemas com a https: fixação de certificados e tudo mais.
De fato, não há nada de particularmente interessante no acesso à API do Google. O dispositivo envia dados sobre si mesmo, em troca recebe tokens ... O único momento incompreensível é a solicitação POST ao serviço antiabuso.

Após essa solicitação, entre os parâmetros não dignos de nota, aparece um misterioso, com o nome
droidguard_result . É uma string Base64 muito longa:
O DroidGuard é um mecanismo do Google para separar bots e emuladores de dispositivos reais. O SafetyNet também usa dados do DroidGuard em seu trabalho. O Google tem uma coisa semelhante para navegadores - Botguard.
Mas ainda assim, o que são esses dados, o que é transmitido nele? Agora vamos entender.
Buffers de protocolo
De onde vem o link
www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI , exatamente quem faz essa solicitação no sistema Android? É fácil descobrir que esse link está diretamente armazenado neste formulário em uma das classes ofuscadas do Google Play Services:
public bdd(Context var1, bdh var2) {
this(var1, "https://www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI", var2);
}
Burp,
Content-Type POST —
application/x-protobuf (Google Protocol Buffers, Google). json, — , .
protocol buffers :
- .proto
- .proto , protoc ( Android Java)
protobuf . — - protobuf .proto . — protoc- Google Play Services. .
apk Google Play Services , ( , apk ). dex2jar .dex .jar . Fernflower JetBrains. IntelliJ IDEA ( Android Studio), Android Studio . proguard , Java protobuf .
, protobuf Build.* (, ):
...
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);
...
, , protobuf . , . , :
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");
}
, :
byteCode,
vmUrl,
vmChecksum expiryTimeSecs. .
Google Play Services , , Build.* ( ). - ,
.
:
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
. ,
vmUrl.apk
.apk , SHA-1 . apk — 150 . : Android , 270 .

DroidGuardService
, Google Play Services, , , .dex .so , reflection,
com.google.ccc.abuse.droidguard.DroidGuard
. - ,
DroidGuardService
DroidGuard Droidguasso. Droidguasso — .
,
DroidGuard
— JNI .so . ABI , protobuf
CPU_ABI
: armeabi, x86, mips.
DroidGuardService
-
DroidGuard
.
DroidGuard
,
byteCode protobuf , , .
droidguard_result.
,
DroidGuard
DroidGuardService
( apk, ). .dex APK, .jar . ,
DroidGuard
.
loadDroidGuardLibrary()
:
static
{
try
{
loadDroidGuardLibrary();
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
,
loadDroidGuardLibrary()
library.txt ( .apk )
System.load(String filename)
. , - apk, library.txt .so . .so lib
System.loadLibrary(String libname)
.
.
smali/baksmali — / dex . classes.dex .smali .
com.google.ccc.abuse.droidguard.DroidGuard
,
System.loadLibrary("droidguard")
loadDroidGuardLibrary()
. smali , :
.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
baksmali .dex, .jar. jar , . ,
.
DroidGuard
. — , anti-abuse
DroidGuard
.
private fun runDroidguard() {
var byteCode: ByteArray? = loadBytecode("bytecode.base64");
byteCode?.let {
val droidguard = DroidGuard(applicationContext, "addAccount", it)
val params = mapOf("dg_email" to "test@gmail.com", "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()
}
}
Android Studio , DroidGuard.

initNative()
java-:
hasSystemFeature(), getMemoryInfo(), getPackageInfo()
… -, . , , .so .
libdroidguard.so
, , .dex .jar . , Hex-Rays IDA arm x86, . arm, . , x86 .
, Hex-Rays IDA, - c-.
Java_com_google_ccc_abuse_droidguard_DroidGuard_ssNative
, :
__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);
...
. , . JNI, Android NDK jni.h. , JNI —
JNIEnv*
jobject (this)
. Java DroidGuard. , JNI :
__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);
...
, anti-abuse , . , « ?» . -, — . AES , - . — , . , 70: int, byte, , java , , if-goto .
Wake up, Neo
- . : ( ) , . , Java.
- . , , dlsym . java 5 25 - anti-abuse . 26- -. , .
Virtual Machine command #26
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 droidguard@google.com)
, . , , . , , anti-abuse -. 25-30 - . , . , , . «droidguard+tag@google.com»: anti-abuse tag .
droidguard@google.com: Don't be a stranger!
You got in! Talk to us at droidguard@google.com
Greetings from droidguard@google.com intrepid traveller! Say hi!
Was it easy to find this? droidguard@google.com would like to know
The folks at droidguard@google.com would appreciate hearing from you!
What's all this gobbledygook? Ask droidguard@google.com… they'd know!
Hey! Fancy seeing you here. Have you spoken to droidguard@google.com yet?
You're not just running strings on our .so! Talk to us at droidguard@google.com
, ? , DroidGuard Google, .
. , . , - . , . , Hex-Rays IDA, . .
Java .
jelf ( ELF )
Java_com_google_ccc_abuse_droidguard_DroidGuard_initNative
,
Capstone ( , , Java) .
, DroidGuard: anti-abuse , apk, , , , -. , Google. glassdoor . .
. DroidGuard : « ?».

«» — . Google , DroidGuard: Android ( !). DroidGuard. .
. DroidGuard . ? !
Google . , — hr . .
Google . , Google Doc , . «» coursera, hackerrank, …
. , — . Google Doc IDE. , . , , 5 . — . — , . , …

… . , , . . Base64 . Base64. , Base64, Java.
3 , , . Google .
DroidGuard , , . , . , : , .
, Google . , ( , ). .