<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jr Carreiro</title>
    <description>The latest articles on DEV Community by Jr Carreiro (@jr_carreiro).</description>
    <link>https://dev.to/jr_carreiro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3039519%2F6834dd96-683e-4d78-ad2c-7a93098dd1ec.png</url>
      <title>DEV Community: Jr Carreiro</title>
      <link>https://dev.to/jr_carreiro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jr_carreiro"/>
    <language>en</language>
    <item>
      <title>Deep Dive into Info.plist Security Flags for Penetration Testing</title>
      <dc:creator>Jr Carreiro</dc:creator>
      <pubDate>Sun, 22 Jun 2025 23:28:15 +0000</pubDate>
      <link>https://dev.to/jr_carreiro/deep-dive-into-infoplist-security-flags-for-penetration-testing-2cc6</link>
      <guid>https://dev.to/jr_carreiro/deep-dive-into-infoplist-security-flags-for-penetration-testing-2cc6</guid>
      <description>&lt;p&gt;When performing penetration tests or static analysis on iOS/macOS applications, one of the most overlooked but critical files is &lt;code&gt;Info.plist&lt;/code&gt;. This file contains configuration keys that control behavior, privacy permissions, app transport security, input handling, and much more.&lt;/p&gt;

&lt;p&gt;Many of these settings can unintentionally expose sensitive data, allow insecure communications, or increase the attack surface of an app. This article provides a detailed analysis of &lt;strong&gt;common &lt;code&gt;Info.plist&lt;/code&gt; keys&lt;/strong&gt;, explains their technical behavior, illustrates &lt;strong&gt;real-world abuse cases&lt;/strong&gt;, and offers &lt;strong&gt;security best practices&lt;/strong&gt; for each.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Debugging &amp;amp; Security Flags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Technical Description&lt;/th&gt;
&lt;th&gt;Usage in Development&lt;/th&gt;
&lt;th&gt;Security Risk&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;th&gt;Best Practice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UIFileSharingEnabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Boolean (&lt;code&gt;false&lt;/code&gt; by default). If &lt;code&gt;true&lt;/code&gt;, exposes the app’s &lt;code&gt;Documents/&lt;/code&gt; directory to iTunes/Finder file sharing.&lt;/td&gt;
&lt;td&gt;Apps that allow file import/export (e.g. document editors).&lt;/td&gt;
&lt;td&gt;Attackers with physical access can extract SQLite databases, tokens, and logs stored in &lt;code&gt;Documents/&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;Productivity apps exposed sensitive files via this flag in earlier iOS versions.&lt;/td&gt;
&lt;td&gt;Set to &lt;code&gt;false&lt;/code&gt; for production; move sensitive data to &lt;code&gt;Library/Private&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LSSupportsOpeningDocumentsInPlace&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows editing files from external sources like iCloud without copying into the sandbox.&lt;/td&gt;
&lt;td&gt;Used by code editors, drawing tools.&lt;/td&gt;
&lt;td&gt;Malicious apps can overwrite or tamper with files through symbolic links or sandbox escapes.&lt;/td&gt;
&lt;td&gt;Exploits have overwritten "in-place" Realm DB files to cause corruption or injection.&lt;/td&gt;
&lt;td&gt;Use security-scoped bookmarks and validate file access repeatedly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UIApplicationExitsOnSuspend&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;true&lt;/code&gt;, the app terminates when backgrounded. Prevents lingering memory data.&lt;/td&gt;
&lt;td&gt;Used by banking or password vaults to increase memory security.&lt;/td&gt;
&lt;td&gt;If &lt;code&gt;false&lt;/code&gt;, sensitive keys/tokens may stay in memory until system purges the app.&lt;/td&gt;
&lt;td&gt;Trading apps leaked access tokens in suspended state.&lt;/td&gt;
&lt;td&gt;Enable if the UX permits and wipe memory on background transition.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UIBackgroundModes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows specific background capabilities: &lt;code&gt;audio&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;location&lt;/code&gt;, etc.&lt;/td&gt;
&lt;td&gt;Messaging, music, or GPS apps.&lt;/td&gt;
&lt;td&gt;Overused modes (like &lt;code&gt;location&lt;/code&gt;) enable data exfiltration and power analysis attacks.&lt;/td&gt;
&lt;td&gt;Citizen Lab reported spyware using &lt;code&gt;location&lt;/code&gt; + &lt;code&gt;bluetooth-central&lt;/code&gt; for passive surveillance.&lt;/td&gt;
&lt;td&gt;Declare only necessary modes and monitor task lifetimes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ITSAppUsesNonExemptEncryption&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Indicates use of strong encryption (for export compliance).&lt;/td&gt;
&lt;td&gt;Games or simple apps might set &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;Setting &lt;code&gt;false&lt;/code&gt; while using TLS violates compliance (e.g. GDPR, PCI).&lt;/td&gt;
&lt;td&gt;US lottery apps were delisted after audit revealed encrypted traffic but &lt;code&gt;false&lt;/code&gt; flag.&lt;/td&gt;
&lt;td&gt;Always set to &lt;code&gt;true&lt;/code&gt; when using TLS, AES, or RSA.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UIApplicationSupportsIndirectInputEvents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enables input from external devices like braille or USB keyboards.&lt;/td&gt;
&lt;td&gt;Accessibility or point-of-sale apps.&lt;/td&gt;
&lt;td&gt;Allows injection or keylogging via HID spoofing.&lt;/td&gt;
&lt;td&gt;Black Hat 2021 showed USB devices injecting malicious sequences.&lt;/td&gt;
&lt;td&gt;Only enable if needed and whitelist HID inputs.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🌐 Network &amp;amp; Data Security Flags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Technical Description&lt;/th&gt;
&lt;th&gt;Usage in Development&lt;/th&gt;
&lt;th&gt;Security Risk&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;th&gt;Best Practice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSAllowsArbitraryLoads&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Disables ATS (App Transport Security) and allows insecure HTTP.&lt;/td&gt;
&lt;td&gt;Used during HTTP-to-HTTPS migration.&lt;/td&gt;
&lt;td&gt;Enables MITM attacks, downgrades, and data leakage.&lt;/td&gt;
&lt;td&gt;Banking apps leaked analytics data over HTTP due to this setting.&lt;/td&gt;
&lt;td&gt;Always &lt;code&gt;false&lt;/code&gt;; use &lt;code&gt;NSExceptionDomains&lt;/code&gt; for granular exceptions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSExceptionDomains&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Specifies per-domain ATS exceptions like cipher suite or TLS version.&lt;/td&gt;
&lt;td&gt;Whitelist legacy servers.&lt;/td&gt;
&lt;td&gt;Wildcards (&lt;code&gt;NSIncludesSubdomains=true&lt;/code&gt;) expose QA/staging to attack.&lt;/td&gt;
&lt;td&gt;QA environments exposed via CDN wildcard subdomains.&lt;/td&gt;
&lt;td&gt;Define exact hostnames and monitor for abuse.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSAllowsLocalNetworking&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows connections to &lt;code&gt;.local&lt;/code&gt; or Bonjour services without TLS.&lt;/td&gt;
&lt;td&gt;IoT configuration apps (e.g. smart devices).&lt;/td&gt;
&lt;td&gt;App can scan internal network, pivot, or exploit devices.&lt;/td&gt;
&lt;td&gt;PoC app extracted default credentials from IP cams on LAN.&lt;/td&gt;
&lt;td&gt;Validate Bonjour targets and restrict protocols.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSAppTransportSecurity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Master dictionary that controls ATS settings.&lt;/td&gt;
&lt;td&gt;Required for modern iOS apps.&lt;/td&gt;
&lt;td&gt;Weak or incomplete settings (e.g. RC4 cipher allowed) reduce security posture.&lt;/td&gt;
&lt;td&gt;MOBIX identified apps allowing insecure TLS versions.&lt;/td&gt;
&lt;td&gt;Enforce TLS 1.2+, perfect forward secrecy, and CT.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSContactsUsageDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Custom prompt when accessing user contacts.&lt;/td&gt;
&lt;td&gt;Social apps or calendars.&lt;/td&gt;
&lt;td&gt;Poor justification leads to over-permission; can aid phishing or spam.&lt;/td&gt;
&lt;td&gt;Casual games uploaded contact lists to ad brokers.&lt;/td&gt;
&lt;td&gt;Use clear messages and encrypt data at rest.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔒 Privacy &amp;amp; Data Exposure Risks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Technical Description&lt;/th&gt;
&lt;th&gt;Usage in Development&lt;/th&gt;
&lt;th&gt;Security Risk&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;th&gt;Best Practice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSCameraUsageDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prompt shown when using the camera.&lt;/td&gt;
&lt;td&gt;Document scanners, AR apps.&lt;/td&gt;
&lt;td&gt;Can enable covert surveillance without feedback.&lt;/td&gt;
&lt;td&gt;Zoom macOS bug kept camera active post-call.&lt;/td&gt;
&lt;td&gt;Show visual indicators and pause when backgrounded.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSMicrophoneUsageDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prompt for microphone access.&lt;/td&gt;
&lt;td&gt;VoIP or recording apps.&lt;/td&gt;
&lt;td&gt;Eavesdropping or background recording.&lt;/td&gt;
&lt;td&gt;Pegasus malware used microphone access post-jailbreak.&lt;/td&gt;
&lt;td&gt;Disable session when inactive.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSPhotoLibraryUsageDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows access to the user’s photo library.&lt;/td&gt;
&lt;td&gt;Editors, uploaders, social media.&lt;/td&gt;
&lt;td&gt;EXIF GPS metadata can reveal sensitive locations.&lt;/td&gt;
&lt;td&gt;Ad SDKs used image hashes for fingerprinting.&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;PHPickerViewController&lt;/code&gt; to limit scope.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSLocationAlwaysUsageDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enables tracking even when the app is closed.&lt;/td&gt;
&lt;td&gt;Navigation, delivery apps.&lt;/td&gt;
&lt;td&gt;Tracking across time and space violates user expectations.&lt;/td&gt;
&lt;td&gt;Data brokers bought GPS data from health-related apps.&lt;/td&gt;
&lt;td&gt;Prefer &lt;code&gt;WhenInUse&lt;/code&gt;; provide toggles for users.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NSUserTrackingUsageDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required by AppTrackingTransparency (ATT) to access IDFA.&lt;/td&gt;
&lt;td&gt;Ad monetization.&lt;/td&gt;
&lt;td&gt;Apps that fingerprint users after denial violate ATT/GDPR.&lt;/td&gt;
&lt;td&gt;Adjust SDK was rejected by Apple for ATT circumvention.&lt;/td&gt;
&lt;td&gt;Only use when critical for ad revenue.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ⚙️ App Execution &amp;amp; IPC Risks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Technical Description&lt;/th&gt;
&lt;th&gt;Usage in Development&lt;/th&gt;
&lt;th&gt;Security Risk&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;th&gt;Best Practice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;CFBundleURLTypes&lt;/code&gt; (Deep Linking)&lt;/td&gt;
&lt;td&gt;Registers custom URL schemes (&lt;code&gt;myapp://&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;Password reset flows, login deep links.&lt;/td&gt;
&lt;td&gt;Other apps can hijack and invoke these URLs with malicious input.&lt;/td&gt;
&lt;td&gt;Health apps vulnerable to OAuth token theft via deep link hijacking.&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;Universal Links&lt;/code&gt; with HTTPS and signed association.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CFBundleExecutable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defines the binary name.&lt;/td&gt;
&lt;td&gt;Apps using multiple binaries.&lt;/td&gt;
&lt;td&gt;Tampering attacks can replace the binary post-install.&lt;/td&gt;
&lt;td&gt;Masque Attack (2014) exploited bundle executable swaps.&lt;/td&gt;
&lt;td&gt;Validate executable hash in runtime.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CFBundleIdentifier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;App’s unique reverse-DNS ID.&lt;/td&gt;
&lt;td&gt;Build separation (prod, QA).&lt;/td&gt;
&lt;td&gt;Identifier collisions allow data theft via malicious apps.&lt;/td&gt;
&lt;td&gt;Masque Attack cloned bundle ID to extract Keychain data.&lt;/td&gt;
&lt;td&gt;Only install from trusted sources; enforce code signing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UIRequiresFullScreen&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Forces full-screen mode.&lt;/td&gt;
&lt;td&gt;Games and immersive apps.&lt;/td&gt;
&lt;td&gt;Hides status bar or security indicators like mic/camera usage.&lt;/td&gt;
&lt;td&gt;Lottery apps hid indicators using fullscreen overlays.&lt;/td&gt;
&lt;td&gt;Allow multitasking unless UX absolutely requires fullscreen.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LSApplicationQueriesSchemes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows checking if other apps are installed.&lt;/td&gt;
&lt;td&gt;Deep link logic or conditional flows.&lt;/td&gt;
&lt;td&gt;Overuse creates fingerprinting vectors.&lt;/td&gt;
&lt;td&gt;Some apps queried 50+ schemes for tracking.&lt;/td&gt;
&lt;td&gt;Limit to critical schemes only.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;These &lt;code&gt;Info.plist&lt;/code&gt; keys, while often viewed as just metadata, can have a &lt;strong&gt;massive impact on an app’s security posture&lt;/strong&gt;. Static analysis of the &lt;code&gt;Info.plist&lt;/code&gt; is a key part of mobile pentesting, jailbreak bypass detection, and compliance validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  📫 About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Júnior Carreiro]&lt;/strong&gt;&lt;br&gt;
🔐 Mobile AppSec | iOS Security | Reverse Engineering&lt;br&gt;
📍 Let's connect: [&lt;a href="https://github.com/jrcarreiro" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;] · [&lt;a href="http://linkedin.com/in/juniorcarreiro/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;]&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🔵 Chapter 02 – Ruby Language Fundamentals (Line by Line for Absolute Beginners)</title>
      <dc:creator>Jr Carreiro</dc:creator>
      <pubDate>Thu, 08 May 2025 14:57:07 +0000</pubDate>
      <link>https://dev.to/jr_carreiro/chapter-02-ruby-language-fundamentals-line-by-line-for-absolute-beginners-iop</link>
      <guid>https://dev.to/jr_carreiro/chapter-02-ruby-language-fundamentals-line-by-line-for-absolute-beginners-iop</guid>
      <description>&lt;p&gt;Welcome to Chapter 02 of my learning journey through scripting and offensive security.&lt;/p&gt;

