{
	"id": "e6dcfd3c-c29a-4de2-9c16-db6f5095475a",
	"created_at": "2026-04-06T00:10:13.958258Z",
	"updated_at": "2026-04-10T03:29:31.698638Z",
	"deleted_at": null,
	"sha1_hash": "b6df23325025c2a1f50b8874a737661004d629a3",
	"title": "Organizing malware analysis with Colander: example on Android/WyrmSpy",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1375005,
	"plain_text": "Organizing malware analysis with Colander: example on\r\nAndroid/WyrmSpy\r\nBy @cryptax\r\nPublished: 2023-12-19 · Archived: 2026-04-05 22:47:36 UTC\r\n6 min read\r\nDec 18, 2023\r\nWhen I analyze a malware, I keep side by side an ugly text file where I write down my reversing notes.\r\nUnfortunately, my notes are usually totally cryptic — even by me — a few weeks later.\r\nUpdate December 19, 2023: searching the cases is already possible, my error: I had missed the functionality (see\r\nConclusion).\r\nPress enter or click to view image in full size\r\nThis is taken from my old notes on the analysis of a sample of Android/GodFather\r\nTo tackle this problem, I have been using Colander now and then for a few months. Colander is an open-source\r\n“incident response and knowledge management platform”. It is multi-purpose, i.e not specific to Android malware\r\nanalysis, but I find it quite easy to use to organize my reverse engineering notes.\r\nAs an example, we’ll analyze a sample of Android/WyrmSpy sha256\r\nb66847d571e471ac78ffa11a82dded5ac6d2f52b25304adbfab90716d22c0905 .\r\nWhat does this article cover? (1) Use of Colander, (2) Analysis of a sample of WyrmSpy. Enjoy!\r\nColander\r\nColander uses Incident Response terminology with artifacts, devices, threats, observables, events and data.\r\nBasically, you create items in these “categories” and then you can create relations between them, and Colander\r\nautomatically generates a graph to display it all.\r\nPress enter or click to view image in full size\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 1 of 9\n\nLookOut’s report contains lists of WyrmSpy IOCs. So, I created a URL item for the report, a\r\nSHA256 observable for the sample I want to look into, and assigned the relation “lists IOCs”\r\nbetween both entities. Actually, it would probably be wiser to upload the sample as an artifact, but I\r\nwas lazy and didn’t want to upload any file.\r\nThe main activity is referenced in the Android Manifest, and fortunately, the sample is not packed, so we can\r\ndecompile the activity. I always like to keep track of where the main entry point is, so I create a “fragment of data”\r\nbelow for the main activity.\r\nPress enter or click to view image in full size\r\nFragment of data for the Main activity of the malware.\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 2 of 9\n\nThe malware starts a FakeActivity , which starts a so-called AdobeService , which processes malicious\r\ncommands. For instance, the following code will upload raw audio recording to the remote C2.\r\nPress enter or click to view image in full size\r\nIf at some point the malware processed a message “Calls” or “audio”, the malware retrieves the\r\naudio file (if necessary converts from RAW format to MP3) and uploads the file to the remote C2.\r\nIn a few weeks, I won’t remember where this piece of code is, so in Colander, I create (1) a threat “Leaks audio\r\nrecordings”, (2) a piece of code — in that case it is in ExecServerCmd of com.flash18.AdobeService — and (3)\r\ncreates a relation “implements” between the first 2.\r\nPress enter or click to view image in full size\r\nCreating a threat to memorize the malware does this + easily find again where this happens in the\r\ncode\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 3 of 9\n\nThe initialization of the malware is done in a method called InitAppConfig of com.flash18.Config . 👀 It’s\nactually the first time I see that: the C2’s URL is kept in a meta-data item of the Android Manifest ! Not very\nstealthy 👓, but probably easy to customize for APT 41.\npublic static Boolean InitAppConfig(Context context) {\n try {\n Bundle meta = context.getPackageManager().getApplicationInfo(\"com.sec.android.provide.badge\n Config._server_url = meta.getString(\"u\");\n Config._password = meta.getString(\"p\");\n Config._version = meta.getString(\"v\");\n if(Config._interval \u003c= 0) {\n Config._interval = 30;\n }\n Config._bind = meta.getString(\"kb\");\n Config._CustomId = meta.getString(\"CustomId\");\n Config._uid = Utils.GetAndroidId(context);\n...\nRooting status\nWyrmSpy is known to test for and install rooting applications, which isn’t altogether that common in malware.\nSo, I want to look into that.\nThe AdobeService call uploadRootInfo , which sends the rooting status of the device: it says if the device can\nbe rooted with King Root, and if there is yet another rooting solution on the device. To check if King Root can be\nused, the malware probably uses a non-identified (yet) third party SDK which contacts pmir.3g.qq.com and\nexpects rooting solutions in return.\nGet @cryptax’s stories in your inbox\nJoin Medium for free to get updates from this writer.\nRemember me for faster sign in\nLater in the code, the malware roots the device if it isn’t rooted yet. As expected, it will use King Root if it can.\nOtherwise, it tries “Ivy Root” which is also referred to in the code as tryOurSolutions . The later root zip is\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\nPage 4 of 9\n\ndownloaded from the C2, unzipped and executed. Default download URLs are found in methods named\r\nDownRootPlan and DownRootPlan2 .\r\nColander’s graph\r\nAfter a while, my brains are exploding and it is time to use Colander’s graph capability. This is what the graph\r\nlooks like at first.\r\nPress enter or click to view image in full size\r\nColander initial graph for Android/WyrmSpy shows relationships between entities. It’s pretty good\r\nalready but we see there are a few unrelated groups (in red)\r\nI forgot several relations, which is why some nodes appear as isolated in the analysis. Let’s fix this. For example:\r\nwho contacts the URL to get the mainfest / mainifest (both typos are present in the malware)? It’s the\r\nAdobeService . We can directly add the relationship from the graph view.\r\nPress enter or click to view image in full size\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 5 of 9\n\nImproving the graph: Adding relations of “AdobeService” to point to “Mainfest URL”\r\nPress enter or click to view image in full size\r\nRelations are fully editable from the graph. For example, I want to correct the fact that the sample\r\ndoes not directly start the AdobeService. Rather, the sample begins with the MainActivity, which\r\nstarts a FakeActivity (not represented), which starts the AdobeActivity. To do so, I delete the\r\nrelation and create the correct ones.\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 6 of 9\n\nFinal version of Android/WyrmSpy analysis\r\nAfter a little edition, this is the final graph I get to. Honestly, I didn’t have much to do and only moved a few\r\nnodes to reach this state.\r\nPress enter or click to view image in full size\r\nFinal graph reprensenting my analysis of WyrmSpy.\r\nI can guarantee this is way easier to understand than my ugly notes.\r\nPress enter or click to view image in full size\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 7 of 9\n\nThe graph is just an entry point to get more details on each node. For instance, I clicked on\r\nRemoteFileMgr and can read / update what this class does in the malware.\r\nConclusion\r\nColander is not going to do the analysis for you 🎅. I see it more as a very helpful tool to organize your\r\nanalysis.\r\nThe graph editor is absolutely awesome 😍. I played with several editors in the past and my graphs\r\nusually ended up like a plate of spaghettis. It’s not the case with Colander where I find the resulting graph\r\nreadable (of course, it depends the level of detail you include)\r\nThere is very little overhead to using Colander: I focused on the reverse engineering of my sample,\r\nthat’s all and did not have to waste time “understanding how to make Colander do it”. To be honest,\r\nsometimes, I probably did not use it in an optimal manner: I’m a bit lost in the list of possible observables,\r\nthreats and artifacts. Fortunately, it didn’t matter too much and I managed to get Colander do what was\r\nhelpful to me. Good tools don’t turn you into slaves. It’s the opposite: good tools are your slaves to do\r\nwhat you want, or to be easily tweakable to do what you need. That’s versatility.\r\nMy advice is to keep labels of relationships short. Actually, it’s the same for any node label. If you want to\r\nsay something long, put it in the description, not in the title.\r\nNext feature I’d love is for cases to be searchable and scriptable, so that in 8 months I can quickly search\r\nthrough my cases to find again that sample which was doing XYZ. Update Dec 19: I hadn’t noticed the\r\nfeature, but it’s already possible to search through all your all titles of all entities of your cases in\r\nColander.\r\nAndroid/WyrmSpy keeps the URL of its C2 in the AndroidManifest.xml file!\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 8 of 9\n\nAndroid/WyrmSpy implements several downloadable “plugins” which implement malicious features like\r\nreading and uploading all contacts.\r\nAndroid/WyrmSpy wants to operate on a rooted device. It will try and root the device several different\r\nways.\r\n— Cryptax\r\nSource: https://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nhttps://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b\r\nPage 9 of 9",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://cryptax.medium.com/organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b"
	],
	"report_names": [
		"organizing-malware-analysis-with-colander-example-on-android-wyrmspy-1f3ec30ae33b"
	],
	"threat_actors": [
		{
			"id": "c7d9878a-e691-4c6f-81ae-84fb115a1345",
			"created_at": "2022-10-25T16:07:23.359506Z",
			"updated_at": "2026-04-10T02:00:04.556639Z",
			"deleted_at": null,
			"main_name": "APT 41",
			"aliases": [
				"BrazenBamboo",
				"Bronze Atlas",
				"Double Dragon",
				"Earth Baku",
				"G0096",
				"Grayfly",
				"Operation ColunmTK",
				"Operation CuckooBees",
				"Operation ShadowHammer",
				"Red Kelpie",
				"SparklingGoblin",
				"TA415",
				"TG-2633"
			],
			"source_name": "ETDA:APT 41",
			"tools": [
				"9002 RAT",
				"ADORE.XSEC",
				"ASPXSpy",
				"ASPXTool",
				"AceHash",
				"Agent.dhwf",
				"Agentemis",
				"AndroidControl",
				"AngryRebel",
				"AntSword",
				"BLUEBEAM",
				"Barlaiy",
				"BlackCoffee",
				"Bladabindi",
				"BleDoor",
				"CCleaner Backdoor",
				"CHINACHOPPER",
				"COLDJAVA",
				"China Chopper",
				"ChyNode",
				"Cobalt Strike",
				"CobaltStrike",
				"Crackshot",
				"CrossWalk",
				"CurveLast",
				"CurveLoad",
				"DAYJOB",
				"DBoxAgent",
				"DEADEYE",
				"DEADEYE.APPEND",
				"DEADEYE.EMBED",
				"DEPLOYLOG",
				"DIRTCLEANER",
				"DUSTTRAP",
				"Derusbi",
				"Destroy RAT",
				"DestroyRAT",
				"DodgeBox",
				"DragonEgg",
				"ELFSHELF",
				"EasyNight",
				"Farfli",
				"FunnySwitch",
				"Gh0st RAT",
				"Ghost RAT",
				"HDD Rootkit",
				"HDRoot",
				"HKDOOR",
				"HOMEUNIX",
				"HUI Loader",
				"HidraQ",
				"HighNoon",
				"HighNote",
				"Homux",
				"Hydraq",
				"Jorik",
				"Jumpall",
				"KEYPLUG",
				"Kaba",
				"Korplug",
				"LATELUNCH",
				"LOLBAS",
				"LOLBins",
				"LightSpy",
				"Living off the Land",
				"Lowkey",
				"McRAT",
				"MdmBot",
				"MessageTap",
				"Meterpreter",
				"Mimikatz",
				"MoonBounce",
				"MoonWalk",
				"Motnug",
				"Moudour",
				"Mydoor",
				"NTDSDump",
				"PACMAN",
				"PCRat",
				"PINEGROVE",
				"PNGRAT",
				"POISONPLUG",
				"POISONPLUG.SHADOW",
				"POTROAST",
				"PRIVATELOG",
				"PipeMon",
				"PlugX",
				"PortReuse",
				"ProxIP",
				"ROCKBOOT",
				"RbDoor",
				"RedDelta",
				"RedXOR",
				"RibDoor",
				"Roarur",
				"RouterGod",
				"SAGEHIRE",
				"SPARKLOG",
				"SQLULDR2",
				"STASHLOG",
				"SWEETCANDLE",
				"ScrambleCross",
				"Sensocode",
				"SerialVlogger",
				"ShadowHammer",
				"ShadowPad Winnti",
				"SinoChopper",
				"Skip-2.0",
				"SneakCross",
				"Sogu",
				"Speculoos",
				"Spyder",
				"StealthReacher",
				"StealthVector",
				"TERA",
				"TIDYELF",
				"TIGERPLUG",
				"TOMMYGUN",
				"TVT",
				"Thoper",
				"Voldemort",
				"WIDETONE",
				"WINNKIT",
				"WINTERLOVE",
				"Winnti",
				"WyrmSpy",
				"X-Door",
				"XDOOR",
				"XMRig",
				"XShellGhost",
				"Xamtrav",
				"ZXShell",
				"ZoxPNG",
				"certutil",
				"certutil.exe",
				"cobeacon",
				"gresim",
				"njRAT",
				"pwdump",
				"xDll"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434213,
	"ts_updated_at": 1775791771,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/b6df23325025c2a1f50b8874a737661004d629a3.pdf",
		"text": "https://archive.orkl.eu/b6df23325025c2a1f50b8874a737661004d629a3.txt",
		"img": "https://archive.orkl.eu/b6df23325025c2a1f50b8874a737661004d629a3.jpg"
	}
}