Skip to content

feat: Phase 5 dynamic string resolution via DexTrace#919

Draft
haeter525 wants to merge 2 commits into
ev-flow:masterfrom
haeter525:feat/phase5-dynamic-resolution
Draft

feat: Phase 5 dynamic string resolution via DexTrace#919
haeter525 wants to merge 2 commits into
ev-flow:masterfrom
haeter525:feat/phase5-dynamic-resolution

Conversation

@haeter525
Copy link
Copy Markdown
Member

@haeter525 haeter525 commented May 17, 2026

Add DexTrace-based dynamic string resolution to resolve encrypted strings for Phase 5 keyword matching. The false negative on bianlian APK (80% → 100% confidence) is the motivating case.

⚠️ Merge dependency:
This PR cannot be merged until the following tasks are completed:

How to Test

1. Install DexTrace (development install)

git clone https://github.com/haeter525/DexTrace.git
cd DexTrace
git checkout feat/droidkungfu-stubs
pip install -e .

2. Install quark-engine with this branch

git clone git@github.com:haeter525/quark-engine.git
cd quark-engine
git checkout feat/phase5-dynamic-resolution
pip install -e .

3. Download the sample APK

Download bianlian.zip (Password: infected) and extract bianlian.apk.

4. Save the detection rule

Save the following as auto_click_comfirm_button_on_dialog.json:

{
    "crime": "Auto click button on system dialog",
    "permission": [],
    "api": [
        {
            "class": "Landroid/view/accessibility/AccessibilityNodeInfo;",
            "method": "findAccessibilityNodeInfosByText",
            "descriptor": "(Ljava/lang/String;)Ljava/util/List;",
            "match_keywords": [
                "android:id/button1"
            ]
        },
        {
            "class": "Landroid/view/accessibility/AccessibilityNodeInfo;",
            "method": "performAction",
            "descriptor": "(I)Z"
        }
    ],
    "score": 10,
    "label": ["sms", "calllog", "collection"]
}

5. Run — compare static vs dynamic

The sample first calls the method dilemmaexact() to compute a string, then takes it as the 2nd argument to call the findButtonAndClick method:

截圖 2026-05-20 21 08 40

The method then calls the first API findAccessibilityNodeInfosByText with this string to locate a button on the system dialog:

截圖 2026-05-20 21 09 29
Quark Analysis Without --dynamic-resolve (static only)
quark -a bianlian.apk -s auto_click_comfirm_button_on_dialog.json
截圖 2026-05-17 16 28 35

Since the string is dynamically computed, the Quark rule above cannot fully detect this behavior, resulting in an 80% confidence score.

Quark Analysis With --dynamic-resolve
quark -a bianlian.apk -s auto_click_comfirm_button_on_dialog.json --dynamic-resolve
截圖 2026-05-17 16 26 53

With the dynamic string resolution feature, Quark successfully resolves the string from the dilemmaexact() method and identifies the target behavior with 100% confidence.

Adds opt-in dynamic_resolve=False parameter to Quark.__init__ that uses
DexTrace to execute encrypted string methods at analysis time, recovering
plaintext for Phase 5 keyword matching.

Core changes:
- _resolveStringCalls: two-phase resolver — (1) prior calls of methodCall,
  (2) PyEval-scan of parentMethod's callers for String-returning calls when
  the encryption function lives in a higher frame
- _dextrace_cached: LRU-cached per (apk_path, sig) to avoid re-executing
  the same method across multiple keyword checks
- getMatchedKeywords: fixed Primitive('') guard, accepts parentMethod,
  delegates to DexTrace only when no meaningful static primitives found
- checkParameterOnSingleMethod / check_parameter: thread parentMethod down
- CLI: --dynamic-resolve flag; setup.py: extras_require["dynamic"]

Verified: bianlian.apk auto_click_comfirm_button_on_dialog.json
  static  → 80%  (Phase 5 FN: dilemmaexact() string not resolved)
  dynamic → 100% (Phase 5 passes after DexTrace executes dilemmaexact())

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@haeter525 haeter525 marked this pull request as draft May 17, 2026 07:34
@codecov
Copy link
Copy Markdown

codecov Bot commented May 17, 2026

Codecov Report

❌ Patch coverage is 80.82192% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.40%. Comparing base (9fb4362) to head (5f8b8d8).
⚠️ Report is 19 commits behind head on master.

Files with missing lines Patch % Lines
quark/core/quark.py 83.09% 12 Missing ⚠️
quark/cli.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #919      +/-   ##
==========================================
+ Coverage   81.31%   81.40%   +0.09%     
==========================================
  Files          80       80              
  Lines        6946     6969      +23     
==========================================
+ Hits         5648     5673      +25     
+ Misses       1298     1296       -2     
Flag Coverage Δ
unittests 81.40% <80.82%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@haeter525 haeter525 requested a review from pulorsok May 26, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant