<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Security on Clean Tech</title><link>http://www.lineon.fr/categories/security/</link><description>Recent content in Security on Clean Tech</description><generator>Hugo</generator><language>en</language><lastBuildDate>Wed, 01 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="http://www.lineon.fr/categories/security/index.xml" rel="self" type="application/rss+xml"/><item><title>Building a Threat Intel CLI Tool in Rust</title><link>http://www.lineon.fr/posts/rust-cli-threat-intel/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/rust-cli-threat-intel/</guid><description>&lt;p&gt;Python is the default language for security tooling, but Rust offers compelling advantages for CLI tools that need to be fast, distributable as a single binary, and safe by default. Here&amp;rsquo;s how I built a threat intelligence lookup tool in Rust.&lt;/p&gt;
&lt;h2 id="the-goal"&gt;The goal&lt;/h2&gt;
&lt;p&gt;A single binary that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accepts an IP, domain, or hash as input&lt;/li&gt;
&lt;li&gt;Queries VirusTotal, AbuseIPDB, and Shodan in parallel&lt;/li&gt;
&lt;li&gt;Outputs a unified JSON report&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="project-setup"&gt;Project setup&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo init threat-lookup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; threat-lookup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add reqwest --features json,rustls-tls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add tokio --features full
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add serde --features derive
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add serde_json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add clap --features derive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="cli-argument-parsing-with-clap"&gt;CLI argument parsing with Clap&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clap&lt;/span&gt;::&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[derive(Parser, Debug)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[command(name = &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;threat-lookup&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[command(about = &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Query threat intel APIs for IOCs&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// The indicator to look up (IP, domain, or hash)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Output format
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;#[arg(short, long, default_value = &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;json&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Verbose output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;#[arg(short, long)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="parallel-api-queries-with-tokio"&gt;Parallel API queries with Tokio&lt;/h2&gt;
&lt;p&gt;The key advantage of Rust here is safe, zero-cost concurrency. All three API calls happen simultaneously:&lt;/p&gt;</description></item><item><title>Writing Effective YARA Rules for Cobalt Strike Beacon Detection</title><link>http://www.lineon.fr/posts/yara-rules-for-cobalt-strike/</link><pubDate>Sat, 28 Mar 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/yara-rules-for-cobalt-strike/</guid><description>&lt;p&gt;Cobalt Strike remains one of the most prevalent post-exploitation frameworks used by both red teams and threat actors. Detecting its beacons through YARA rules is a fundamental skill for any SOC analyst or threat hunter.&lt;/p&gt;
&lt;h2 id="understanding-beacon-artifacts"&gt;Understanding beacon artifacts&lt;/h2&gt;
&lt;p&gt;Cobalt Strike beacons leave identifiable patterns in both their staged and stageless payloads. The key areas to target are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Configuration blocks&lt;/strong&gt; — the beacon stores its config in a predictable structure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sleep mask routines&lt;/strong&gt; — the obfuscation applied during sleep cycles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Named pipe patterns&lt;/strong&gt; — default pipe names are a common indicator&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="a-basic-detection-rule"&gt;A basic detection rule&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rule CobaltStrike_Beacon_Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; meta:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; description = &amp;#34;Detects Cobalt Strike beacon configuration block&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; author = &amp;#34;SOC Team&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; date = &amp;#34;2026-03&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; severity = &amp;#34;high&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; strings:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $config_header = { 00 01 00 01 00 02 ?? ?? 00 02 00 01 00 02 ?? ?? }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $default_pipe = &amp;#34;\\\\.\\pipe\\msagent_&amp;#34; ascii wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $watermark = { 00 09 00 02 00 04 }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; condition:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uint16(0) == 0x5A4D and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; filesize &amp;lt; 1MB and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ($config_header or $default_pipe) and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $watermark
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="hunting-in-memory"&gt;Hunting in memory&lt;/h2&gt;
&lt;p&gt;For in-memory detection, you&amp;rsquo;ll want rules that match against the decrypted beacon configuration. Use a tool like &lt;code&gt;pe-sieve&lt;/code&gt; or &lt;code&gt;BeaconEye&lt;/code&gt; to dump process memory first, then scan:&lt;/p&gt;</description></item></channel></rss>