Mobile Development 10 min read

Detecting Android Privacy Calls in .so Files and Building a Static Call Graph

This article explains how to statically analyze Android apps to identify privacy‑related method calls hidden in native .so libraries, extract method signatures from smali files, construct a call‑graph with callers and callees, handle cycles, and traverse the graph to reveal call chains.

NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
Detecting Android Privacy Calls in .so Files and Building a Static Call Graph

Introduction

The author previously shared a partial implementation for static privacy compliance checks on Android apps. The earlier approach decompiled APKs to scan Java method calls but missed calls hidden in native .so libraries and could not pinpoint the exact entry points of detected calls.

Scanning Native Libraries

Privacy‑related methods may be invoked via JNI reflection, which leaves no trace in Java code. To address this, the article proposes examining the string constants inside .so files. In Linux, strings are stored in the .text (code) segment or the .rodata (read‑only data) segment.

Running the strings command on each .so file extracts all embedded strings: strings xx.so By matching extracted strings against a list of privacy‑method names, any .so containing a potential call is flagged as suspicious. The workflow is illustrated with diagrams (omitted for brevity).

Method Collection from Smali

After decompiling the APK, the generated smali files contain class and method definitions. Each class starts with a .class directive, and methods are declared with the .method directive. For example, the Retrofit.smali file shows constructors, private methods, and public methods with their signatures.

To uniquely identify a method, the following fields are recorded:

Fully qualified class name (package + class)

Method name

Parameter list

Method descriptors follow JVM conventions (e.g., V for void, Z for boolean, Landroid/content/Context; for object types).

Establishing Method Relationships

Smali uses invoke- instructions to call other methods. The article lists the five variants:

invoke-direct
invoke-static
invoke-virtual
invoke-super
invoke-interface

Except for invoke-interface, the target method can be determined directly from the instruction, which has the form:

invoke-virtual {v2, p2, v1}, Ljava/util/HashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;

Parsing these instructions yields the callee’s full class and method name. During a full‑app scan, each method stores two lists:

calleds : methods that this method invokes

callers : methods that invoke this method

The resulting structure is a multi‑branch tree (or a bidirectional graph when both lists are kept), enabling upward or downward traversal of call chains.

Traversing Call Chains

Depth‑first search (DFS) is used to enumerate all possible call paths. The algorithm must detect cycles: if a method appears twice in the current path, the recursion stops for that branch, and the path is recorded as a cycle.

fun traversal(method) {
    val paths = []
    dfs(method, [], paths)
}

fun dfs(method, path, temp) {
    if (method.calleds.isNotEmpty) {
        for (called in method.calleds) {
            if (path.contains(called)) {
                temp.add(path)
                continue
            } else {
                val newPath = []
                newPath.addAll(path)
                newPath.add(0, method)
                dfs(called.method, newPath, temp)
            }
        }
    } else {
        path.add(0, method)
        temp.add(path)
    }
}

The final output visualizes the call chains, highlighting privacy‑related leaf nodes.

Conclusion

The static analysis approach described covers both Java‑level and native‑level privacy method detection, builds a comprehensive call graph, and provides a way to trace the origin of sensitive calls. While static checks are valuable, they complement runtime monitoring for a more robust compliance solution.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Androidreverse engineeringstatic analysisSmaliSO Filesprivacy complianceMethod Call Graph
NetEase Cloud Music Tech Team
Written by

NetEase Cloud Music Tech Team

Official account of NetEase Cloud Music Tech Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.