&lt;p&gt;I’m not just learning to code — I’m learning to &lt;strong&gt;build, document, and explain&lt;/strong&gt;.&lt;br&gt;
This series is based on &lt;em&gt;Hacking with Go&lt;/em&gt;, but reimagined in &lt;strong&gt;Ruby and Swift&lt;/strong&gt;, with step-by-step examples and real-world analogies to help anyone understand — even if you’ve never written a single line of code.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 What we’ll cover in this chapter:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📦 Variables (how to store information)&lt;/li&gt;
&lt;li&gt;🔁 Loops (how to repeat actions)&lt;/li&gt;
&lt;li&gt;🔀 Conditionals (how to make decisions)&lt;/li&gt;
&lt;li&gt;🧠 Functions (how to reuse logic)&lt;/li&gt;
&lt;li&gt;💬 Input/Output (how to talk to the user)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Variables – Giving names to values
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;p&gt;We’re storing data in memory using &lt;strong&gt;variables&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; holds the string &lt;code&gt;"Alice"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;age&lt;/code&gt; holds the number &lt;code&gt;30&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of variables like &lt;strong&gt;stickers you put on boxes&lt;/strong&gt; — the name tells you what’s inside.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 Loops – Repeating things automatically
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Knock knock!"&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;3.times&lt;/code&gt; runs the block &lt;strong&gt;three times&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;puts&lt;/code&gt; prints the message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is like telling a kid: “Say ‘knock knock!’ three times” — and they’ll do it without question.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔀 Conditionals – Making decisions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"swordfish"&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"swordfish"&lt;/span&gt;  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Access granted!"&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Access denied!"&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;p&gt;We check a condition:&lt;br&gt;
If the password matches, we let the person in. Otherwise, we block them.&lt;/p&gt;

&lt;p&gt;It’s like checking someone’s ID before opening the door.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Methods – Reusable blocks of logic
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;&lt;span class="n"&gt;endputs&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;p&gt;We’re defining a method (like a mini-program) that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes one input: &lt;code&gt;name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Returns a message using string interpolation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calling &lt;code&gt;greet("Alice")&lt;/code&gt; is like pushing a button labeled “Say hello to Alice.”&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 User Input – Interacting with people
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"What's your name? "&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chompputs&lt;/span&gt; &lt;span class="s2"&gt;"Welcome, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;print&lt;/code&gt; shows a prompt without a newline&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gets&lt;/code&gt; waits for input from the user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chomp&lt;/code&gt; removes the trailing newline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how Ruby &lt;strong&gt;talks to the user&lt;/strong&gt; — and listens back.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Final Recap
&lt;/h2&gt;

&lt;p&gt;📦 &lt;strong&gt;Variables&lt;/strong&gt; → Store information with names&lt;br&gt;
🔁 &lt;strong&gt;Loops&lt;/strong&gt; → Repeat things automatically&lt;br&gt;
🔀 &lt;strong&gt;Conditionals&lt;/strong&gt; → Make decisions&lt;br&gt;
🧠 &lt;strong&gt;Methods&lt;/strong&gt; → Reuse blocks of logic&lt;br&gt;
💬 &lt;strong&gt;Input/Output&lt;/strong&gt; → Talk to the user&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ You’ve learned the building blocks
&lt;/h2&gt;

