---
title: How to Build a Log4Shell Detector with ProGuardCORE | Guardsquare
description: Interested in code analysis and software security? Learn how you can build a Log4Shell detector with just a few lines of code using ProGuardCORE.
image: https://23593082.hs-sites.com/hubfs/Imported_Blog_Media/How-to-Build-a-Log4Shell-Detector-with-ProGuardCORE-2.jpg
---

[![guardsquare-logo](https://insights.guardsquare.com/hs-fs/hubfs/Logos/logo-white.png?length=536&name=logo-white.png "guardsquare-logo") ](https://23593082.hs-sites.com/)

- pricing

[Request Pricing](https://www.guardsquare.com/request-pricing?hsCtaTracking=646b0379-d596-4b1a-8526-2ccbdbb0f81b%7Ce8809087-a83f-4476-8b22-34b9572013fd)

[Login](https://customers.guardsquare.com/login?utm_referrer=https%3A%2F%2Fwww.guardsquare.com%2F)

En

- [中文](https://www.guardsquare.com/zh-hans)
- [한국어](https://www.guardsquare.com/ko)
- [Português](https://www.guardsquare.com/pt-br)
- [Español](https://www.guardsquare.com/es)

<https://twitter.com/intent/tweet?original_referer=https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore&url=https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore&source=tweetbutton> <http://www.linkedin.com/shareArticle?mini=true&url=https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore> <http://www.facebook.com/share.php?u=https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore> [mailto:?subject=Check%20out%20https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore](mailto:?subject=Check%20out%20https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore)

February 3, 2022

# How to Build a Log4Shell Detector with ProGuardCORE

Written by: James Hamilton - Software Engineer

![](https://23593082.hs-sites.com/hubfs/Imported_Blog_Media/How-to-Build-a-Log4Shell-Detector-with-ProGuardCORE-2.jpg)

Log4Shell ([CVE-2021-44228](https://cve.org/CVERecord?id=CVE-2021-44228)) is a zero-day vulnerability in [Log4J](https://logging.apache.org/log4j/2.x/), a popular open-source Java logging framework used by many organizations around the world. Though the vulnerability has been patched, and upgrading to a newer Log4J version solves the problem, not everyone has completed the necessary upgrade.

A simple technique to detect the Log4Shell vulnerability is to find something unique in the vulnerable versions that is not in the patched version. That’s exactly the approach used by [this Yara rule](https://github.com/darkarnium/Log4j-CVE-Detect/blob/main/rules/vulnerability/log4j/CVE-2021-44228.yar) which detects [a particular constructor](https://github.com/apache/logging-log4j2/blob/rel/2.14.1/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java#L42) that only appears in the vulnerable versions.

In this blog post, we will show you how to build a Log4Shell detector using [ProGuardCORE](https://github.com/Guardsquare/proguard-core) to determine if applications are using an older Log4J version that is susceptible to the vulnerability.

## Using ProGuardCORE to Detect Log4Shell

[ProGuardCORE](https://github.com/Guardsquare/proguard-core) is a library to parse, modify and analyze Java class files upon which the well-known shrinker, optimizer, and obfuscator [ProGuard](https://github.com/Guardsquare/proguard), and the compatible Android security solution [DexGuard](https://23593082.hs-sites.com/dexguard), are built.

Using the ProGuardCORE toolbox, we can easily:

- Read Java class files and extract classes from Jar files
- Filter those classes for a specific class
- Filter that specific class for a specific constructor

We’ll concentrate the discussion on the last two points: these implement the actual detection logic. The [input reading code](https://github.com/Guardsquare/log4shell-detector/blob/7a85f43774f21eccbdaaea3fde568c12eb417655/src/main/kotlin/eu/jameshamilton/log4shell/Main.kt#L94) will return a[`ClassPool`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/ClassPool.html)instance containing a collection of[`ProgramClass`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/ProgramClass.html)instances given an input file or directory, which we can use to look for the constructor.

### Applying actions on a specific class

ProGuardCORE uses the [visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern) to interact with the model classes and provides many useful built-in visitors which allow traversing and filtering.

The class we are interested in finding is`org.apache.logging.log4j.core.net.JndiManager`. To apply a visitor to this class, we can call the`classesAccept`method on the program class pool with the class name as the first parameter (note that ProGuardCORE uses internal naming with`/`instead of`.`):

```
programClassPool.classesAccept(
  "org/apache/logging/log4j/core/net/JndiManager",
  classVisitor
)
```

`classVisitor`in this snippet is an instance of [`ClassVisitor`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/visitor/ClassVisitor.html): it can be implemented by combining some of ProGuardCORE’s built-in visitors to delegate to a [`MemberVisitor`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/visitor/MemberVisitor.html)that can be applied to the constructor we’re interested in.

### Applying actions on a specific member

The`JndiManager` constructor we’re looking for has the following signature:

```
private <init>(Ljava/lang/String;Ljavax/naming/Context;)V
```

There are a few built-in ProGuardCORE visitors we can use to visit a specific constructor of a class:

- `AllMemberVisitor`: a`ClassVisitor`that applies a`MemberVisitor`to all members (methods and fields) of a class.
- [`MethodFilter`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/visitor/MethodFilter.html): a`MemberVisitor`that delegates to another`MemberVisitor`if the member is a method (i.e. not a field).
- `ConstructorMethodFilter`: a`MemberVisitor` that delegates to another`MemberVisitor`if the method is a constructor.
- [`MemberAccessFilter`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/visitor/MemberAccessFilter.html): a`MemberVisitor` that delegates to another`MemberVisitor`if the access flags match those given.
- [`MemberDescriptorFilter`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/visitor/MemberDescriptorFilter.html): a`MemberVisitor`that delegates to another`MemberVisitor`if the member descriptor matches the given descriptor.

Putting these together, we can construct a`ClassVisitor`that delegates to a`MemberVisitor`if the member matches the specific`JndiManager`constructor signature:

```
val classVisitor = AllMemberVisitor(
    MethodFilter(
        ConstructorMethodFilter(
            MemberAccessFilter(
                /* requiredSetAccessFlags = */ PRIVATE, 
                /* requiredUnsetAccessFlags = */ 0,
                MemberDescriptorFilter(
                    "(Ljava/lang/String;Ljavax/naming/Context;)V",
                     memberVisitor
                )
            )
        )
    )
)
```

## Counting visits to members

The main logic of our Log4Shell detector involves finding a specific`JndiManager`constructor. Now that we’ve constructed a`ClassVisitor`that will delegate to a`MemberVisitor`if this constructor is found - the implementation of that`MemberVisitor`should be as simple as knowing whether or not it was applied to any member of the visited class.

 ProGuardCORE contains a built-in `MemberVisitor`that can be used for this purpose:

- [`MemberCounter`](https://guardsquare.github.io/proguard-core/api/proguard/classfile/visitor/MemberCounter.html): a`MemberVisitor`that counts the number of class members that have been visited.

Using this, we can create the`memberVisitor`to be used with our`classVisitor`from the previous section:

```
val memberVisitor = MemberCounter()
val classVisitor = AllMemberVisitor(
    MethodFilter(
        ConstructorMethodFilter(
            MemberAccessFilter(
                /* requiredSetAccessFlags = */ PRIVATE,
                /* requiredUnsetAccessFlags = */ 0,
                MemberDescriptorFilter(
                    "(Ljava/lang/String;Ljavax/naming/Context;)V",
                     memberVisitor
                )
            )
        )
    )
)
```

After the`classVisitor`is applied to the program class pool we can check how many times the`memberVisitor`was applied. It should be once if this is an application using a vulnerable Log4J version.

```
programClassPool.classesAccept(
  "org/apache/logging/log4j/core/net/JndiManager",
  classVisitor
)
println(memberVisitor.count) // prints 1 if vulnerable to Log4Shell
```

## Putting it all together

Putting all this together, we can construct [a function](https://github.com/Guardsquare/log4shell-detector/blob/7a85f43774f21eccbdaaea3fde568c12eb417655/src/main/kotlin/eu/jameshamilton/log4shell/Main.kt#L53) that takes a`ClassPool`of a given application as a parameter and returns`true`or`false`based on whether or not the application is vulnerable to Log4Shell.

 There are some improvements we can make, as well:

- The class and member filters in ProGuardCORE accept wildcards. This allows us to take into account [shadow packing](https://github.com/johnrengelman/shadow) by prefixing the class name with a wildcard that matches any package: `**org/apache/logging/log4j/core/net/JndiManager`
- A [workaround for protecting against Log4Shell](https://www.kb.cert.org/vuls/id/930724#workarounds) is to remove the class  
  `org/apache/logging/log4j/core/lookup/JndiLookup`so we can first check if this class exists before we check if the`JndiManage` constructor exists.

```
fun check(programClassPool: ClassPool): Boolean {
    val jndiLookupCounter = ClassCounter()
    val jndiManagerOldConstructorCounter = MemberCounter()

    programClassPool.classesAccept(
      "**org/apache/logging/log4j/core/lookup/JndiLookup",
      jndiLookupCounter)

    if (jndiLookupCounter.count == 0) return false

    programClassPool.classesAccept(
        "**org/apache/logging/log4j/core/net/JndiManager",
        AllMemberVisitor(
            MethodFilter(
                ConstructorMethodFilter(
                    MemberAccessFilter(
                        /* requiredSetAccessFlags = */ PRIVATE,
                        /* requiredUnsetAccessFlags = */ 0,
                        MemberDescriptorFilter(
                            "(Ljava/lang/String;Ljavax/naming/Context;)V",
                            jndiManagerOldConstructorCounter
                        )
                    )
                )
            )
        )
    )

    return jndiManagerOldConstructorCounter.count > 0
}
```

## Conclusion

We’ve shown how [ProGuardCORE ](https://github.com/Guardsquare/proguard-core) provides a toolbox to easily implement a [Log4Shell detector](https://github.com/Guardsquare/log4shell-detector) based on pattern matching classes and members. ProGuardCORE provides even more features not demonstrated here such as [partial evaluation](https://guardsquare.github.io/proguard-core/analyzing.html#partial-evaluation), [Kotlin metadata support](https://guardsquare.github.io/proguard-core/kotlin.html), and [powerful instruction sequence matching and replacement](https://guardsquare.github.io/proguard-core/patternmatching.html).

These powerful features are used at Guardsquare to build software, including [ProGuard](https://github.com/Guardsquare/proguard), the [Kotlin metadata printer](https://github.com/Guardsquare/kotlin-metadata-printer) used in [ProGuard Playground](https://playground.proguard.com/), and the Android security solution [DexGuard](https://23593082.hs-sites.com/dexguard).

Tag(s): [Android](https://23593082.hs-sites.com/amilia-test/tag/android) , [Technical](https://23593082.hs-sites.com/amilia-test/tag/technical) , [ProGuard & R8](https://23593082.hs-sites.com/amilia-test/tag/proguard-r8) , [DexGuard](https://23593082.hs-sites.com/amilia-test/tag/dexguard)

## [James Hamilton - Software Engineer](https://23593082.hs-sites.com/amilia-test/author/james-hamilton-software-engineer)

Connect with the author

## Discover how Guardsquare provides industry-leading protection for mobile apps.

## Other posts you might be interested in

[

** 11 min read  | August 22, 2023

## Webinar Recap: Accessibility Features and Overlays on Android

Android Protection Security Research 

](https://23593082.hs-sites.com/amilia-test/blog/app-permissions-abuse) [

** 7 min read  | August 15, 2023

## What is RASP and Why It Matters to Mobile App Developers

Android iOS Protection DexGuard iXGuard 

](https://23593082.hs-sites.com/amilia-test/blog/rasp-dynamic-analysis)

## Subscribe to our newsletter

Stay in the know with monthly updates right to your inbox.

![HubSpot CMS](https://cdn2.hubspot.net/hubfs/302335/hubspot-cms-logo-gray.svg "HubSpot CMS")

[General Terms](https://23593082.hs-sites.com/terms-of-use) | [Privacy Policy](https://23593082.hs-sites.com/privacy-policy) | [Cookie Policy](https://23593082.hs-sites.com/cookie-policy)

Tervuursevest 362 bus 1, 3000 Leuven, Belgium | VAT: BE0550675829 |

© 2016-2026 Guardsquare nv. All rights reserved.

<https://www.facebook.com/guardsquare> <https://twitter.com/Guardsquare> <https://www.linkedin.com/company/guardsquare/> <https://www.youtube.com/channel/UCP9s5F1ksT1E-7vSF2CDyhw> <https://github.com/Guardsquare>

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "James Hamilton - Software Engineer",
    "url" : "https://23593082.hs-sites.com/amilia-test/author/james-hamilton-software-engineer"
  },
  "dateModified" : "2023-09-19T17:46:46.752Z",
  "datePublished" : "2022-02-03T05:00:00.000Z",
  "headline" : "How to Build a Log4Shell Detector with ProGuardCORE | Guardsquare",
  "image" : [ "https://23593082.hs-sites.com/hubfs/Imported_Blog_Media/How-to-Build-a-Log4Shell-Detector-with-ProGuardCORE-2.jpg" ],
  "mainEntityOfPage" : {
    "@id" : "https://23593082.hs-sites.com/amilia-test/blog/how-to-build-a-log4shell-detector-with-proguardcore",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject"
    }
  }
}
```