app逆向练手系列

1.回音 360加固

import hashlib
import time
import uuid
import requests
from urllib.parse import quote_plus

def get_sign(params):
    concat_params = "&".join(f"{key}={quote_plus(str(params[key]), safe='')}" for key in sorted(params))
    if len(concat_params) > 10:
        salt = "meXlhxAm9Lh17V76g5gQZ4C3ELVZgjAg"
    elif len(concat_params) >= 6:
        salt = "2S1rybDLpQv4F6jM9zCNJ0Fq436ZfnJ5"
    else:
        salt = "sdlfkl345sdfewrs"
    cipher_text = f"{concat_params}|{salt}"
    first = hashlib.md5(cipher_text.encode("utf-8")).hexdigest()
    if len(concat_params) > 10:
        return hashlib.md5((cipher_text + first).encode("utf-8")).hexdigest()
    return first
url = "https://api.xinyuhole.com/api/dynamic/getPlazaHomePage"

params = {
    'appkey': "3ak70bq5z9v6f50cj197",
    'category': "2",
    'deviceDate': int(time.time() * 1000),
    'deviceID': "ecd31af825cd749619661be2683ba0e3",
    'pg': "0",
    'requestId': uuid.uuid4().hex, # 不校验随便写
    'size': "10",
    'userId': "10734230",
    'userToken': "",
}

# params['requestId'] = hashlib.md5(
#     (str(uuid.uuid4()) + params['deviceDate']).encode('utf-8')
# ).hexdigest()

params['sign'] = get_sign(params)

headers = {
    'User-Agent': "{\"appName\":\"HeartVoice\",\"appVersion\":\"2.23.1\",\"channel\":\"oppo\",\"cpuType\":\"redfin-redfin\",\"deviceName\":\"google-Pixel 5\",\"displayHeight\":\"2160\",\"displayWidth\":\"1080\",\"systemVersion\":\"Android12\"}",
    'Connection': "Keep-Alive",
    'Accept-Encoding': "gzip"
}

response = requests.get(url,params=params, headers=headers, timeout=30)

if response.content:
    text = response.content.decode("utf-8", errors="replace")
    print(text)
View Code

so层算法 360脱壳

image

 2.酷安

 

"""Pure-Python Coolapk X-App-Device/X-App-Token generation and request."""

from __future__ import annotations

import base64
import hashlib
import json
import os
import secrets
import time

import bcrypt
import requests


# libauth.so .rodata 0x408e6: Base64 -> XOR 0x5a gives the rotating table.
_TOKEN_TABLE_B64 = (
    "Dg4YDxUcCykLah82Fg8XMQ0eHzALCR8pDyMfNxYeFBsPI2seChwDLxMjajMXDxdvEyAYDxAcOS4XIzEyFw8LaxAJax4VCQ8iFyAyCxYMFy0MamopEyMyCRcOCykNDhweCBwfLQtqCAwXCQsxDwlqMBEJFy4QHjIDFgwLMQ8wHyARCQspF2oYDBYOCy0PM2pqFAkXKRdoGAIWDBc2EBlrHhQcNhQWGQtqDQ4fIBYJCyILah8yFh8XNhMwHyARHDktFyBqNhYzFB8MIB8wCgkDLxQeMTEWHBctDDMiDhEcMS4LIDICFhwXKQ0ZbjAWCQMuD2gYDg4OG2oWHB8vFyAyDhYwFzITMBweFxwXKRNqGAwWGQsxDxktIBAJEykTIBgJFx8XYg8ZIh8WCRMuE2gYCxYPCzUPI2owFhwXKRMjDzEXHAstDDFqLggZIgMXDhc2EBluahQJHy0PaggLFhwXMhMzajEUCRctD2gYCxYwFD0PIy0wFRwfKRQZIg4WHxctDRkiDxYJHy4TIwgOFh4UGBMjamoQHAAUFw8XKQ8eGB8QHD0uFBlqMRYeCzENGWseFxwXIggZMTAWDBdqDDMiDhccPSITI2o3FgwXIhAJaiAQHAsiF2gYCxYJC24NDhgeFxwXLxNqDzIOCS0gChw9LggeGAgXHhQfDwlqMBUcAy8QHjE2FwkLag8gGyAUCRctCB4xMRcOFzEMCSIPFxwLLggZIgMXDhQcEyMiHxYcAykTIA8yFjMLagxqaiIUGSIMFhkXagwjbiAQHA8iFBkiDhYcC24MI24wAxwDIhAeDzAWDxctDyAcHgocEykXah82Fh4XKQweG2oVCRcvFBkxNxYfCzEMMyIfFwkQFBYOFzUPMy0gFhw5Lg9qCAsWMwstDA4cHhAJDy0PIzEwFw8XMhMjaiATCQ8pE2ofMBcOFy0PCWsPFBw5IggeHzYWDwsuEAluMRQcEykTIDIADg4YDgMcHy0LIwgDFgkXNhMJbmoWHD0pDB4IABYPCzUNDhgeCxwDLggZIg0WMBQfDB4YHhccMS4UHg82FhwLbgwJaw8QHD0tFyAIDRYeC24PD2otCyNqNxYPC24NCWsOFwkXKQ8jDzMXDxQbDwkiDxYcAy8TaggPFjMXKQ0eHB8WHBciE2gYCxYMF2oNCW4xFRw5LRdqCAIWDBc1DRlqMBEcHyIWGRdqDDMiDhQcGy4IHggNFg8LNhAZaw4QHBstFBkiPQMb"
)


def token_table(clock: int, version_code: int) -> bytes:
    """Recover the native rotating table and select its 128-byte window."""
    decoded = base64.b64decode(_TOKEN_TABLE_B64)
    table = bytes(value ^ 0x5A for value in decoded)
    offset = ((int(clock) + int(version_code)) % 100) * 4 + 0x80
    return table[offset:offset + 0x80]


def generate_device_header(aid: str | None = None, mac: str = "",
                           manufacturer: str = "Google", brand: str = "google",
                           model: str = "Pixel 5",
                           build_number: str = "SQ3A.220705.003.A1") -> str:
    """Generate the real ``X-App-Device`` field layout used by Coolapk.

    Native/Java constructs nine ``; `` separated fields, Base64 encodes the
    UTF-8 bytes without padding, then reverses the complete Base64 string.
    """
    if aid is None:
        aid = secrets.token_urlsafe(27)
    fields = (aid, "", "", mac, manufacturer, brand, model, build_number, "null")
    plain = "; ".join(fields).encode("utf-8")
    return base64.b64encode(plain).decode("ascii").rstrip("=")[::-1]


def decode_device_header(value: str) -> str:
    """Decode an ``X-App-Device`` value for verification/debugging."""
    encoded = value[::-1]
    return base64.b64decode(encoded + "=" * ((-len(encoded)) % 4)).decode("utf-8")


def generate_app_token(device: str, timestamp: int | str, *, app_id: str = "com.coolapk.market",
                       app_code: str = "2608212", clock: int | None = None) -> str:
    """Generate the recovered v3 token pipeline from request/device context."""
    if clock is None:
        clock = int(timestamp)
    window = token_table(clock, int(app_code))
    rotating = base64.b64decode(window + b"=" * ((-len(window)) % 4))
    device_md5 = hashlib.md5(device.encode("utf-8")).hexdigest()
    material = (app_id.encode("utf-8") + b"&" + rotating + b"&"
                + device_md5.encode("ascii") + b"&"
                + str(timestamp).encode("ascii") + b"&" + app_code.encode("ascii"))
    material_b64 = base64.b64encode(material)
    password = hashlib.md5(material_b64).hexdigest().encode("ascii")
    material_md5 = hashlib.md5(material).hexdigest()
    salt_seed = base64.b64encode(
        f"{int(timestamp):x}/{material_md5}".encode("ascii")
    ).decode("ascii").rstrip("=")
    salt_body = salt_seed.translate(str.maketrans({"+": "."}))[:22]
    bcrypt_alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    last_index = bcrypt_alphabet.index(salt_body[-1]) & 0x30
    salt_body = salt_body[:-1] + bcrypt_alphabet[last_index]
    salt = ("$2y$04$" + salt_body).encode("ascii")
    hashed = bcrypt.hashpw(password, salt)
    if hashed.startswith(b"$2b$"):
        hashed = b"$2y$" + hashed[4:]
    return "v3" + base64.b64encode(hashed).decode("ascii").rstrip("=")



API_URL = "https://api.coolapk.com/v6/main/init"
APP_CODE = "2608212"
USER_AGENT = (
    "Dalvik/2.1.0 (Linux; U; Android 12; Pixel 5 Build/SQ3A.220705.003.A1) "
    "(#Build; google; Pixel 5; SQ3A.220705.003.A1; 12) "
    "+CoolMarket/16.6.1-2608212-community"
)


def request_init(aid: str | None = None) -> requests.Response:
    timestamp = str(int(time.time()))
    device = generate_device_header(aid)
    token = generate_app_token(device, timestamp)
    headers = {
        "User-Agent": USER_AGENT,
        "X-Requested-With": "XMLHttpRequest",
        "X-Sdk-Int": "32",
        "X-Sdk-Locale": "zh-CN",
        "X-App-Id": "com.coolapk.market",
        "X-App-Version": "16.6.1",
        "X-App-Code": APP_CODE,
        "X-Api-Version": "16",
        "X-Dark-Mode": "1",
        "X-App-Channel": "xiaomi",
        "X-App-Mode": "community",
        "X-App-Supported": APP_CODE,
        "X-App-Device": device,
        "X-App-Token": token,
    }
    return requests.get(
        API_URL,
        params={"exp": "0", "t": timestamp},
        headers=headers,
        timeout=20,
    )


def main() -> None:
    response = request_init(os.getenv("APP_AID"))
    print(f"HTTP_STATUS={response.status_code}")
    try:
        body = response.json()
        print(f"RESULT={'OK' if isinstance(body.get('data'), list) else 'ERROR'}")
        print(json.dumps(body, ensure_ascii=False, separators=(',', ':')))
    except ValueError:
        print("RESULT=ERROR")
        print(response.text)


if __name__ == "__main__":
    main()
View Code

 

image

 

葫芦侠

 

posted @ 2023-10-12 22:08  inks  阅读(39)  评论(0)    收藏  举报