# Reversing the C2C HTTP Emmental communication **blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html** In last [post l explained how it was possible to decrypt the initial C&C communication from the data dumped from memory, with the support of a](http://blog.angelalonso.es/2015/10/decrypting-emmental-blowfish-and-base64.html) python script. In this post, I am going to follow the same approach, but using the information from the captured network traffic. For that I will capture with Wireshark all the communication with the C&C while the malware is running. Then I can export all the 'objects' in the HTTP connection, which means the content of the HTTP request and response. ----- Now, I have e in a folder all the files with the objects from the HTTP request: $ ls main main(1).php main(11).php main(13).php main(15).php main(3).php main(5).php main(7).php main(9).php main(10).php main(12).php main(14).php main(2).php main(4).php main(6).php main(8).php main.php $ more main.php i=McsZtRV7Bv7ZjMSzwk5aIyZEiijP8F38NJcxd5VNElaIVxctxxX9UWCGbUaOIYRxhMxTtA8nBYmT%0A%2FkgJOPilsUZZyvc2swCziOJC5ae17wU [As the HTTP request is URL encoded, I need first to decode it, so I will adapt the python script created in this post to do it automatically. This is](http://blog.angelalonso.es/2015/10/decrypting-emmental-blowfish-and-base64.html) the script: #!/usr/bin/python from Crypto.Cipher import Blowfish from Crypto import Random from struct import pack from binascii import hexlify, unhexlify import sys import urllib file1 = sys.argv[1] file_out = sys.argv[2] blfs_key = open('/path/to/the/blfs.key','r') url_encode = open(file1,'r') url_encode_2 = url_encode.read() url_decode = urllib.unquote(url_encode_2).decode('utf8') file_ciphertext_base64 = url_decode file_blfs_key = blfs_key.read() ciphertext_raw = file_ciphertext_base64.decode("base64") IV = "12345678" _KEY = file_blfs_key ciphertext = ciphertext_raw KEY = hexlify(_KEY)[:50] cipher = Blowfish.new(KEY, Blowfish.MODE_CBC, IV) message = cipher.decrypt(ciphertext) config_plain = open(file_out,'w') config_plain.write(message) With this script it is easy to run a shell command with a loop 'for' to decrypt all the files in the directory. Bare in mind than the HTTP response are not URL encoded, so I will not need to perform that step on some of the files. Now I should have decrypted all the information from each object. Looking at the first two HTTP POST requests I see this is the case, but for the third one, this is not the case and the data is still encrypted. What's going on here? ----- I am going to take a look to the HTTP response from the server, what information is being sent? **A Public Key!! really interesting stuff...** Actually, if I look further in the second HTTP request from the screenshot above I can see the following: $ more "main(3).php" a:4.... ..... cjogVGhlIEFuZHJvaWQgUHJvamVjdCB8IGphdmEudmVyc2lvbjogMA== ";s:3:"cmd";s:7:"get_key";s:3:"rid";s:2:"25";s:4:"data";s:0:"";} This looks to me like the malware sends a request for a key and the server replies with the public key. So the only possibility is that the malware is using that key to encrypt the data so only the C&C can decrypt it with the private key. [To confirm this is the case, I am going to check the source code of the malware with 'androguard' as I explained in previous post.](http://blog.angelalonso.es/2015/10/malware-analysis-with-androguad.html) Looking at the code, I see there is a method with the string 'get_key' and I can see which other method is calling it: In [10]: d.CLASS_Lorg_thoughtcrime_securesms_h_c.METHOD_c.pretty_show() ########## Method Information Lorg/thoughtcrime/securesms/h/c;->c()V [access_flags=public] ########## Params local registers: v0...v2 - return: void #################### *************************************************************************** c-BB@0x0 : 0 (00000000) const-string v0, 'get_key' 1 (00000004) const-string v1, '' 2 (00000008) invoke-virtual v2, v0, v1, Lorg/thoughtcrime/securesms/h/c;->a(Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 3 (0000000e) move-result-object v0 4 (00000010) iput-object v0, v2, Lorg/thoughtcrime/securesms/h/c;->c Ljava/lang/String; 5 (00000014) invoke-virtual v2, Lorg/thoughtcrime/securesms/h/c;->b()Ljava/lang/Boolean; 6 (0000001a) move-result-object v0 7 (0000001c) invoke virtual v0 Ljava/lang/Boolean; >booleanValue()Z ----- 8 (000000 ) o e esu t 0 9 (00000024) if-eqz v0, 5 [ c-BB@0x28 c-BB@0x2e ] c-BB@0x28 : 10 (00000028) invoke-direct v2, Lorg/thoughtcrime/securesms/h/c;->d()V [ c-BB@0x2e ] c-BB@0x2e : 11 (0000002e) return-void *************************************************************************** ########## XREF F: Lorg/thoughtcrime/securesms/h/i; b (Landroid/content/Context;)V be T: Lorg/thoughtcrime/securesms/h/c; b ()Ljava/lang/Boolean; 14 T: Lorg/thoughtcrime/securesms/h/c; d ()V 28 T: Lorg/thoughtcrime/securesms/h/c; a (Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 8 #################### When decompiling the code I end up with some interesting Java methods: Looking tat the Java code I can see that the public key is used. But also, looking deeper into the code, I find another interesting method: private String a(String p9) { String v1_0 = 0; String v0_0 = ""; try { javax.crypto.Cipher v2_1 = javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1PADDING"); v2_1.init(1, this.d); String[] v3_2 = this.a(p9, 100); java.util.ArrayList v4_2 = new java.util.ArrayList(); int v5 = v3_2.length; } catch (String v1) { return this.a.c(v0_0); } while (v1_0 < v5) { v4_2.add(android.util.Base64.encodeToString(v2_1.doFinal(v3_2[v1_0].getBytes()), 0)); v1_0++; } v0_0 = android.text.TextUtils.join(".", v4_2); return this.a.c(v0_0); } So basically, one method is for encryption and the other for decryption, and both of them are using the same public key. This is really interesting stuff. So this is whats going on so far: 1. The compromised device sends the information encrypted with blowfish to the C&C ----- e C&C se e ep es t O 3. The compromised device requests the public key 4. The C&C server replies with the public key 5. The compromised device encrypts the information with the public key and sends to the C&C 6. The C&C server can decrypt with it's private key 7. The C&C server sends data encrypted with the private key ->I need to verify this 8. The compromised device can decrypt with the public key > I need to verify this To verify step 6 and 7, and as very quick PoC, I have created some Java code which takes the public key sent by the C&C and try to decrypt the successive messages sent by the C&C. Bingo! When I run the code I clearly see it works and my 'guess' was right: What is the information sent by the C&C? it looks like a new config.xml with new C&C URL.. Very interesting.. Looking to the code again, I see methods which performs the request for a new configuration file: In [7]: d.CLASS_Lorg_thoughtcrime_securesms_xservices_b.source() package org.thoughtcrime.securesms.xservices; class b extends android.os.AsyncTask { android.content.Context a; final synthetic org.thoughtcrime.securesms.xservices.XRepeat b; ----- pub c b(o g t oug tc e secu es s se ces epeat p, a d o d co te t Co te t p ) { this.b = p1; this.a = p2; return; } protected varargs String a(String[] p4) { org.thoughtcrime.securesms.h.i.a(this.a); org.thoughtcrime.securesms.h.i.c("CONF", "Check pull off urls", this.a); org.thoughtcrime.securesms.h.i.b(this.a); org.thoughtcrime.securesms.h.i.c(this.a); org.thoughtcrime.securesms.h.i.c("CONF", "Get config data from server", this.a); org.thoughtcrime.securesms.h.i.j(this.a); org.thoughtcrime.securesms.h.i.c("DATA", "Send data to server", this.a); return "OK"; } protected void a(String p1) { super.onPostExecute(p1); return; } protected synthetic Object doInBackground(Object[] p2) { return this.a(((String[]) p2)); } protected synthetic void onPostExecute(Object p1) { this.a(((String) p1)); return; } } As the HTTP request to the C&C are encrypted with the Public key, I can't decrypt it. However, I could check in memory the information before is encrypted. And this is what I found: a:2:{s:7:"LogCode";s:4:"CONF";s:7:"LogText";s:27:"Get config data from server";} Which matches the methods I checked previously :) -----