Reverse Engineering a Product Recommendation API in the Dewu Mobile Application

Today's Objective

  • Collect product recommendation data from the Dewu app home screen
  • Target application version: 4.74.5

Bypassing Forced Updates

# -*- coding: utf-8 -*-
'''
@IDE : PyCharm
@version : 3.9
@Auth : Security Researcher
@time : 2024/2/25 8:01
@Description: Bypass update dialog in Dewu app
'''
import frida
import sys

rdev = frida.get_remote_device()
pid = rdev.spawn(["com.shizhuang.duapp"])
session = rdev.attach(pid)

scr = """
Java.perform(function () {
    var AlertDialog = Java.use('androidx.appcompat.app.AlertDialog');
    AlertDialog.show.implementation = function(){
        console.log("Update dialog intercepted");
        // Commenting out the actual call to bypass
        //this.show();
    }
});
"""
script = session.create_script(scr)

def on_message(message, data):
    print(message, data)

script.on("message", on_message)
script.load()
rdev.resume(pid)
sys.stdin.read()

Network Traffic Analysis

The application implements client-side proxy detection, requiring the use of SocksDroid for traffic capture. Before beginning, ensure all previous proxy configurations have been removed from your device.

API Analysis

  • Endpoint: https://app.dewu.com/sns-rec/v1/recommend/all/feed
  • Method: GET
  • Headers: Only X-Auth-Token is required (can be removed from testing)
  • User-Agent: duapp/4.74.5(android;11)
    X-Auth-Token: # Required parameter
  • Parameters:
    • lastId (empty for first page, or 1 for pagination)
    • limit (number of items per page, default 20)
    • newSign (encrypted signature, must be cracked for full functionality)
    • Optional parameters:
      • abType: social_brand_strategy_v454
      • abValue: 1
      • deliveryProjectId: 0
      • abVideoCover: 2
      • abRectagFengge: 0
      • abRecReason: 0

Reverse Engineering Targets

  • newSign generation
  • X-Auth-Token handling

Cracking newSign Generation

3.1 Application Decompilation

  • Drag the Dewu app to JADX for decompilation
  • Search for "newSign" in the codebase
  • Identify addQueryParameter as the likely method responsible
  • Analyze the code: host.addQueryParameter("newSign", RequestUtils.c(hashMap2, currentTimeMillis))
  • Confirm RequestUtils.c is called with two parameters
  • Create a hook script to verify this method is being called

3.2 Hooking RequestUtils.c Method

# -*- coding: utf-8 -*-
'''
@IDE : PyCharm
@version : 3.9
@Auth : Security Researcher
@time : 2024/2/25 10:01
@Description: Hook RequestUtils.c method to analyze signature generation
'''
import frida
import sys
# Connect to mobile device
rdev = frida.get_remote_device()
session = rdev.attach("com.shizhuang.duapp")

scr = """
Java.perform(function () {
    // Package.Class
    var RequestUtils = Java.use("com.shizhuang.duapp.common.utils.RequestUtils");
    // Hook and replace
    RequestUtils.c.implementation = function(map, timestamp){
        console.log('--------------------------------')
        // Execute original method
        console.log('1. Parameter map:', map);
        console.log('2. Parameter type:', JSON.stringify(map));
        // Standard conversion format
        var HashMap = Java.use('java.util.HashMap');
        var obj = Java.cast(map, HashMap);
        console.log('3. Converted map string:', obj.toString());
        console.log("Input timestamp:", timestamp);
        var result =  this.c(map, timestamp)
        console.log("Generated signature:", result);
        return result;
    }
});
"""

script = session.create_script(scr)
def on_message(message, data):
    print(message, data)

script.on("message", on_message)
script.load()
sys.stdin.read()

3.3 Analyzing RequestUtils.c Implementation

The Java source code reveals a five-step process:

public static synchronized String c(Map<String, String> map, long j2) throws UnsupportedEncodingException {
    synchronized (RequestUtils.class) {
        PatchProxyResult proxy = PatchProxy.proxy(new Object[]{map, new Long(j2)}, null, changeQuickRedirect, true, 6612, new Class[]{Map.class, Long.TYPE}, String.class);
        if (proxy.isSupported) {
            return (String) proxy.result;
        } else if (map == null) {
            return "";
        } else {
            // 1. Add multiple key-value pairs to the map
            map.put("uuid", DuHttpConfig.d.getUUID());
            map.put("platform", "android");
            map.put("v", DuHttpConfig.d.getAppVersion());
            map.put("loginToken", DuHttpConfig.d.getLoginToken());
            map.put("timestamp", String.valueOf(j2));
            // 2. Convert the map to an ArrayList for sorting
            ArrayList arrayList = new ArrayList(map.entrySet());

Tags: reverse engineering API analysis mobile security Frida Android

Posted on Fri, 08 May 2026 11:17:44 +0000 by axo