MCPcopy Index your code
hub / github.com/CalebFenton/apkfile

github.com/CalebFenton/apkfile @v1.0.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.0.1 ↗ · + Follow
669 symbols 1,323 edges 62 files 151 documented · 23% updated 5y agov1.0.1 · 2017-12-12★ 2271 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

apkfile

ApkFile is a library which creates a representation of an APK composed of Java objects which can be easily inspected for analysis or serialized into JSON. The goal of the library is to provide a robust way to inspect hostile malware samples, but it's general purpose enough to be used for other stuff too.

Usage

The main object is ApkFile and it extends java.io.File:

ApkFile apkFile = new ApkFile('ApiDemos.apk');
AndroidManifest androidManifest = apkFile.getAndroidManifest();
String packageName = androidManifest.getPackageName(); // com.example.android.apis

ApkFile provides objects for:

  • Android manifest
  • Resources via modified & hardened ArscBlamer
  • Signing certificate
  • DEX files via dexlib2
  • JAR (ZIP) entries

Serializing to JSON

Below is an example of how to stream an ApkFile to JSON:

ApkFile apkFile = new ApkFile("ignore/DroidSwarm-1.0.1.apk");
GsonBuilder gsonBuilder = new GsonBuilder();

// Use these settings to handle odd strings and floating point values like "NaN":
Gson gson = new GsonBuilder().disableHtmlEscaping().serializeSpecialFloatingPointValues().setPrettyPrinting().create();

// Don't just create a JSON string since it's huge. Instead, stream it out.
Writer writer = new OutputStreamWriter(System.out);
gson.toJson(apkFile, writer);
writer.close();
apkFile.close();

Below is the highly abbreviated output from the code above. A full version can be found here.