&lt;p&gt;This chapter gave you everything you need to start writing real scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next up: we’ll dive into &lt;strong&gt;useful packages and Ruby gems&lt;/strong&gt; to do powerful things like parsing files, automating tasks, and working with the web.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  📫 About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Júnior Carreiro]&lt;/strong&gt;&lt;br&gt;
🔐 Mobile AppSec | iOS Security | Reverse Engineering&lt;br&gt;
📍 Let's connect: [&lt;a href="https://github.com/jrcarreiro" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;] · [&lt;a href="http://linkedin.com/in/juniorcarreiro/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>hacking</category>
      <category>ruby</category>
      <category>appsec</category>
      <category>learning</category>
    </item>
    <item>
      <title>🧠 iOS Reverse Engineering: iOS SQL Injection Challenge</title>
      <dc:creator>Jr Carreiro</dc:creator>
      <pubDate>Wed, 30 Apr 2025 12:34:05 +0000</pubDate>
      <link>https://dev.to/jr_carreiro/ios-reverse-engineering-ios-sql-injection-challenge-3f2c</link>
      <guid>https://dev.to/jr_carreiro/ios-reverse-engineering-ios-sql-injection-challenge-3f2c</guid>
      <description>&lt;p&gt;A Technical Walkthrough from Binary Analysis to Runtime Query Manipulation&lt;/p&gt;

&lt;p&gt;Welcome to this detailed walkthrough of the &lt;a href="https://www.mobilehackinglab.com/course/lab-flipcoin-wallet" rel="noopener noreferrer"&gt;Flipcoin Wallet iOS&lt;/a&gt; challenge, part of the &lt;a href="https://www.mobilehackinglab.com/start" rel="noopener noreferrer"&gt;Mobile Hacking Lab&lt;/a&gt; training platform.&lt;/p&gt;

&lt;p&gt;Our mission?&lt;/p&gt;

&lt;p&gt;✅ Unpack and reverse the application.&lt;br&gt;
✅ Identify insecure SQL query construction.&lt;br&gt;
✅ Confirm the presence of a SQL Injection vulnerability.&lt;br&gt;
✅ Bypass UI limitations using Frida instrumentation.&lt;br&gt;
✅ Inject a custom SQL payload and extract the hidden flag — documenting every step with clarity.&lt;/p&gt;
&lt;h2&gt;
  
  
  🎯 Objective
&lt;/h2&gt;

&lt;p&gt;This project aims to &lt;strong&gt;identify and exploit a SQL Injection vulnerability&lt;/strong&gt; in the Flipcoin Wallet iOS application. We will demonstrate how a poorly constructed SQL query can be manipulated to extract sensitive data, even when there is no visible input from the user.&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠 Tools Used
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Tool&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frida&lt;/td&gt;
&lt;td&gt;Dynamic instrumentation and runtime memory manipulation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Radare2 / rabin2&lt;/td&gt;
&lt;td&gt;Static analysis of the binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TrollStore&lt;/td&gt;
&lt;td&gt;Installing unsigned apps on a jailbroken iPhone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPhone SE (jailbroken)&lt;/td&gt;
&lt;td&gt;Target device used for dynamic testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal&lt;/td&gt;
&lt;td&gt;Execution of analysis commands and scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  🧩 Analysis Steps (In Detail)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. IPA Extraction and Binary Inspection
&lt;/h3&gt;

&lt;p&gt;We started by extracting the &lt;code&gt;.ipa&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip com.mobilehackinglab.Flipcoin-Wallet6.ipa &lt;span class="nt"&gt;-d&lt;/span&gt; flipcoin_wallet_lab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the &lt;code&gt;Payload/Flipcoin Wallet.app&lt;/code&gt; folder, we located the app binary. We used &lt;code&gt;rabin2&lt;/code&gt; to inspect embedded strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rabin2 &lt;span class="nt"&gt;-zqq&lt;/span&gt; Payload/Flipcoin&lt;span class="se"&gt;\ &lt;/span&gt;Wallet.app/Flipcoin&lt;span class="se"&gt;\ &lt;/span&gt;Wallet | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'select|insert|update|delete|sqlite'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Key findings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A SQLite file: &lt;code&gt;your_database_name.sqlite&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Table: &lt;code&gt;wallet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SQL strings including &lt;code&gt;INSERT OR IGNORE INTO wallet&lt;/code&gt; and &lt;code&gt;SELECT * FROM wallet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The recovery key column contains the flag: &lt;code&gt;FLAG{fl1p_d4_c01nz}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This confirmed that the app interacts with a local SQLite database.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Function Discovery via Imports and Cross-references
&lt;/h3&gt;

