{
	"id": "a02d6ae8-9bb9-4794-8028-01b25bb0ef96",
	"created_at": "2026-04-06T00:21:41.102799Z",
	"updated_at": "2026-04-10T13:13:05.517417Z",
	"deleted_at": null,
	"sha1_hash": "bfb13908377346e0c55b39bdf640cb489277f56c",
	"title": "How To Build Advanced Threat Intelligence Queries Utilising Regex and TLS Certificates - (BianLian)",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1544284,
	"plain_text": "How To Build Advanced Threat Intelligence Queries Utilising\r\nRegex and TLS Certificates - (BianLian)\r\nBy Matthew\r\nPublished: 2023-11-27 · Archived: 2026-04-05 17:40:11 UTC\r\nIn this post we will investigate a Bianlian C2 address and use TLS certificates to obtain another ~50 servers.\r\nOur primary focus will be building a regex query that matches the unique TLS structure used by recent BianLian.\r\nRegex and TLS Certs present a great opportunity to build queries without introducing geographic limitations like\r\nASN numbers and hosting providers. By using TLS Certificates, we can also avoid limiting searches to specific\r\nport numbers or port counts. Effectively catching actors that avoid patterns demonstrated in previous posts. (Eg\r\nhere and here)\r\nOur final query will look something like this.\r\nservices.banner_hashes=\"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\" and\r\nservices.tls.certificates.leaf_data.subject_dn:/C=.{16}, O=.{16}, OU=.{16}/\r\nNote that regular expression searches are a paid feature of Censys. But for the purposes of\r\ndemonstrating interesting concepts I thought this blog would be useful\r\nAt the end of this blog, there is a query that will catch the same certificates without utilising Regex.\r\nThis can be used if you don't have a paid Censys account.\r\nPerforming an Initial Search\r\nWe can begin the search by looking up the initial IP of 185.248.100[.]118 which was obtained on ThreatFox.\r\nNote that we can prepend ip: if we want an overview before jumping directly to the IP page.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 1 of 12\n\nClicking on the IP Address takes us to the full page, where we can see an interesting TLS certificate on port 443.\r\nIf we click on the \"view all data\" tab in the top right of the above screenshot, we can view the full information for\r\nport 443.\r\nThis enables us to see all available information for a given port, which is typically significantly more\r\nthan what is available within the default summary view.\r\nThe first thing that stands out is the empty services.banner field. A lack of service banner (although boring at\r\ninitial glance) could be a great pivot point.\r\nWe can click on the blue search box next to the services.banner field to perform a pivot. This will pre-build the\r\nquery and save us time finding the exact field to search.\r\nIt's often better to use the banner hash when we want an exact match, this will avoid any issues where a\r\nvalue might be incorrectly typed when searching. This also ensures an exact match is queried.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 2 of 12\n\nPerforming a basic pivot from the banner hash, we have an initial result of 14,605,188 servers. An admittedly\r\nhuge number, But we'll improve this later.\r\nIf we go back to the initial summary view, we can see that the service was identified as \"Unknown\".\r\nWe can again use the \"view all data\" to find the \"Unknown\" field and perform a pivot with the search box.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 3 of 12\n\nThis returns a lot of results, so we can take the resulting query and add it to our initial empty banner search.\r\nSadly this doesn't actually reduce the hits to any useful degree (in this case), but it's a useful technique to know so\r\nI wanted to include it in the post.\r\nSince the addition of `UNKNOWN1 only reduced the hits by a very very small degree, it doesn't matter whether\r\nwe include it or not for the remainder of this search.\r\nFor the remaining queries we can leave it out.\r\nMoving on, we can go back to the field details page and observe the certificate information in more detail.\r\nOf particular interest here is that only the C=,O= and OU= fields are present in the subject and issuer fields.\r\nTypically there are additional values like Location L , State ST and others. The absence of these\r\nvalues is an additional indicator that can be used.\r\nFor example, a \"normal\" certificate should look more like this.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 4 of 12\n\nWe can also note that all of the C=,O=,OU= values are exactly 16 characters in length.\r\nThe lack of \"regular\" fields and presence of exactly 16 characters is itself a pattern worth signaturing.\r\nWe can use the blue search box again (right side of the detailed fields view) to automatically build an exact query.\r\nConverting a Field to Regex\r\nThe initial pre-built query is an exact string search. (Indicated by the presence of = and the entire thing encased\r\nin quotes)\r\nservices.tls.certificates.leaf_data.subject_dn=\"C=ID5hgJb31CGtxS3R, O=NgOiQK7LZP5nKyTE,\r\nOU=fcr8shEwbsebOGQc\"\r\nWe can turn this into a regex by adjusting the equals = to a colon : and changing the double quotes \" to\r\nforward slashes /\r\nWe can then validate the syntax by modifying the query and ensuring the same result is returned.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 5 of 12\n\nAfter validating the syntax, we can remove the main values and replace them with .{16} .\r\nThis ensures that exactly 16 characters are present following any of the C=, O= or OU= values.\r\nIn a real example you would probably want to avoid the . wildcard and use a more specific query like\r\n[a-zA-Z0-9]{16} , [^,]{16} or \\w{16} . But for this example we will keep it simple with a .\r\nAdjusting the query returns 56 results for matching certificates.\r\nValidating a Regex Query with the \"Build Report\" Feature\r\nBy using the \"report\" button in the top-right corner, we can view a specific field for all of our returned results.\r\nThis can be extremely useful for validating that results are matching as intended.\r\nNote in the screenshot below, that the \"build report\" function will show results for other services\r\nrunning on returned servers.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 6 of 12\n\nFor example, a server with a matching hit on port 443, may also have a non-matching hit on port 8080.\r\nIf both services contain a relevant field, they both will be displayed. Hence the additional results that\r\ndon't match our query.\r\nEither way this function is still useful for validating results.\r\nWith the query now validated further, we can add it to our initial empty banner search.\r\nservices.banner_hashes=\"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\" and\r\nservices.tls.certificates.leaf_data.subject_dn:/C=.{16}, O=.{16}, OU=.{16}/\r\nThis results in 53 returned servers.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 7 of 12\n\nInvestigating Hits With VirusTotal\r\nInvestigating the first 2 hits (that aren't our initial IP) with VirusTotal, we can see that both have been marked as\r\nBianLian trojan.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 8 of 12\n\nTo save time scrolling through the page, we can use the Build Report feature again to obtain an easy list of all\r\nreturned IPs.\r\nWe can also scroll down to the JSON output and combine it with CyberChef to obtain a text-based list.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 9 of 12\n\nTaking that list and validating servers with VirusTotal, we can that every result was marked malicious, and all had\r\nat least one comment referencing BianLian.\r\nFinal Results Checked Against Virustotal\r\n2[.]58[.]14[.]41 - BianLian 8/88 VT\r\n3[.]76[.]100[.]131 - BianLian 11/88 VT\r\n13[.]59[.]168[.]154 - BianLian 11/88 VT\r\n13[.]215[.]227[.]78 - BianLian 11/88 VT\r\n13[.]215[.]228[.]73 - BianLian 11/88 VT\r\n23[.]152[.]0[.]64 - BianLian 11/88 VT\r\n34[.]207[.]174[.]202 - BianLian 11/88 VT\r\n34[.]219[.]121[.]232 - BianLian 9/88 VT\r\n43[.]139[.]241[.]58 - BianLian 13/88 VT\r\n45[.]45[.]219[.]141 - BianLian 6/88 VT\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 10 of 12\n\n45[.]56[.]165[.]27 - BianLian 12/88 VT\r\n45[.]56[.]165[.]30 - BianLian 11/88 VT\r\n45[.]80[.]151[.]49 - 4/88 BianLian\r\n45[.]86[.]163[.]188 - 9/88 BianLian\r\n45[.]86[.]163[.]224 - 13/88 BianLian\r\n54[.]193[.]91[.]232 - 11/88 BianLian\r\n65[.]109[.]3[.]80 - 6/88 BianLian\r\n66[.]29[.]155[.]44 - 6/88 BianLian\r\n85[.]13[.]118[.]11 - 6/88 BianLian\r\n87[.]247[.]185[.]109 - 6/88 BianLian\r\n91[.]102[.]162[.]229 - 9/88 BianLian\r\n94[.]131[.]98[.]34 - 14/88 BianLian\r\n94[.]198[.]50[.]195 - 11/88 BianLian\r\n103[.]57[.]250[.]152 - 14/88 BianLian\r\n104[.]36[.]229[.]15 - 13/88 BianLian\r\n104[.]194[.]11[.]252 - 6/88 BianLian\r\n104[.]238[.]34[.]130 - 6/88 BianLian\r\n104[.]238[.]35[.]163 - 11/88 BianLian\r\n104[.]238[.]60[.]64 - 9/88 BianLian\r\n104[.]238[.]61[.]150 - 9/88 BianLian\r\n104[.]243[.]32[.]53 - 5/88 BianLian\r\n104[.]243[.]33[.]83 - 6/88 BianLian\r\n104[.]243[.]33[.]84 - 7/88 BianLian\r\n108[.]174[.]60[.]151 - 8/88 BianLian\r\n120[.]48[.]110[.]233 - 5/88 BianLian\r\n139[.]59[.]40[.]48 - 8/88 BianLian\r\n143[.]198[.]46[.]29 - 9/88 BianLian\r\n149[.]154[.]158[.]34 - 10/88 BianLian\r\n149[.]154[.]158[.]199 - 11/88 BianLian\r\n149[.]248[.]14[.]201 - 6/88 BianLian\r\n168[.]119[.]88[.]236 - 6/88 BianLian\r\n173[.]254[.]235[.]30 - 10/88 BianLian\r\n185[.]240[.]103[.]195 - 9/88 VT BianLian\r\n185[.]248[.]100[.]118 - 6/88 BianLian\r\n188[.]34[.]130[.]46 - 4/88 BianLian\r\n192[.]52[.]166[.]233 - 6/88 VT BianLian\r\n192[.]236[.]192[.]207 - 6/88 VT BianLian\r\n194[.]213[.]18[.]45 - 9/88 VT BianLian\r\n195[.]128[.]235[.]20 - 7/88 VT BianLian\r\n198[.]199[.]76[.]216 - 6/88 VT BianLian\r\nSign up for Embee Research\r\nMalware Analysis, Detection and Threat Intelligence\r\nNo spam. Unsubscribe anytime.\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 11 of 12\n\nNote on Searching Without Regex\r\nThe regular expression (Regex) feature is only available within the Paid version of Censys.\r\nIf you wish to obtain the same results on the free version, you can use the following query. This works if you\r\nknow the specific length of each field you want to search.\r\nIt won't work in other cases where you want to specify a length range (eg something like .{14,16} . But for\r\nhardcoded lengths, it can work and is functionally equivalent to .{16}\r\nservices.banner_hashes=\"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\" and\r\nservices.tls.certificates.leaf_data.subject_dn:\"C=????????????????, O=????????????????,\r\nOU=????????????????\"\r\nSource: https://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nhttps://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/\r\nPage 12 of 12\n\n  https://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/     \nTo save time scrolling through the page, we can use the Build Report feature again to obtain an easy list of all\nreturned IPs.       \nWe can also scroll down to the JSON output and combine it with CyberChef to obtain a text-based list.\n   Page 9 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://embee-research.ghost.io/building-advanced-censys-queries-utilising-regex-bianlian/"
	],
	"report_names": [
		"building-advanced-censys-queries-utilising-regex-bianlian"
	],
	"threat_actors": [
		{
			"id": "2864e40a-f233-4618-ac61-b03760a41cbb",
			"created_at": "2023-12-01T02:02:34.272108Z",
			"updated_at": "2026-04-10T02:00:04.97558Z",
			"deleted_at": null,
			"main_name": "WildCard",
			"aliases": [],
			"source_name": "ETDA:WildCard",
			"tools": [
				"RustDown",
				"SysJoker"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "256a6a2d-e8a2-4497-b399-628a7fad4b3e",
			"created_at": "2023-11-30T02:00:07.299845Z",
			"updated_at": "2026-04-10T02:00:03.484788Z",
			"deleted_at": null,
			"main_name": "WildCard",
			"aliases": [],
			"source_name": "MISPGALAXY:WildCard",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		}
	],
	"ts_created_at": 1775434901,
	"ts_updated_at": 1775826785,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/bfb13908377346e0c55b39bdf640cb489277f56c.pdf",
		"text": "https://archive.orkl.eu/bfb13908377346e0c55b39bdf640cb489277f56c.txt",
		"img": "https://archive.orkl.eu/bfb13908377346e0c55b39bdf640cb489277f56c.jpg"
	}
}