APK静态基本信息查询
接口说明
通过 APK md5 查询样本的静态信息, 包含人工分析的特有字段 fphash。
推荐应用场景
用于后台管理和风控系统
请求地址
https://api.f.360.cn/files/apk/v1/static_info/md5
请求方法
POST
请求参数
| 参数名 | 类型 | 位置 | 是否必填 | 示例值 | 说明 |
|---|---|---|---|---|---|
| md5 | string | body | 是 | 7eccf18c291a0bec935426c3522a3b98 | APK 文件的 md5 |
响应参数
| 名称 | 类型 | 示例值 | 描述 | 应用说明 |
|---|---|---|---|---|
| cert_md5 | string | APK 文件的 证书 md5 | ||
| cert_name | string | APK 文件的 证书名 | ||
| cert_sha1 | string | APK 文件的 证书 sha1 | ||
| cert_valid_from | string | APK 文件的 证书有效起始日期 | ||
| cert_valid_to | string | APK 文件的 证书有效结束日期 | ||
| create_time | number | 收录时间戳(扫描时间) | ||
| dex_compile_time | string | APK 主dex文件编译时间 | ||
| dex_count | number | APK 主dex文件数量 | ||
| dex_md5 | string | APK 主dex文件 md5 | ||
| dex_sha1 | string | APK 主dex文件 sha1 | ||
| dex_sha256 | string | APK 主dex文件 sha256 | ||
| fp_hash | string | APK 文件的 路径 hash | ||
| icon_md5 | string | APK 文件图标 md5 | ||
| md5 | string | 7eccf18c291a0bec935426c3522a3b98 | APK 文件的 md5 | |
| mfsha1 | string | APK 文件的 mfsha1 | ||
| name | string | APK 文件的 应用名 | ||
| package_name | string | APK 文件的 包名 | ||
| package_size | number | APK 文件的 大小 | ||
| pms | Array(number) | APK 文件 权限列表 | ||
| sha1 | string | 510bf0d6595248fda0ebf508eca41da818a16cfc | APK 文件的 sha1 | |
| sha256 | string | 164f5205e749fa5dc0459b7d6b26680e83684c5d256401e87e955d07cf744beb | APK 文件的 sha256 | |
| verify | number | 25 | APK 文件 有效性 | 25 表示有效,其他表示无效 |
| version | string | APK 文件的 版本 | ||
| version_code | number | APK 文件的 版本号 |
请求示例
支持cUrl、Python、Java、PHP、Go语言的请求,示例如下
#!/usr/bin/env bash
set -euo pipefail
APPID="" # apikey
SECRET="" # salt
URL="https://api.f.360.cn/files/apk/v1/static_info/md5"
BODY='{"md5":"7eccf18c291a0bec935426c3522a3b98"}'
NONCE=$(printf '%08d' $((RANDOM % 100000000)))
TIMESTAMP=$(date +%s)
BODY_MD5=$(printf '%s' "$BODY" | openssl dgst -md5 -hex | awk '{print $NF}')
SIGNATURE=$(printf '%s' "${BODY_MD5}${APPID}${NONCE}${TIMESTAMP}${SECRET}" | openssl dgst -md5 -hex | awk '{print $NF}')
SIGNATURE=${SIGNATURE:16}
curl --location --request POST "$URL" \
--header "Content-Type: application/json" \
--header "X-360-Key: ${APPID}" \
--header "X-360-Nonce: ${NONCE}" \
--header "X-360-Timestamp: ${TIMESTAMP}" \
--header "X-360-Signature: ${SIGNATURE}" \
--data "${BODY}"# python3.6.8
import hashlib
import json
import random
import time
import requests
APPID = "" # apikey
SECRET = "" # salt
def make_headers(appid, secret, body):
headers = {}
headers["X-360-Key"] = appid
headers["X-360-Nonce"] = str(random.randint(0, 99999999)).zfill(8)
headers["X-360-Timestamp"] = str(int(time.time()))
s = (
hashlib.md5(body.encode("utf8")).hexdigest()
+ headers["X-360-Key"]
+ headers["X-360-Nonce"]
+ headers["X-360-Timestamp"]
+ secret
)
md5 = hashlib.md5(s.encode("utf8")).hexdigest()
headers["X-360-Signature"] = md5[16:]
headers["Content-Type"] = "application/json"
return headers
def do_post(url, body):
res = requests.post(
url,
data=json.dumps(params),
headers=make_headers(APPID, SECRET, json.dumps(body)),
)
print(res.text)
if __name__ == "__main__":
# 请求地址
url = "https://api.f.360.cn/files/apk/v1/static_info/md5"
# 查询参数
params = {"md5": "7eccf18c291a0bec935426c3522a3b98"}
do_post(url, params)import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.concurrent.ThreadLocalRandom;
public class Demo {
static String md5(String input) throws Exception {
byte[] digest = MessageDigest.getInstance("MD5")
.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
String appid = ""; // apikey
String secret = ""; // salt
String url = "https://api.f.360.cn/files/apk/v1/static_info/md5";
String body = "{\"md5\":\"7eccf18c291a0bec935426c3522a3b98\"}";
String nonce = String.format("%08d", ThreadLocalRandom.current().nextInt(100000000));
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String signature = md5(md5(body) + appid + nonce + timestamp + secret).substring(16);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.header("X-360-Key", appid)
.header("X-360-Nonce", nonce)
.header("X-360-Timestamp", timestamp)
.header("X-360-Signature", signature)
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
.build();
HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
System.out.println(response.body());
}
}<?php
// apikey
$appid = "";
// salt
$secret = "";
$url = 'https://api.f.360.cn/files/apk/v1/static_info/md5';
$body = json_encode(['md5' => '7eccf18c291a0bec935426c3522a3b98'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$nonce = str_pad((string) random_int(0, 99999999), 8, "0", STR_PAD_LEFT);
$timestamp = (string) time();
$signature = substr(md5(md5($body) . $appid . $nonce . $timestamp . $secret), 16);
$ch = curl_init($url);
$options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-360-Key: {$appid}",
"X-360-Nonce: {$nonce}",
"X-360-Timestamp: {$timestamp}",
"X-360-Signature: {$signature}",
],
];
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $body;
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
if ($response === false) {
echo curl_error($ch), PHP_EOL;
} else {
echo $response, PHP_EOL;
}
curl_close($ch);package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"math/rand"
"net/http"
"time"
)
func md5Hex(s string) string {
sum := md5.Sum([]byte(s))
return hex.EncodeToString(sum[:])
}
func main() {
appid := "" // apikey
secret := "" // salt
url := "https://api.f.360.cn/files/apk/v1/static_info/md5"
body := []byte(`{"md5":"7eccf18c291a0bec935426c3522a3b98"}`)
nonce := fmt.Sprintf("%08d", rand.Intn(100000000))
timestamp := fmt.Sprintf("%d", time.Now().Unix())
signature := md5Hex(md5Hex(string(body)) + appid + nonce + timestamp + secret)[16:]
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-360-Key", appid)
req.Header.Set("X-360-Nonce", nonce)
req.Header.Set("X-360-Timestamp", timestamp)
req.Header.Set("X-360-Signature", signature)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(respBody))
}响应示例
业务正常响应
{
"code": "0",
"reason": "",
"message": "",
"data": {
"md5": "7eccf18c291a0bec935426c3522a3b98",
"sha1": "510bf0d6595248fda0ebf508eca41da818a16cfc",
"sha256": "164f5205e749fa5dc0459b7d6b26680e83684c5d256401e87e955d07cf744beb",
"mfsha1": "84bc6a88789220a098f48870b5cf81c15478edd2",
"name": "群青魔女汉化直装版使用方法安卓真人版",
"package_name": "com.berry.designate.quiet",
"version": "6.26.02",
"version_code": "62602",
"package_size": "27480968",
"cert_name": "CN=WilsonWu, OU=3G, O=Tencent, L=ShangHai, ST=GD, C=CN",
"cert_md5": "e8344e6851b3e6f43632ab9ddd9478e6",
"cert_sha1": "f325e63a1101f850657ef77638a76022f5cfba9b",
"cert_valid_from": "20241226043441",
"cert_valid_to": "25720726043441",
"dex_md5": "b41e7f3c2ef0796e538293c37a160c18",
"dex_sha1": "959459d8107d236ef8e3b980275c407e7fff0328",
"dex_sha256": "497a1ec3bde9acec559876c0a7b74e7659b6b8c1011642b1c6491c5500b1cd3d",
"dex_count": 1,
"dex_compile_time": "1981-01-01 01:01:02",
"icon_md5": "7dd0c9c2cdad59f4cb27b4d6553b445e",
"pms": [
19,
20,
27,
31,
42,
48,
49,
64,
73,
78,
79,
85,
93,
94,
95
],
"verify": 25,
"create_time": "1766618818",
"fp_hash": "c8768cbd5d00f4058d9104361f500125"
}
}业务异常响应
{
"code": "AC00500",
"reason": "BAD_REQUEST",
"message": "query apk, invalid hash:7eccf18c291a0bec935426c3522a3b9",
"data": null
}