&lt;p&gt;We searched for imported SQLite functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rabin2 &lt;span class="nt"&gt;-i&lt;/span&gt; Payload/Flipcoin&lt;span class="se"&gt;\ &lt;/span&gt;Wallet.app/Flipcoin&lt;span class="se"&gt;\ &lt;/span&gt;Wallet | &lt;span class="nb"&gt;grep &lt;/span&gt;sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;We found the app uses functions like &lt;code&gt;sqlite3_prepare&lt;/code&gt;, &lt;code&gt;sqlite3_exec&lt;/code&gt;, and &lt;code&gt;sqlite3_column_text&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To locate where these were used in the binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;r2 &lt;span class="nt"&gt;-A&lt;/span&gt; Payload/Flipcoin&lt;span class="se"&gt;\ &lt;/span&gt;Wallet.app/Flipcoin&lt;span class="se"&gt;\ &lt;/span&gt;Wallet
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; axt sym.imp.sqlite3_prepare
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two key functions were identified: &lt;code&gt;createWallets&lt;/code&gt; and &lt;code&gt;getWallets&lt;/code&gt;. We disassembled &lt;code&gt;getWallets&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;s 0x10000f98c
pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We confirmed that it performs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;wallet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without using parameter binding — indicating potential for SQL Injection.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Why We Switched to Frida Instead of Manual Input
&lt;/h2&gt;

&lt;p&gt;After installing the app using TrollStore on a jailbroken iPhone SE, the interface was completely broken: the layout was oversized and unusable.&lt;/p&gt;

&lt;p&gt;We attempted several UI fix strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applying view scaling using Frida scripts&lt;/li&gt;
&lt;li&gt;Iterating subviews to locate the root UIView&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All failed due to the app likely being developed in &lt;strong&gt;Flutter or SwiftUI&lt;/strong&gt;, where traditional UIKit methods no longer apply.&lt;/p&gt;

&lt;p&gt;As we could not interact via the UI, we used Frida to simulate SQL Injection &lt;strong&gt;directly at the memory level&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚔️ Simulating SQL Injection with Frida
&lt;/h2&gt;

