{"id":9047,"date":"2024-01-06T23:46:54","date_gmt":"2024-01-06T23:46:54","guid":{"rendered":"https:\/\/www.hexacorn.com\/blog\/?p=9047"},"modified":"2024-02-25T00:42:16","modified_gmt":"2024-02-25T00:42:16","slug":"bitmap-hunting-in-spl-part-2","status":"publish","type":"post","link":"https:\/\/www.hexacorn.com\/blog\/2024\/01\/06\/bitmap-hunting-in-spl-part-2\/","title":{"rendered":"Bitmap hunting in SPL, Part 2"},"content":{"rendered":"\n<p>In my previous post I introduced the concept of <a href=\"https:\/\/www.hexacorn.com\/blog\/2024\/01\/01\/bitmap-hunting-in-spl\/\" data-type=\"post\" data-id=\"9025\">bitmap hunting<\/a>. Today I will show another example that helps to find a sequence of more than 2 events.<\/p>\n\n\n\n<p>Consider this artificially generated sequence of events:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">| makeresults           | eval _time=_time + 01 | eval evt=\"Run\" | eval program=\"outlook.exe\"\n| append [| makeresults | eval _time=_time + 02 | eval evt=\"Run\" | eval program=\"firefox.exe\"]\n| append [| makeresults | eval _time=_time + 03 | eval evt=\"Run\" | eval program=\"firefox.exe\"]\n| append [| makeresults | eval _time=_time + 04 | eval evt=\"File\" | eval file=\"...\\invoice.lnk\" ]\n| append [| makeresults | eval _time=_time + 05 | eval evt=\"Run\" | eval program=\"cscript.exe\"]\n| append [| makeresults | eval _time=_time + 06 | eval evt=\"Run\" | eval program=\"powershell.exe\"]\n| append [| makeresults | eval _time=_time + 07 | eval evt=\"Run\" | eval program=\"mshta.exe\"]\n| append [| makeresults | eval _time=_time + 08 | eval evt=\"File\" | eval file=\"...\\bar.tmp\" ]\n| append [| makeresults | eval _time=_time + 09 | eval evt=\"Run\" | eval program=\"svchost.exe\"]\n| append [| makeresults | eval _time=_time + 10 | eval evt=\"Run\" | eval program=\"outlook.exe\"]\n| append [| makeresults | eval _time=_time + 11 | eval evt=\"Run\" | eval program=\"dllhost.exe\"]\n| append [| makeresults | eval _time=_time + 12 | eval evt=\"File\" | eval file=\"...\\foo.tmp\" ]\n| append [| makeresults | eval _time=_time + 13 | eval evt=\"Run\" | eval program=\"cscript.exe\"]\n| append [| makeresults | eval _time=_time + 14 | eval evt=\"Run\" | eval program=\"powershell.exe\"]\n| append [| makeresults | eval _time=_time + 15 | eval evt=\"Run\" | eval program=\"mshta.exe\"]<\/pre>\n\n\n\n<p>giving us this data:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2.png\"><img decoding=\"async\" loading=\"lazy\" width=\"848\" height=\"533\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2.png\" alt=\"\" class=\"wp-image-9048\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2.png 848w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2-300x189.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2-768x483.png 768w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2-477x300.png 477w\" sizes=\"(max-width: 848px) 100vw, 848px\" \/><\/a><\/figure>\n\n\n\n<p>It&#8217;s completely fictional, but you can see that we have two clusters of <em>cscript<\/em>, <em>powershell<\/em>, <em>mshta<\/em> program executions, with one following the file creation event where the file was a shortcut file using the file extension <em>LNK<\/em> (often used by malware).<\/p>\n\n\n\n<p>Let&#8217;s say we want to find all the clusters of these 3 programs being executed AFTER any LNK file was created, and ignore the others.<\/p>\n\n\n\n<p>We can first create a bitmap by adding the following code:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">| eval b=\n   case (\n         evt=\"Run\" and program=\"cscript.exe\", \"c\",\n         evt=\"Run\" and program=\"powershell.exe\", \"p\",\n         evt=\"Run\" and program=\"mshta.exe\", \"m\",\n         evt=\"File\" and like (file, \"%.lnk\"), \"l\",\n         1=1,\" \"\n        ) \n| eventstats list(b) as allb\n| eval allb_bitmap = mvjoin(allb,\"\")\n| table _time, allb_bitmap, b, evt, file, program<\/pre>\n\n\n\n<p>giving us this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2a.png\"><img decoding=\"async\" loading=\"lazy\" width=\"963\" height=\"535\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2a.png\" alt=\"\" class=\"wp-image-9049\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2a.png 963w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2a-300x167.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2a-768x427.png 768w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2a-500x278.png 500w\" sizes=\"(max-width: 963px) 100vw, 963px\" \/><\/a><\/figure>\n\n\n\n<p>We can clearly see 2 interesting clusters, but only one fitting our criteria.<\/p>\n\n\n\n<p>We can obviously exclude the rows where the <em>b<\/em> is empty, but we still need to split these <em>lcpm<\/em> and <em>cpm<\/em> clusters into separate buckets.<\/p>\n\n\n\n<p>And the <em>bucket<\/em> is the word!<\/p>\n\n\n\n<p>Modifying our earlier code a bit:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">| eval b=\n   case (\n         evt=\"Run\" and program=\"cscript.exe\", \"c\",\n         evt=\"Run\" and program=\"powershell.exe\", \"p\",\n         evt=\"Run\" and program=\"mshta.exe\", \"m\",\n         evt=\"File\" and like (file, \"%.lnk\"), \"l\",\n         1=1,\" \"\n        ) \n| bucket _time span=10s\n| eventstats list(b) as allb by _time\n| eval allb_bitmap = mvjoin(allb,\"\")\n| where b!=\" \" and like(allb_bitmap, \"%lcpm%\")\n| table _time, allb_bitmap, evt, file, program<\/pre>\n\n\n\n<p>we get this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2b.png\"><img decoding=\"async\" loading=\"lazy\" width=\"937\" height=\"166\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2b.png\" alt=\"\" class=\"wp-image-9050\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2b.png 937w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2b-300x53.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2b-768x136.png 768w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2024\/01\/spl_bmp2b-500x89.png 500w\" sizes=\"(max-width: 937px) 100vw, 937px\" \/><\/a><\/figure>\n\n\n\n<p>We can now start the triage!<\/p>\n\n\n\n<p>Of course, there is a manual effort to this exercise and it may not be always possible to fully automate it, but I hope you can see the potential of this technique.<\/p>\n\n\n\n<p>And see how cheap that is! There are no summary indexes, nested queries, complex statistics involved &#8211; it&#8217;s just a simple exercise of putting interesting events on a one-dimensional map, and then breaking them down into manageable clusters.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post I introduced the concept of bitmap hunting. Today I will show another example that helps to find a sequence of more than 2 events. Consider this artificially generated sequence of events: | makeresults | eval _time=_time &hellip; <a href=\"https:\/\/www.hexacorn.com\/blog\/2024\/01\/06\/bitmap-hunting-in-spl-part-2\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[86,79],"tags":[],"_links":{"self":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/9047"}],"collection":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/comments?post=9047"}],"version-history":[{"count":7,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/9047\/revisions"}],"predecessor-version":[{"id":9093,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/9047\/revisions\/9093"}],"wp:attachment":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/media?parent=9047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/categories?post=9047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/tags?post=9047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}