{
	"id": "507ad58d-a2a9-46a7-a9af-07bfa7afcede",
	"created_at": "2026-04-06T00:14:30.413839Z",
	"updated_at": "2026-04-10T03:20:44.626211Z",
	"deleted_at": null,
	"sha1_hash": "75fd68bb0cf91b45be8595c21229132e38bf951b",
	"title": "Reversing the C2C HTTP Emmental communication",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1249261,
	"plain_text": "Reversing the C2C HTTP Emmental communication\r\nArchived: 2026-04-05 19:44:32 UTC\r\nIn last post l explained how it was possible to decrypt the initial C\u0026C communication from the data dumped from memory,\r\nwith the support of a python script. In this post, I am going to follow the same approach, but using the information from the\r\ncaptured network traffic.\r\nFor that I will capture with Wireshark all the communication with the C\u0026C while the malware is running. Then I can export\r\nall the 'objects' in the HTTP connection, which means the content of the HTTP request and response.\r\nNow, I have e in a folder all the files with the objects from the HTTP request:\r\n$ ls main\r\nmain(1).php   main(11).php  main(13).php  main(15).php  main(3).php   main(5).php   main(7).php   main(9).php\r\nmain(10).php  main(12).php  main(14).php  main(2).php   main(4).php   main(6).php   main(8).php   main.php\r\n$ more main.php\r\ni=McsZtRV7Bv7ZjMSzwk5aIyZEiijP8F38NJcxd5VNElaIVxctxxX9UWCGbUaOIYRxhMxTtA8nBYmT%0A%2FkgJOPilsUZZyvc2swCziOJC5ae17wU\r\nAs 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\r\nautomatically. This is the script:\r\n#!/usr/bin/python\r\nfrom Crypto.Cipher import Blowfish\r\nfrom Crypto import Random\r\nfrom struct import pack\r\nfrom binascii import hexlify, unhexlify\r\nimport sys\r\nimport urllib\r\nfile1 =  sys.argv[1]\r\nhttp://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nPage 1 of 6\n\nfile_out = sys.argv[2]\r\nblfs_key =  open('/path/to/the/blfs.key','r')\r\nurl_encode = open(file1,'r')\r\nurl_encode_2 = url_encode.read()\r\nurl_decode = urllib.unquote(url_encode_2).decode('utf8')\r\nfile_ciphertext_base64 = url_decode\r\nfile_blfs_key = blfs_key.read()\r\nciphertext_raw = file_ciphertext_base64.decode(\"base64\")\r\nIV = \"12345678\"\r\n_KEY = file_blfs_key\r\nciphertext = ciphertext_raw\r\nKEY = hexlify(_KEY)[:50]\r\ncipher = Blowfish.new(KEY, Blowfish.MODE_CBC, IV)\r\nmessage = cipher.decrypt(ciphertext)\r\nconfig_plain = open(file_out,'w')\r\nconfig_plain.write(message)\r\nWith 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\r\nthe HTTP response are not URL encoded, so I will not need to perform that step on some of the files. \r\nNow I should have decrypted all the information from each object. Looking at the first two HTTP POST requests I see this\r\nis the case, but for the third one, this is not the case and the data is still encrypted. What's going on here?\r\nI am going to take a look to the HTTP response from the server, what information is being sent?\r\n A Public Key!! really interesting stuff...\r\nActually, if I look further in the second HTTP request from the screenshot above I can see the following:\r\nhttp://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nPage 2 of 6\n\n$ more \"main(3).php\"\r\na:4....\r\n.....\r\ncjogVGhlIEFuZHJvaWQgUHJvamVjdCB8IGphdmEudmVyc2lvbjogMA==\r\n\";s:3:\"cmd\";s:7:\"get_key\";s:3:\"rid\";s:2:\"25\";s:4:\"data\";s:0:\"\";}\r\nThis looks to me like the malware sends a request for a key and the server replies with the public key. So the only possibility\r\nis that the malware is using that key to encrypt the data so only the C\u0026C can decrypt it with the private key.\r\nTo confirm this is the case, I am going to check the source code of the malware with 'androguard' as I explained in previous\r\npost.\r\nLooking at the code, I see there is a method with the string 'get_key' and I can see which other method is calling it:\r\nIn [10]: d.CLASS_Lorg_thoughtcrime_securesms_h_c.METHOD_c.pretty_show()\r\n########## Method Information\r\nLorg/thoughtcrime/securesms/h/c;-\u003ec()V [access_flags=public]\r\n########## Params\r\nlocal registers: v0...v2\r\n- return: void\r\n####################\r\n***************************************************************************\r\nc-BB@0x0 :\r\n0  (00000000) const-string        v0, 'get_key'\r\n1  (00000004) const-string        v1, ''\r\n2  (00000008) invoke-virtual      v2, v0, v1, Lorg/thoughtcrime/securesms/h/c;-\u003ea(Ljava/lang/String;\r\nLjava/lang/String;)Ljava/lang/String;\r\n3  (0000000e) move-result-object  v0\r\n4  (00000010) iput-object         v0, v2, Lorg/thoughtcrime/securesms/h/c;-\u003ec Ljava/lang/String;\r\n5  (00000014) invoke-virtual      v2, Lorg/thoughtcrime/securesms/h/c;-\u003eb()Ljava/lang/Boolean;\r\n6  (0000001a) move-result-object  v0\r\n7  (0000001c) invoke-virtual      v0, Ljava/lang/Boolean;-\u003ebooleanValue()Z\r\n8  (00000022) move-result         v0\r\n9  (00000024) if-eqz              v0, 5 [ c-BB@0x28 c-BB@0x2e ]\r\nc-BB@0x28 :\r\n10 (00000028) invoke-direct       v2, Lorg/thoughtcrime/securesms/h/c;-\u003ed()V [ c-BB@0x2e ]\r\nc-BB@0x2e :\r\n11 (0000002e) return-void\r\n***************************************************************************\r\n########## XREF\r\nF: Lorg/thoughtcrime/securesms/h/i; b (Landroid/content/Context;)V be\r\nT: Lorg/thoughtcrime/securesms/h/c; b ()Ljava/lang/Boolean; 14\r\nT: Lorg/thoughtcrime/securesms/h/c; d ()V 28\r\nT: Lorg/thoughtcrime/securesms/h/c; a (Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 8\r\n####################\r\nWhen decompiling the code I end up with some interesting Java methods:\r\nhttp://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nPage 3 of 6\n\nLooking tat the Java code I can see that the public key is used. But also, looking deeper into the code, I find another\r\ninteresting method:\r\nprivate String a(String p9)\r\n    {\r\n        String v1_0 = 0;\r\n        String v0_0 = \"\";\r\n        try {\r\n            javax.crypto.Cipher v2_1 = javax.crypto.Cipher.getInstance(\"RSA/ECB/PKCS1PADDING\");\r\n            v2_1.init(1, this.d);\r\n            String[] v3_2 = this.a(p9, 100);\r\n            java.util.ArrayList v4_2 = new java.util.ArrayList();\r\n            int v5 = v3_2.length;\r\n        } catch (String v1) {\r\n            return this.a.c(v0_0);\r\n        }\r\n        while (v1_0 \u003c v5) {\r\n            v4_2.add(android.util.Base64.encodeToString(v2_1.doFinal(v3_2[v1_0].getBytes()), 0));\r\n            v1_0++;\r\n        }\r\n        v0_0 = android.text.TextUtils.join(\".\", v4_2);\r\n        return this.a.c(v0_0);\r\n    }\r\nSo basically, one method is for encryption and the other for decryption, and both of them are using the same public key. This\r\nis really interesting stuff. \r\nSo this is whats going on so far:\r\n1. The compromised device sends the information encrypted with blowfish to the C\u0026C\r\n2. The C\u0026C server replies with OK\r\n3. The compromised device requests the public key\r\n4. The C\u0026C server replies with the public key\r\n5. The compromised device encrypts the information with the public key and sends to the C\u0026C\r\n6. The C\u0026C server can decrypt with it's private key\r\n7. The C\u0026C server sends data encrypted with the private key -\u003eI need to verify this \r\n8. The compromised device can decrypt with the public key \u003e I need to verify this \r\nTo 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\u0026C\r\nand try to decrypt the successive messages sent by the C\u0026C.\r\nhttp://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nPage 4 of 6\n\nBingo! When I run the code I clearly see it works and my 'guess' was right:\r\nWhat is the information sent by the C\u0026C? it looks like a new config.xml with new C\u0026C URL..\r\nVery interesting..\r\nLooking to the code again,  I see methods which performs the request for a new configuration file:\r\nIn [7]: d.CLASS_Lorg_thoughtcrime_securesms_xservices_b.source()\r\npackage org.thoughtcrime.securesms.xservices;\r\n class b extends android.os.AsyncTask {\r\n    android.content.Context a;\r\n    final synthetic org.thoughtcrime.securesms.xservices.XRepeat b;\r\n    public b(org.thoughtcrime.securesms.xservices.XRepeat p1, android.content.Context p2)\r\n    {\r\n        this.b = p1;\r\n        this.a = p2;\r\n        return;\r\n    }\r\nhttp://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nPage 5 of 6\n\nprotected varargs String a(String[] p4)\r\n    {\r\n        org.thoughtcrime.securesms.h.i.a(this.a);\r\n        org.thoughtcrime.securesms.h.i.c(\"CONF\", \"Check pull off urls\", this.a);\r\n        org.thoughtcrime.securesms.h.i.b(this.a);\r\n        org.thoughtcrime.securesms.h.i.c(this.a);\r\n        org.thoughtcrime.securesms.h.i.c(\"CONF\", \"Get config data from server\", this.a);\r\n        org.thoughtcrime.securesms.h.i.j(this.a);\r\n        org.thoughtcrime.securesms.h.i.c(\"DATA\", \"Send data to server\", this.a);\r\n        return \"OK\";\r\n    }\r\n    protected void a(String p1)\r\n    {\r\n        super.onPostExecute(p1);\r\n        return;\r\n    }\r\n    protected synthetic Object doInBackground(Object[] p2)\r\n    {\r\n        return this.a(((String[]) p2));\r\n    }\r\n    protected synthetic void onPostExecute(Object p1)\r\n    {\r\n        this.a(((String) p1));\r\n        return;\r\n    }\r\n}\r\nAs the HTTP request to the C\u0026C are encrypted with the Public key, I can't decrypt it. However, I could check in memory the\r\ninformation before is encrypted.\r\nAnd this is what I found:\r\na:2:{s:7:\"LogCode\";s:4:\"CONF\";s:7:\"LogText\";s:27:\"Get config data from server\";}\r\nWhich matches the methods I checked previously :)\r\nSource: http://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nhttp://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"ETDA"
	],
	"references": [
		"http://blog.angelalonso.es/2015/10/reversing-c2c-http-emmental.html"
	],
	"report_names": [
		"reversing-c2c-http-emmental.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434470,
	"ts_updated_at": 1775791244,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/75fd68bb0cf91b45be8595c21229132e38bf951b.pdf",
		"text": "https://archive.orkl.eu/75fd68bb0cf91b45be8595c21229132e38bf951b.txt",
		"img": "https://archive.orkl.eu/75fd68bb0cf91b45be8595c21229132e38bf951b.jpg"
	}
}