&lt;p&gt;We built a script to intercept and replace the vulnerable query at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Script: &lt;code&gt;extract_flag_sqlite.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Intercept and replace vulnerable query&lt;/span&gt;
&lt;span class="nx"&gt;Interceptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getExportByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sqlite3_prepare&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;readUtf8String&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM wallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT 1, 2, 3, 4, recovery_key FROM wallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeUtf8String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;newQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[+] SQL query replaced:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Monitor data extraction from each column&lt;/span&gt;
&lt;span class="nx"&gt;Interceptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getExportByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sqlite3_column_text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toInt32&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;onLeave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;retval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readUtf8String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;retval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FLAG{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🚩 FLAG FOUND:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How This Works (Line by Line)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sqlite3_prepare&lt;/code&gt; is called when SQL queries are constructed.&lt;/li&gt;
&lt;li&gt;We check if the query contains &lt;code&gt;SELECT * FROM wallet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If so, we &lt;strong&gt;replace&lt;/strong&gt; the query string in memory with a malicious one that extracts the &lt;code&gt;recovery_key&lt;/code&gt; column&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;sqlite3_column_text&lt;/code&gt; is called, we read each column's content&lt;/li&gt;
&lt;li&gt;If the result contains &lt;code&gt;FLAG{&lt;/code&gt;, we print it&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The app must still execute the original function. We manually triggered it by interacting with whatever broken UI was visible, until &lt;code&gt;getWallets&lt;/code&gt; was called.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Execution:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;frida &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"Flipcoin Wallet"&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; extract_flag_sqlite.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[+] SQL query replaced: SELECT 1, 2, 3, 4, recovery_key FROM wallet
🚩 FLAG FOUND: FLAG{fl1p_d4_c01nz}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 Why This is SQL Injection
&lt;/h2&gt;

&lt;p&gt;SQL Injection is not defined by typing a payload — it’s about &lt;strong&gt;injecting or modifying a SQL query&lt;/strong&gt; due to poor query construction.&lt;/p&gt;

&lt;p&gt;In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The query is built as a static string without input sanitization&lt;/li&gt;
&lt;li&gt;No parameter binding is used&lt;/li&gt;
&lt;li&gt;Although we couldn’t inject via UI, we demonstrated the flaw by &lt;strong&gt;changing the query directly&lt;/strong&gt;, proving it is vulnerable and exploitable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a valid example of SQL Injection — only the delivery method changed (from input field to in-memory injection).&lt;/p&gt;




&lt;h2&gt;
  
  
  📫 About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Júnior Carreiro]&lt;/strong&gt;&lt;br&gt;
🔐 Mobile AppSec | iOS Security | Reverse Engineering&lt;br&gt;
📍 Let's connect: [&lt;a href="https://github.com/jrcarreiro" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;] · [&lt;a href="http://linkedin.com/in/juniorcarreiro/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;]&lt;br&gt;
🏷️ Tags: &lt;code&gt;#ios&lt;/code&gt; &lt;code&gt;#reverseengineering&lt;/code&gt; &lt;code&gt;#frida&lt;/code&gt; &lt;code&gt;#infosec&lt;/code&gt; &lt;code&gt;#mobile&lt;/code&gt;&lt;/p&gt;

</description>
      <category>appsec</category>
      <category>mobile</category>
      <category>offsec</category>
      <category>ios</category>
    </item>
    <item>
      <title>🧠 iOS Reverse Engineering: Defeating Anti-Debug</title>
      <dc:creator>Jr Carreiro</dc:creator>
      <pubDate>Fri, 25 Apr 2025 17:50:23 +0000</pubDate>
      <link>https://dev.to/jr_carreiro/ios-reverse-engineering-defeating-anti-debug-and-extracting-a-hidden-flag-58mb</link>
      <guid>https://dev.to/jr_carreiro/ios-reverse-engineering-defeating-anti-debug-and-extracting-a-hidden-flag-58mb</guid>
      <description>&lt;p&gt;&lt;em&gt;A Technical Walkthrough from Static Reversing to Dynamic Hooking&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Welcome to this advanced walkthrough of the &lt;strong&gt;&lt;a href="https://www.mobilehackinglab.com/course/lab-captain-nohook" rel="noopener noreferrer"&gt;Captain Nohook&lt;/a&gt;&lt;/strong&gt; iOS challenge, part of the &lt;a href="https://www.mobilehackinglab.com/" rel="noopener noreferrer"&gt;Mobile Hacking Lab&lt;/a&gt; training platform.&lt;/p&gt;

&lt;p&gt;Our mission?&lt;/p&gt;

&lt;p&gt;✅ Analyze the binary.&lt;br&gt;
✅ Identify anti-debug and anti-Frida mechanisms.&lt;br&gt;
✅ Patch them.&lt;br&gt;
✅ Instrument the app dynamically.&lt;br&gt;
✅ Retrieve the hidden flag — and document every single step.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧭 Objective
&lt;/h2&gt;

&lt;p&gt;Bypass anti-debug and anti-Frida protections, inject &lt;strong&gt;FridaGadget&lt;/strong&gt;, hook runtime components, and &lt;strong&gt;dynamically retrieve a hidden flag&lt;/strong&gt; from the binary.&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠 Tools &amp;amp; Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Frida 16.6.6&lt;/li&gt;
&lt;li&gt;Radare2&lt;/li&gt;
&lt;li&gt;Rabin2 (from r2 toolset)&lt;/li&gt;
&lt;li&gt;insert_dylib&lt;/li&gt;
&lt;li&gt;TrollStore (for installing the patched .ipa)&lt;/li&gt;
&lt;li&gt;Jailbroken iPhone&lt;/li&gt;
&lt;li&gt;FridaGadget.dylib&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  📦 Step 1: Extracting the .IPA
&lt;/h2&gt;

&lt;p&gt;We began by unzipping the provided &lt;code&gt;.ipa&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip com.mobilehackinglab.Captain-Nohook.ipa &lt;span class="nt"&gt;-d&lt;/span&gt; captain_nohook_dev-io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The app is extracted to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;captain_nohook_dev-io/Payload/Captain Nohook.app/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have access to the application bundle, which includes the binary &lt;code&gt;Captain Nohook&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Step 2: Static String Inspection with Rabin2
&lt;/h2&gt;

&lt;p&gt;We used the following command to find strings related to jailbreak, Frida, ptrace, and debug protection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rabin2 &lt;span class="nt"&gt;-zq&lt;/span&gt; captain_nohook_dev-io/Payload/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'frida|ptrace|sysctl|debug|jail|hook|flag'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output (excerpt):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x1001563a0 34 33 Arrr, find yerr hidden flag here!
0x10015641f 5 4 flag
0x100156450 22 21 T@"UILabel",N,W,Vflag
...
0x100157380 23 22 /usr/sbin/frida-server
0x1001573b8 12 11 FridaGadget
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We found an interesting string at address &lt;code&gt;0x1001563a0&lt;/code&gt; which is a candidate for the hidden flag.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Step 3: Analyzing the Binary with Radare2
&lt;/h2&gt;

&lt;p&gt;We opened the binary with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;r2 &lt;span class="nt"&gt;-AAA&lt;/span&gt; captain_nohook_dev-io/Payload/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find references to the interesting string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;axt 0x1001563a0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub.Captain_Nohook.ViewController.whereIsflag.allocator...ySo8UIButtonCF_100009e70 0x10000a284 [STRN:r--] add x0, x0, str.Arrr__find_yerr_hidden_flag_here_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that the string is used in a function associated with a button action. We now know what to hook dynamically.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Step 4: Injecting FridaGadget (Dynamic Instrumentation)
&lt;/h2&gt;

&lt;p&gt;After identifying anti-Frida protections and patching static binary checks, we instrumented the app with &lt;strong&gt;FridaGadget&lt;/strong&gt;, a dynamic and injectable version of the Frida runtime.&lt;/p&gt;

&lt;p&gt;FridaGadget is used to &lt;strong&gt;instrument iOS apps that cannot be easily hooked with &lt;code&gt;frida-server&lt;/code&gt;&lt;/strong&gt;, especially in non-jailbroken environments or when runtime detection is active. It works by being &lt;strong&gt;embedded into the app’s binary as a &lt;code&gt;.dylib&lt;/code&gt;&lt;/strong&gt;, which is &lt;strong&gt;automatically loaded on app launch&lt;/strong&gt; and &lt;strong&gt;communicates with Frida via USB&lt;/strong&gt;. This setup lets us inject scripts and hook into runtime behavior &lt;strong&gt;without triggering traditional detection&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧩 Step-by-Step: Embedding FridaGadget
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Copy the FridaGadget.dylib
&lt;/h4&gt;

&lt;p&gt;We used the FridaGadget.dylib already available in our system (through Objection or manual download).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; ~/.objection/ios/FridaGadget.dylib Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Insert the Gadget into the binary
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;insert_dylib &lt;span class="nt"&gt;--weak&lt;/span&gt; &lt;span class="nt"&gt;--all-yes&lt;/span&gt; @executable_path/FridaGadget.dylib Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook_patched
&lt;span class="nb"&gt;mv &lt;/span&gt;Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook_patched Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook.app/Captain&lt;span class="se"&gt;\ &lt;/span&gt;Nohook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📝 &lt;strong&gt;Why?&lt;/strong&gt; This embeds the FridaGadget using a weak LC_LOAD_DYLIB command so it won’t crash if not present. It allows Frida to auto-attach once the app is started.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Repack the IPA
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
zip &lt;span class="nt"&gt;-r&lt;/span&gt; CaptainNohook-Frida.ipa Payload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  📲 4. Install the IPA on the iPhone via TrollStore
&lt;/h3&gt;

&lt;p&gt;This step assumes a TrollStore-enabled device, allowing unsigned IPA installation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp CaptainNohook-Frida.ipa mobile@&amp;lt;iphone-ip&amp;gt;:/path/to/TrollStore/appgroup/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, the app can be launched, and Frida will auto-attach.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧵 Frida Script: monitor_flag.js
&lt;/h3&gt;

&lt;p&gt;We developed the following script to watch for UILabels and capture the real flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// monitor_flag.js&lt;/span&gt;
&lt;span class="c1"&gt;// This script is used to monitor a UILabel inside the Captain Nohook app and print whenever its text is updated.&lt;/span&gt;
&lt;span class="c1"&gt;// It relies on dynamic instrumentation using FridaGadget, allowing us to observe runtime behavior.&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🛡️ Monitoring UILabels and checking for flag updates...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// The Objective-C class we want to analyze is the ViewController defined in the Captain Nohook app.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vcClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Captain_Nohook.ViewController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Schedule the script to run on the main thread, where UI updates occur.&lt;/span&gt;
&lt;span class="nx"&gt;ObjC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ObjC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mainQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Find all live instances of the ViewController class in memory.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ObjC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chooseSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ObjC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;vcClass&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// If no instances were found, display an error and stop.&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;❌ No ViewController instance found.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Use the first found instance of the ViewController.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;✅ ViewController found:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewController&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Use Key-Value Coding (KVC) to access the UILabel that holds the flag text.&lt;/span&gt;
    &lt;span class="c1"&gt;// The property name "flag" was discovered through static analysis of the binary.&lt;/span&gt;
    &lt;span class="c1"&gt;// Specifically, we used the command:&lt;/span&gt;
    &lt;span class="c1"&gt;//    `axt 0x1001563a0`&lt;/span&gt;
    &lt;span class="c1"&gt;// which showed that the string "Arrr, find yerr hidden flag here!" was referenced inside the function:&lt;/span&gt;
    &lt;span class="c1"&gt;//    `sub.Captain_Nohook.ViewController.whereIsflag.allocator...ySo8UIButtonCF`&lt;/span&gt;
    &lt;span class="c1"&gt;// From there, we reverse engineered the relationship between the ViewController and the flag UILabel.&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flagLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueForKey_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Print the current UILabel state&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🏴‍☠️ UILabel da flag:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;   ▪️ Text:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flagLabel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;   ▪️ Hidden?:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flagLabel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isHidden&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// Intercept all calls to UILabel.setText to observe when any UILabel text is changed at runtime.&lt;/span&gt;
    &lt;span class="nx"&gt;Interceptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ObjC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UILabel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;- setText:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// `args[2]` contains the new NSString being set on the UILabel.&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ObjC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Log the modification&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;📢 UILabel modified:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;   ▪️ Class: UILabel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;   ▪️ New text:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧪 Real-Time Output After Button Press
&lt;/h3&gt;

&lt;p&gt;Once the user interacts with the app, we observed the following real output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📢 UILabel modified:
   ▪️ Class: UILabel
   ▪️ New text: Noncompliant device detected!
📢 UILabel modified:
   ▪️ Class: UILabel
   ▪️ New text: Yerr hook won't work!
📢 UILabel modified:
   ▪️ Class: UILabel
   ▪️ New text: MHL{H00k_1n_Y0ur_D3bUgg3r}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final line contains the &lt;strong&gt;hidden flag&lt;/strong&gt;, dynamically generated and not statically embedded.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This challenge tested &lt;strong&gt;binary analysis, anti-debug bypass, and live instrumentation&lt;/strong&gt; — all essential skills for mobile offensive security professionals.&lt;/p&gt;

&lt;p&gt;FridaGadget made it possible to bypass runtime checks and extract the hidden flag, even in a protected app.&lt;/p&gt;




&lt;h2&gt;
  
  
  📫 About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Júnior Carreiro]&lt;/strong&gt;&lt;br&gt;