```json { "androidManifest": { "application": { "activities": [ { "allowEmbedded": false, "allowTaskReparenting": false, "alwaysRetainTaskState": false, "autoRemoveFromRecents": false, "banner": "", "clearTaskOnLaunch": false, "configChanges": 0, "documentLaunchMode": 0, "excludeFromRecents": false, "finishOnTaskLaunch": false, "hardwareAccelerated": false, "launchMode": 0, "maxRecents": 16, "multiprocess": false, "noHistory": false, "parentActivityName": "", "persistableMode": 0, "relinquishTaskIdentity": false, "resizeableActivity": false, "screenOrientation": 0, "showForAllUsers": false, "stateNotNeeded": false, "supportsPictureInPicture": false, "taskAffinity": "", "theme": "", "uiOptions": 0, "windowSoftInputMode": 0, "intentFilters": [ { "actions": [ "android.intent.action.MAIN" ], "categories": [ "android.intent.category.LAUNCHER" ], "data": [], "icon": "", "label": "", "priority": 0 } ], "metaData": [], "directBootAware": false, "enabled": true, "exported": false, "icon": "", "label": "DroidSwarm", "name": "com.soong.droidswarm.Main", "permission": "", "process": "" }, // ** SNIP ** ], "activityAliases": [], "allowTaskReparenting": false, "allowBackup": true, "backupAgent": "", "backupInForeground": false, "banner": "", "debuggable": true, "description": "", "directBootAware": false, "enabled": true, "extractNativeLibs": true, "fullBackupContent": "", "fullBackupOnly": false, "hardwareAccelerated": true, "hasCode": true, "icon": "res/drawable-mdpi/ic_launcher.png", "isGame": false, "killAfterRestore": true, "largeHeap": false, "label": "DroidSwarm", "logo": "", "manageSpaceActivity": "", "name": "", "networkSecurityConfig": "", "permission": "", "persistent": false, "process": "", "providers": [], "receivers": [], "restoreAnyVersion": false, "requiredAccountType": "", "resizableActivity": false, "supportsRtl": false, "services": [ { "isolatedProcess": false, "intentFilters": [], "metaData": [], "directBootAware": false, "enabled": true, "exported": false, "icon": "", "label": "", "name": "com.soong.droidswarm.SwarmService", "permission": "", "process": "" } ], "taskAffinity": "", "theme": "", "uiOptions": 0, "usesCleartextTraffic": true, "vmSafeMode": false, "usesLibraries": [] }, "compatibleScreens": [], "hasResources": true, "installLocation": 0, "instrumentations": [], "maxSdkVersion": 0, "minSdkVersion": 7, "packageName": "com.soong.droidswarm", "permissionGroups": [], "permissionTrees": [], "permissions": [], "platformBuildVersionCode": -1, "platformBuildVersionName": "", "sharedUserId": "", "sharedUserLabel": "", "supportsGlTextures": [], "targetSdkVersion": 0, "usesConfigurations": [], "usesFeatures": [], "usesPermissions": [ "android.permission.INTERNET", "android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.ACCESS_NETWORK_STATE", "android.permission.CHANGE_WIFI_STATE" ], "versionCode": 5, "versionName": "0.9.2" }, "certificate": { "allRdns": [ { "issuerRdns": { "C": "US", "CN": "Android Debug", "O": "Android" }, "subjectRdns": { "C": "US", "CN": "Android Debug", "O": "Android" } } ] }, "entryNameToDex": { "classes.dex": { "apiCounts": { "Landroid/text/Editable;->toString()Ljava/lang/String;": 8, "Ljava/util/concurrent/ThreadPoolExecutor;->(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/RejectedExecutionHandler;)V": 1, "Landroid/content/pm/PackageManager;->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;": 2, "Ljava/lang/Object;->toString()Ljava/lang/String;": 1, "Ljava/lang/Long;->valueOf(J)Ljava/lang/Long;": 2, "Landroid/widget/CheckBox;->isChecked()Z": 1, "Landroid/widget/ListView;->setAdapter(Landroid/widget/ListAdapter;)V": 2, "Ljava/lang/CharSequence;->toString()Ljava/lang/String;": 1, "Ljava/util/Iterator;->hasNext()Z": 9, "Ljava/lang/String;->toLowerCase()Ljava/lang/String;": 1, "Landroid/widget/SeekBar;->getMax()I": 1, "Landroid/app/AlertDialog;->setMessage(Ljava/lang/CharSequence;)V": 1, // ** SNIP ** }, "classAccessorCounts": { "interface": 2, "final": 7, "protected": 0, "private": 0, "synchronized": 0, "abstract": 2, "native": 0, "volatile": 0, "transient": 0, "public": 22, "static": 0, "strict": 0 }, "classPathToClass": { // * SNIP ** "Lcom/soong/droidswarm/SwarmMonitor;": { "apiCounts": { "Ljava/lang/Thread;->sleep(J)V": 1, "Ljava/lang/Long;->valueOf(J)Ljava/lang/Long;": 2, "Ljava/io/PrintStream;->println(Ljava/lang/String;)V": 1, "Ljava/util/ArrayList;->get(I)Ljava/lang/Object;": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->getMaximumPoolSize()I": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->execute(Ljava/lang/Runnable;)V": 1, "Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;": 5, "Ljava/util/concurrent/ThreadPoolExecutor;->getActiveCount()I": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->getTaskCount()J": 1, "Ljava/lang/Object;->()V": 1, "Ljava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->getPoolSize()I": 2, "Ljava/util/concurrent/ThreadPoolExecutor;->isShutdown()Z": 3, "Ljava/util/concurrent/ThreadPoolExecutor;->getCorePoolSize()I": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->getCompletedTaskCount()J": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->isTerminated()Z": 1 }, "classAccessors": { "interface": 0, "final": 0, "protected": 0, "private": 0, "synchronized": 0, "abstract": 0, "native": 0, "volatile": 0, "transient": 0, "public": 1, "static": 0, "strict": 0 }, "fieldReferenceCounts": { "Ljava/lang/System;->out:Ljava/io/PrintStream;": 1 }, "methodAccessorCounts": { "interface": 0, "final": 0, "protected": 0, "private": 0, "synchronized": 0, "abstract": 0, "native": 0, "volatile": 0, "transient": 0, "public": 2, "static": 0, "strict": 0 }, "methodSignatureToMethod": { "run()V": { "apiCounts": { "Ljava/util/concurrent/ThreadPoolExecutor;->getActiveCount()I": 1, "Ljava/lang/Thread;->sleep(J)V": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->execute(Ljava/lang/Runnable;)V": 1, "Ljava/lang/Long;->valueOf(J)Ljava/lang/Long;": 2, "Ljava/util/concurrent/ThreadPoolExecutor;->getCompletedTaskCount()J": 1, "Ljava/util/ArrayList;->get(I)Ljava/lang/Object;": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->getMaximumPoolSize()I": 1, "Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;": 5, "Ljava/util/concurrent/ThreadPoolExecutor;->getTaskCount()J": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->isTerminated()Z": 1, "Ljava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->getPoolSize()I": 2, "Ljava/util/concurrent/ThreadPoolExecutor;->getCorePoolSize()I": 1, "Ljava/io/PrintStream;->println(Ljava/lang/String;)V": 1, "Ljava/util/concurrent/ThreadPoolExecutor;->isShutdown()Z": 3 }, "fieldReferenceCounts": { "Ljava/lang/System;->out:Ljava/io/PrintStream;": 1 }, "methodAccessors": { "interface": 0, "final": 0, "protected": 0, "private": 0, "synchronized": 0, "abstract": 0, "native": 0, "volatile": 0, "transient": 0, "public": 1, "static": 0, "strict": 0 }, "opCounts": { "MOVE_RESULT": 12, "IF_NEZ": 1, "ADD_INT_LIT8": 1, "IF_GE": 1, "IF_LEZ": 1, "MOVE_EXCEPTION": 1, "SGET_OBJECT": 1, "MOVE_RESULT_WIDE": 2, "REM_INT": 1, "GOTO": 4, "IF_EQZ": 5, "CHECK_CAST": 1, "CONST_STRING": 1, "NEW_ARRAY": 1, "INVOKE_DIRECT": 1, "IF_LE": 1, "MOVE_RESULT_OBJECT": 9, "INVOKE_STATIC": 9, "IGET_OBJECT": 17, "IGET_BOOLEAN": 2, "RETURN_VOID": 1, "APUT_OBJECT": 7, "INVOKE_VIRTUAL": 17, "NEW_INSTANCE": 1, "MOVE": 4, "CONST_4": 12, "CONST_WIDE_16": 1 }, "stringReferenceCounts": { "[swarm-mon] [%d/%d] active:%d, completed:%d task:%d isShutdown:%s isTerminated:%s": 1 }, "annotationCount": 0, "cyclomaticComplexity": 19, "debugItemCount": 31, "instructionCount": 115, "registerCount": 11, "tryCatchCount": 1 }, "(Ljava/util/concurrent/ThreadPoolExecutor;Lcom/soong/droidswarm/TargetList;)V": { "apiCounts": { "Ljava/lang/Object;->()V": 1 }, "fieldReferenceCounts": {}, "methodAccessors": { "interface": 0, "final": 0, "protected": 0, "private": 0, "synchronized": 0, "abstract": 0, "native": 0, "volatile": 0, "transient": 0, "public": 1, "static": 0, "strict": 0 }, "opCounts": { "RETURN_VOID": 1, "INVOKE_DIRECT": 1, "CONST_4": 1, "IPUT_BOOLEAN": 1, "IPUT_OBJECT": 2 }, "stringReferenceCounts": {}, "annotationCount": 0, "cyclomaticComplexity": 1, "debugItemCount": 6, "instructionCount": 6, "registerCount": 4, "tryCatchCount": 0 } }, "opCounts": { "MOVE_RESULT": 12, "IF_NEZ": 1, "ADD_INT_LIT8": 1, "IF_GE": 1, "IF_LEZ": 1, "MOVE_EXCEPTION": 1, "SGET_OBJECT": 1, "MOVE_RESULT_WIDE": 2, "REM_INT": 1,

Extension points exported contracts — how you extend this code

SerializableResource (Interface)
A resource, typically a @{link Chunk}, that can be converted to an array of bytes. [17 implementers]
src/main/java/org/cf/apkfile/res/SerializableResource.java

Core symbols most depended-on inside this repo

getAttribute
called by 150
src/main/java/org/cf/apkfile/res/XmlStartElementChunk.java
equals
called by 36
src/main/java/org/cf/apkfile/dex/ShortMethodReference.java
size
called by 25
src/main/java/org/cf/apkfile/res/TypeChunk.java
values
called by 24
src/main/java/org/cf/apkfile/res/TypeChunk.java
toByteArray
called by 19
src/main/java/org/cf/apkfile/res/SerializableResource.java
getHeaderSize
called by 15
src/main/java/org/cf/apkfile/res/Chunk.java
data
called by 14
src/main/java/org/cf/apkfile/res/ResourceValue.java
getOrDefault
called by 13
src/main/java/org/cf/apkfile/res/ResourceConfiguration.java

Shape

Method 598
Class 65
Enum 5
Interface 1

Languages

Java100%

Modules by API surface

src/main/java/org/cf/apkfile/res/ResourceConfiguration.java46 symbols
src/main/java/org/cf/apkfile/manifest/Application.java42 symbols
src/main/java/org/cf/apkfile/res/TypeChunk.java37 symbols
src/main/java/org/cf/apkfile/res/StringPoolChunk.java32 symbols
src/main/java/org/cf/apkfile/manifest/AndroidManifest.java30 symbols
src/main/java/org/cf/apkfile/manifest/Activity.java29 symbols
src/main/java/org/cf/apkfile/dex/DexFile.java24 symbols
src/main/java/org/cf/apkfile/ApkFile.java24 symbols
src/main/java/org/cf/apkfile/dex/DexClass.java21 symbols
src/main/java/org/cf/apkfile/res/Chunk.java19 symbols
src/main/java/org/cf/apkfile/dex/DexMethod.java18 symbols
src/main/java/org/cf/apkfile/res/XmlStartElementChunk.java15 symbols

For agents

$ claude mcp add apkfile \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page