What building my own security tools taught me about penetration testing

Cyber security
People behind the post

Finding vulnerabilities is one thing. Understanding how they can be exploited, which risks really matter and what it takes to prevent them is another. Here’s why I build my own security tools.

For me, some of the most valuable lessons in penetration testing haven't come from using security tools. They've come from trying to build them, developing vulnerable applications, and creating malicious proof-of-concept apps to understand how attacks work in the real world.

Mobile penetration testing covers a lot of ground. There’s the Android or iOS version an app runs on, how it stores data, how it communicates with backend services, and whether additional protections against reverse engineering or tampering are needed.

Not every application needs the same security measures. Should a simple information app refuse to run on a rooted phone? Does it need to block emulators? Would that improve security, or just inconvenience users and create unnecessary development work?

The answer depends on what the application does, what it protects, and how it might realistically be attacked.

Learning by building

To better understand those decisions, I started building mobile apps. Seeing development from the other side helped me appreciate how difficult some security controls can be to implement, and how easy it is to overlook something while concentrating on getting a feature working.

My early attempts certainly contained issues I would have raised during a penetration test. Luckily, I didn't have customers using them! But building legitimate applications only showed me one side of the problem. Building malicious applications to exploit those weaknesses taught me something entirely different.

Suddenly, a vulnerability wasn't just an entry in a security report. I had to understand what made it exploitable, what permissions an attacker needed, how Android and iOS enforce their security boundaries, and what could prevent the attack from succeeding.

More importantly, I started seeing defensive measures differently. Some controls that initially seemed unnecessary became much more important once I understood how attackers could take advantage of their absence. Others, despite being regularly highlighted by security scanners, offered little meaningful protection in certain circumstances.

When I started working with mobile phones, back when network unlocking was treated almost like a trade secret, there were far fewer accessible tools and resources. Things have improved enormously. Open-source tooling is more mature, and AI is making it easier for both security testers and attackers to build their own tools.

When a vulnerability isn't what it seems

But there's a limitation I keep coming across: automated scanners can be very good at identifying potential weaknesses, but they can’t always determine whether those weaknesses present a realistic threat. It's one of the reasons manual and automated penetration testing work best together.

Sometimes, a scanner can flag a serious-looking vulnerability without accounting for protections already built into the operating system. Take Android task hijacking. A scanner might inspect an app's AndroidManifest.xml, see that an exported Activity doesn't explicitly restrict taskAffinity or specify a defensive launchMode, and flag a potential StrandHogg vulnerability.

That sounds serious. The original attack could allow a malicious application to manipulate Android's task management and display a convincing fake screen over a legitimate application, potentially tricking users into entering sensitive information.

Now look at the same app's minimum supported Android version:

<uses-sdk android:minSdkVersion="30" />

Android 11 (API level 30) and later include protections against that specific StrandHogg task-affinity vulnerability.

The missing configuration may still be worth reviewing, and other Activity-related attacks still deserve testing. But reporting the original StrandHogg issue as exploitable solely because a manifest setting is absent would be misleading.

Understanding how the attack works, and what Android already does to prevent it, changes how you assess that finding.

Building my own scanning tools

This is where developing my own scanning tools became another valuable learning experience.

Rather than simply reproducing existing security checks, I wanted to understand what each check was looking for and why. That meant studying application code, Android's security mechanisms, the differences between platform versions, and the defensive measures available to developers.

I began combining static inspection of application code and configuration with dynamic testing using Frida. I also wanted the results to explain which OWASP MASVS control or MASTG test they relate to, why a particular behaviour might be dangerous, and what circumstances would make it genuinely exploitable.

Writing those checks forces me to go much deeper than running a scanner and interpreting its output. I have to understand how a vulnerability manifests in Java, Kotlin, and compiled Android code, how to identify it reliably, and how to avoid reporting issues that aren't relevant to the application being assessed.

I'm now exploring how to improve those checks when applications use code obfuscation. That brings its own challenges and plenty of debugging. I'm not a professional software developer, so progress isn't always quick. But every problem I work through teaches me something about the attack surface I'm trying to assess.

Beyond identifying vulnerabilities

I still use established security tools, and building my own doesn't replace them. It's about developing a deeper understanding of what they're telling me and recognising what they might miss.

For example, a scanner might flag an application’s custom URL scheme as potentially hijackable. But understanding how that scheme works, what information passes through it, and whether an attacker could achieve anything meaningful can completely change the finding.

That understanding carries directly into the testing we do at Zoonou. Rather than simply reporting a missing security control, I can explain whether it presents a realistic risk, demonstrate how it could be exploited where applicable, and recommend changes that address the actual weakness without creating unnecessary work for developers.

Building legitimate applications taught me why security weaknesses happen. Building malicious applications gave me an even deeper understanding of how attackers exploit them. Building defensive scanning tools taught me how to recognise those weaknesses and understand which protections matter most.

Together, those experiences have changed how I approach penetration testing. Ultimately, our job isn't simply to identify everything that could be considered insecure. It's to understand what an attacker could realistically achieve, which defences would stop them, and how we can help developers make their applications genuinely more secure.

Looking for a more thoughtful approach to penetration testing? Our security team brings curiosity and a deeper understanding of vulnerabilities to every project. Let's chat.

You might also like

More articles

How we build fresh perspectives into every penetration test

Cyber security
How we build fresh perspectives into every penetration test

Mobile and web penetration testing: why one usually takes more time and effort

Cyber security
Mobile and web penetration testing: why one usually takes more time and effort

Building safe AI: four key security risks for LLMs

Cyber security
Building safe AI: four key security risks for LLMs