{"id":881,"date":"2026-05-10T09:11:59","date_gmt":"2026-05-10T01:11:59","guid":{"rendered":"https:\/\/connectword.dpdns.org\/?p=881"},"modified":"2026-05-10T09:11:59","modified_gmt":"2026-05-10T01:11:59","slug":"a-coding-implementation-to-recover-hidden-malware-iocs-with-flare-floss-beyond-classic-strings-analysis","status":"publish","type":"post","link":"https:\/\/connectword.dpdns.org\/?p=881","title":{"rendered":"A Coding Implementation to Recover Hidden Malware IOCs with FLARE-FLOSS Beyond Classic Strings Analysis"},"content":{"rendered":"<p>In this tutorial, we explore how <a href=\"https:\/\/github.com\/mandiant\/flare-floss\"><strong>FLARE-FLOSS<\/strong><\/a> helps us recover hidden and obfuscated strings from a Windows PE file. We begin by setting up FLOSS and the MinGW-w64 cross-compiler. We synthesize a small malware-like executable that hides strings using multiple techniques, including static strings, stack-built strings, tight strings, and XOR-decoded strings. After that, we compare the limitations of the traditional string utility with FLOSS\u2019s deeper static analysis and emulation-based string recovery. Through this process, we learn how analysts can uncover URLs, registry paths, suspicious APIs, and other indicators of compromise that plain string extraction often misses.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">import subprocess, os, sys, json, re, time\nfrom pathlib import Path\n\n\ndef banner(t): print(\"n\" + \"\u2550\"*72 + f\"n  {t}n\" + \"\u2550\"*72)\ndef sh(cmd, quiet=False, check=False):\n   r = subprocess.run(cmd, shell=True, capture_output=True, text=True)\n   if not quiet:\n       if r.stdout: print(r.stdout.rstrip()[:4000])\n       if r.returncode and r.stderr: print(\"[stderr]\", r.stderr.rstrip()[:1500], file=sys.stderr)\n   if check and r.returncode: raise RuntimeError(cmd)\n   return r\n\n\nbanner(\"STEP 1 \u2014 Install FLOSS + MinGW-w64\")\nsh(\"pip install -q flare-floss\")\nsh(\"apt-get -qq update &amp;&amp; apt-get -qq install -y mingw-w64 binutils-mingw-w64\", quiet=True)\nsh(\"floss --version 2&gt;&amp;1 | head -3\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We set up the core Python imports, helper functions, and command runner used throughout the tutorial. We then install FLARE-FLOSS and the MinGW-w64 cross-compiler. Also, we verify the FLOSS installation by checking its version before moving into executable generation.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">banner(\"STEP 2 \u2014 Build a synthetic malware-like PE\")\nWORK = Path(\"\/content\/floss_tutorial\"); WORK.mkdir(exist_ok=True); os.chdir(WORK)\n\n\nSECRETS = [\n   (\"FAKE_FLAG_DECODED_SECRET\",                0x37),\n   (\"https:\/\/c2-totally-fake.example\/beacon\",  0x42),\n   (\"SOFTWARE\\Microsoft\\Run\\PersistDemo\",   0x5A),\n   (\"kernel32.dll!VirtualAllocEx\",             0x29),\n]\ndef xor_arr(s, k): return \",\".join(f\"0x{(ord(c)^k)&amp;0xff:02x}\" for c in s)\n\n\nc = [\n   '#include &lt;stdio.h&gt;',\n   '__attribute__((noinline)) static void xord(char* b, int n, int k){',\n   '}',\n   'int main(void){',\n   '    puts(\"PLAIN_STATIC_HELLO_FROM_FLOSS_TUTORIAL\");',\n   '',\n   '    volatile char stk[20];',\n]\nseq = \"STACK_BUILT_STRING\"\nfor i, ch in enumerate(seq): c.append(f\"    stk[{i}]='{ch}';\")\nc += [f\"    stk[{len(seq)}]=0;\", \"    puts((char*)stk);\", \"\",\n     \"    volatile char tght[]={'T','I','G','H','T','-','S','T','R',0};\",\n     \"    puts((char*)tght);\", \"\"]\nfor i,(s,k) in enumerate(SECRETS):\n   c += [f\"    char enc{i}[] = {{ {xor_arr(s,k)}, 0x00 }};\",\n         f\"    xord(enc{i}, {len(s)}, 0x{k:02x});\",\n         f\"    puts(enc{i});\"]\nc += [\"    return 0;\", \"}\"]\n(WORK\/\"sample.c\").write_text(\"n\".join(c))\nsh(\"x86_64-w64-mingw32-gcc -O0 -fno-stack-protector -o sample.exe sample.c -static-libgcc\", check=True)\nprint(f\"n\u2713 sample.exe built ({(WORK\/'sample.exe').stat().st_size:,} bytes)\")\nsh(\"file sample.exe\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We create a synthetic Windows PE file that serves as a safe malware analysis sample for learning string recovery. We hide strings using multiple techniques, including plain static text, stack-built strings, tight strings, and XOR-encoded secrets. We then compile the generated C source into sample.exe so FLOSS can analyze it like a real Windows executable.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">banner(\"STEP 3 \u2014 Classic `strings` baseline (what gets MISSED)\")\nclassic = set(subprocess.run(\"strings -a -n 6 sample.exe\", shell=True,\n             capture_output=True, text=True).stdout.splitlines())\nprint(f\"`strings` extracted {len(classic):,} candidates total.\")\nprint(\"Coverage of our planted secrets in plain `strings`:\")\nplanted = [\"PLAIN_STATIC_HELLO_FROM_FLOSS_TUTORIAL\", \"STACK_BUILT_STRING\", \"TIGHT-STR\"] + [s for s,_ in SECRETS]\nfor s in planted:\n   hit = any(s in line for line in classic)\n   print(f\"  {'\u2713 FOUND ' if hit else '\u2717 MISSED'}  {s}\")\n\n\nbanner(\"STEP 4 \u2014 Run FLOSS (vivisect static + emulation; ~30\u201390 s)\")\nt0 = time.time()\nsh(\"floss --json sample.exe &gt; floss.json 2&gt; floss.log\")\nprint(f\"n[FLOSS finished in {time.time()-t0:.1f}s]\")\nprint(\"--- last lines of FLOSS log ---\")\nsh(\"tail -15 floss.log\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We run the traditional strings command first to understand what a basic string extraction tool can and cannot detect. We compare each planted secret against the classic output to identify which strings are found and which are missed. We then run FLOSS on the executable and save both the JSON output and the log file for deeper structured analysis.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">banner(\"STEP 5 \u2014 Parse FLOSS JSON output\")\nwith open(\"floss.json\") as f: data = json.load(f)\n\n\ndef extract(key):\n   out = []\n   for e in data.get(\"strings\", {}).get(key, []):\n       if isinstance(e, dict): out.append(e)\n       else: out.append({\"string\": e})\n   return out\n\n\nstatic_s, stack_s = extract(\"static_strings\"), extract(\"stack_strings\")\ntight_s,  decoded_s = extract(\"tight_strings\"),  extract(\"decoded_strings\")\nbuckets = {\"static\": static_s, \"stack\": stack_s, \"tight\": tight_s, \"decoded\": decoded_s}\n\n\nprint(f\"  metadata.version : {data.get('metadata', {}).get('version','?')}\")\nfor k,v in buckets.items(): print(f\"  {k+'_strings':&lt;17}: {len(v):&gt;5}\")\n\n\nprint(\"nDecoded strings recovered (with decoder routine info):\")\nfor e in decoded_s:\n   s = e.get(\"string\",\"\")\n   rtn = e.get(\"decoding_routine\"); addr = e.get(\"address\")\n   rtn_s = f\"0x{rtn:x}\" if isinstance(rtn,int) else str(rtn)\n   addr_s = f\"0x{addr:x}\" if isinstance(addr,int) else str(addr)\n   print(f\"  decoder={rtn_s:&lt;12} at={addr_s:&lt;12} \u2192 {s!r}\")\nprint(\"nStack \/ tight strings recovered:\")\nfor e in stack_s + tight_s: print(f\"  \u2192 {e.get('string','')!r}\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We load the FLOSS JSON output and organize the recovered strings into static, stack, tight, and decoded categories. We print the metadata and string counts to understand the overall recovery results. We also inspect decoded, stack, and tight strings to see which hidden values FLOSS successfully extracts.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">banner(\"STEP 6 \u2014 IOC hunting in the deobfuscated strings\")\nPATTERNS = [\n   (\"URL\",          re.compile(r\"https?:\/\/[^s\"&lt;&gt;]+\")),\n   (\"IP\",           re.compile(r\"b(?:d{1,3}.){3}d{1,3}b\")),\n   (\"PE\/script\",    re.compile(r\"[A-Za-z0-9_]+.(?:exe|dll|sys|ps1|bat)b\", re.I)),\n   (\"Win32 API\",    re.compile(r\"b(?:Reg(?:Open|Set|Create|Delete)Key(?:Ex)?A?|VirtualAlloc(?:Ex)?|CreateRemoteThread|WinExec|LoadLibraryA?|GetProcAddress|InternetOpenA?)b\")),\n   (\"Registry\",     re.compile(r\"SOFTWARE\\\\?[A-Za-z0-9_\\\\]+\", re.I)),\n   (\"Base64-like\",  re.compile(r\"b[A-Za-z0-9+\/]{24,}={0,2}b\")),\n]\nhits = []\nfor kind, items in buckets.items():\n   for e in items:\n       s = e.get(\"string\",\"\")\n       for label, pat in PATTERNS:\n           if pat.search(s): hits.append((kind, label, s))\n\n\nif hits:\n   print(f\"{'BUCKET':&lt;10}{'IOC':&lt;14}STRING\")\n   print(\"-\"*72)\n   for kind,lbl,s in hits[:40]:\n       print(f\"{kind:&lt;10}{lbl:&lt;14}{s[:80]}\")\n   print(f\"n\u2192 {len(hits)} IOC hits total. Note: most are inside the 'decoded' bucket\")\n   print(\"  \u2014 those would be invisible to plain `strings`!\")\nelse:\n   print(\"(no IOC pattern matches)\")\n\n\nbanner(\"STEP 7 \u2014 Visualize string-type counts and length distribution\")\nimport matplotlib.pyplot as plt\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 4.5))\n\n\nlabels = list(buckets); counts = [len(v) for v in buckets.values()]\nbars = ax1.bar(labels, counts, color=[\"#5fa8d3\",\"#62b6cb\",\"#cae9ff\",\"#ff7b7b\"])\nax1.set_title(\"FLOSS strings by type\"); ax1.set_ylabel(\"count\")\nfor b,n in zip(bars,counts): ax1.text(b.get_x()+b.get_width()\/2, n, str(n), ha=\"center\", va=\"bottom\")\n\n\nfor kind, items in buckets.items():\n   lens = [len(e.get(\"string\",\"\")) for e in items]\n   if lens: ax2.hist(lens, bins=30, alpha=0.55, label=f\"{kind} (n={len(lens)})\")\nax2.set_title(\"String-length distribution\"); ax2.set_xlabel(\"characters\")\nax2.set_ylabel(\"frequency (log)\"); ax2.set_yscale(\"log\"); ax2.legend()\nplt.tight_layout(); plt.savefig(\"floss_summary.png\", dpi=110); plt.show()\n\n\nprint(\"n\u2713 Tutorial complete.\")\nprint(f\"   Artifacts: {WORK\/'sample.exe'}, {WORK\/'floss.json'}, {WORK\/'floss_summary.png'}\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We search all recovered strings for useful indicators such as URLs, IP addresses, DLL names, Win32 APIs, registry paths, and base64-like values. We display each IOC match with its corresponding string bucket so we can understand where important evidence appears. We finish by visualizing string counts and length distributions, then save the final summary image as an artifact.<\/p>\n<p>In conclusion, we built a complete hands-on workflow for analyzing obfuscated strings in a synthetic Windows executable using FLARE-FLOSS. We saw how simple command-line string extraction can miss important evidence, while FLOSS can recover decoded, stack-based, and tightly constructed strings that are useful during malware triage. We also parsed FLOSS\u2019s JSON output, hunted for IOC patterns, and visualized the recovered string categories to make the results easier to understand. It gives us a practical foundation for using FLOSS in reverse engineering, malware analysis, and security research workflows.<\/p>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<p>Check out\u00a0the\u00a0<strong><a href=\"https:\/\/github.com\/Marktechpost\/AI-Agents-Projects-Tutorials\/blob\/main\/Security\/recover_hidden_malware_iocs_with_flare_floss_Marktechpost.ipynb\" target=\"_blank\" rel=\"noreferrer noopener\">Full Codes here<\/a><\/strong>\u00a0<strong>.\u00a0<\/strong>Also,\u00a0feel free to follow us on\u00a0<strong><a href=\"https:\/\/x.com\/intent\/follow?screen_name=marktechpost\" target=\"_blank\" rel=\"noreferrer noopener\"><mark>Twitter<\/mark><\/a><\/strong>\u00a0and don\u2019t forget to join our\u00a0<strong><a href=\"https:\/\/www.reddit.com\/r\/machinelearningnews\/\" target=\"_blank\" rel=\"noreferrer noopener\">150k+ ML SubReddit<\/a><\/strong>\u00a0and Subscribe to\u00a0<strong><a href=\"https:\/\/www.aidevsignals.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">our Newsletter<\/a><\/strong>. Wait! are you on telegram?\u00a0<strong><a href=\"https:\/\/t.me\/machinelearningresearchnews\" target=\"_blank\" rel=\"noreferrer noopener\">now you can join us on telegram as well.<\/a><\/strong><\/p>\n<p>Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.?\u00a0<strong><a href=\"https:\/\/forms.gle\/MTNLpmJtsFA3VRVd9\" target=\"_blank\" rel=\"noreferrer noopener\"><mark>Connect with us<\/mark><\/a><\/strong><\/p>\n<p>The post <a href=\"https:\/\/www.marktechpost.com\/2026\/05\/09\/a-coding-implementation-to-recover-hidden-malware-iocs-with-flare-floss-beyond-classic-strings-analysis\/\">A Coding Implementation to Recover Hidden Malware IOCs with FLARE-FLOSS Beyond Classic Strings Analysis<\/a> appeared first on <a href=\"https:\/\/www.marktechpost.com\/\">MarkTechPost<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we explore h&hellip;<\/p>\n","protected":false},"author":1,"featured_media":29,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-881","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/posts\/881","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=881"}],"version-history":[{"count":0,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/posts\/881\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/media\/29"}],"wp:attachment":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=881"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=881"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=881"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}