🔐 Mobile AppSec | iOS Security | Reverse Engineering&lt;br&gt;
📍 Let's connect: [&lt;a href="https://github.com/jrcarreiro" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;] · [&lt;a href="http://linkedin.com/in/juniorcarreiro/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;]&lt;br&gt;
🏷️ Tags: &lt;code&gt;#ios&lt;/code&gt; &lt;code&gt;#reverseengineering&lt;/code&gt; &lt;code&gt;#frida&lt;/code&gt; &lt;code&gt;#infosec&lt;/code&gt; &lt;code&gt;#mobile&lt;/code&gt;&lt;/p&gt;

</description>
      <category>appsec</category>
      <category>mobile</category>
      <category>offsec</category>
      <category>ios</category>
    </item>
    <item>
      <title>🔴 Chapter 01 – Setting Up a Ruby Environment (Line by Line for Beginners</title>
      <dc:creator>Jr Carreiro</dc:creator>
      <pubDate>Mon, 14 Apr 2025 12:11:10 +0000</pubDate>
      <link>https://dev.to/jr_carreiro/chapter-01-setting-up-a-ruby-environment-line-by-line-for-beginners-53m1</link>
      <guid>https://dev.to/jr_carreiro/chapter-01-setting-up-a-ruby-environment-line-by-line-for-beginners-53m1</guid>
      <description>&lt;p&gt;Before we write any code, we need a place to work.&lt;br&gt;
Think of this like setting up your &lt;strong&gt;workshop&lt;/strong&gt; before you build a robot.&lt;/p&gt;

&lt;p&gt;Let’s organize our tools and build the simplest thing we can:&lt;br&gt;
a script that says &lt;strong&gt;"Hello, Hacker!"&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🧰 What are we building?
&lt;/h2&gt;

&lt;p&gt;We’re creating a &lt;strong&gt;Ruby project&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🗂️ Folders to keep things organized&lt;/li&gt;
&lt;li&gt;🔁 Logic we can reuse later&lt;/li&gt;
&lt;li&gt;🖥️ Scripts we can run from the terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧃 Think of this like a kitchen:&lt;br&gt;
You’ll have drawers (code) and buttons (scripts) that do things.&lt;/p&gt;


&lt;h2&gt;
  
  
  📦 Project Structure
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ruby/
└── Chapter 01 – Setting Up a Ruby Environment/
    ├── bin/
    │   └── hello_world.rb
    └── lib/
        └── hacking/
            └── core.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💻 Installing Ruby
&lt;/h2&gt;

&lt;p&gt;Choose the method for your OS:&lt;/p&gt;


&lt;h3&gt;
  
  
  ✅ Option 1 – Using &lt;code&gt;rbenv&lt;/code&gt; (Linux/macOS)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git curl build-essential libssl-dev libreadline-dev zlib1g-dev
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.rbenv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; src/configure &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="nt"&gt;-C&lt;/span&gt; src
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$HOME/.rbenv/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'eval "$(rbenv init - bash)"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv &lt;span class="nb"&gt;install &lt;/span&gt;3.3.5
rbenv global 3.3.5
ruby &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Option 2 – Using &lt;code&gt;rvm&lt;/code&gt; (macOS or Linux)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;curl gpg
curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://rvm.io/mpapis.asc | gpg &lt;span class="nt"&gt;--import&lt;/span&gt; -
&lt;span class="se"&gt;\c&lt;/span&gt;url &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://get.rvm.io | bash &lt;span class="nt"&gt;-s&lt;/span&gt; stable &lt;span class="nt"&gt;--ruby&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.rvm/scripts/rvm
rvm &lt;span class="nb"&gt;install &lt;/span&gt;3.3.5
rvm use 3.3.5 &lt;span class="nt"&gt;--default&lt;/span&gt;
ruby &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Option 3 – Windows (RubyInstaller)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download from &lt;a href="https://rubyinstaller.org" rel="noopener noreferrer"&gt;https://rubyinstaller.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run installer (check "add to PATH")&lt;/li&gt;
&lt;li&gt;Open PowerShell or CMD:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruby &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📄 lib/hacking/core.rb
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Hacking&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Core&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;
      &lt;span class="s2"&gt;"Hello, Hacker! Ready to break things? 💥"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📄 bin/hello_world.rb
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'../lib/hacking/core'&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Hacking&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ▶️ Run it!
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;ruby/Chapter&lt;span class="se"&gt;\ &lt;/span&gt;01&lt;span class="se"&gt;\ &lt;/span&gt;–&lt;span class="se"&gt;\ &lt;/span&gt;Setting&lt;span class="se"&gt;\ &lt;/span&gt;Up&lt;span class="se"&gt;\ &lt;/span&gt;a&lt;span class="se"&gt;\ &lt;/span&gt;Ruby&lt;span class="se"&gt;\ &lt;/span&gt;Environment
ruby bin/hello_world.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, Hacker! Ready to break things? 💥
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 Final Recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Concept&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;What it means&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;rbenv&lt;/code&gt; / &lt;code&gt;rvm&lt;/code&gt; / RubyInstaller&lt;/td&gt;
&lt;td&gt;Install Ruby safely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bin/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Where your scripts live&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lib/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Where your logic lives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;module&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Group of code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;self.method&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Call a method directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;require_relative&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Load local file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;puts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Print message&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ You now have:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ruby installed (on any OS)&lt;/li&gt;
&lt;li&gt;A clean project structure&lt;/li&gt;
&lt;li&gt;Your first script up and running&lt;/li&gt;
&lt;li&gt;The foundation for your Ruby offensive tools!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hackingwithruby</category>
      <category>offensivesecurity</category>
      <category>appsec</category>
      <category>mobilesec</category>
    </item>
  </channel>
</rss>
