如何获取一个APP的所有接口API和参数签名信息?
myzbx 2025-06-28 15:27 4 浏览
先给出所需的工具:
步骤 | 工具/技术 |
---|---|
抓包 | Charles、Fiddler、Wireshark、tcpdump |
反编译 | Jadx、JEB、Apktool |
动态调试 | Frida、IDA Pro、Unidbg/Unicorn(模拟执行) |
加密分析 | JEB(DES/MD5识别)、IDA Pro(Native层分析) |
模拟请求 | Postman、curl、Reqable、Python(requests库)、 |
(声明:本文章仅用于技术交流学习,所有用到的代码和数据均做了脱敏处理,请勿用于非法用途)
第一步:抓包分析,网络请求
1,抓包分析:通过Charles、Fiddler或Wireshark等工具捕获应用的HTTP/HTTPS请求,分析请求URL、参数、头部信息及响应内容。
Charles/Fiddler: 更易用的界面,但仅限HTTP/HTTPS
fiddler注意:【若客户端校验证书(部分APP),可能导致Charles无法捕获流量,需通过逆向绕过证书绑定,如Xposed模块】
Wireshark:适合分析底层协议(如TCP握手、TLS版本),但需手动过滤HTTP流量。
wireshark2,分析关键点:重点关注加密参数(如Encrypt字段)、动态Token、签名机制等,记录多次请求中变化的参数。
第二步: 静态分析, 反编译与代码解析
1,脱壳与反编译:
若应用加壳,需先通过脱壳脚本提取DEX文件(如使用Frida、Xposed模块或自定义脚本)。
针对主流加固方案(如360加固宝),可使用脱壳工具(如Frida-Dump,BlackDEX等)提取DEX。
或可以自己分析壳的加载机制,定位原始DEX内存地址:
// 核心函数:Hook libart.so的OpenMemory方法function hook_dex_dump(packageName) { var libart = Module.findBaseName('libart.so'); var symbols = ['_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_', '_ZN3art13DexFileLoader10OpenCommonEPKhjS2_jPKNS_10OatDexFileEbbPS9_PNS0_12VerifyResultE']; symbols.forEach(function(symbol) { var openMemory = Module.findExportByName('libart.so', symbol); if (openMemory) { Interceptor.attach(openMemory, { onEnter: function(args) { // 获取DEX起始地址和大小 var dex_begin = is64bit() ? this.context.x1 : args[1]; var dex_size = is64bit() ? this.context.x2 : args[2]; // 校验magic头 var magic = Memory.readUtf8String(ptr(dex_begin), 4); if (magic.indexOf('dex') === 0) { // 生成唯一文件名 var timestamp = new Date().getTime(); var savePath = "/sdcard/Download/" + packageName + "_" + timestamp + ".dex"; // 内存转储 var dexData = Memory.readByteArray(ptr(dex_begin), dex_size); var file = new File(savePath, "wb"); file.write(dexData); file.close(); console.log("[+] Dumped DEX to: " + savePath); } }, onLeave: function(retval) { // 可选:处理返回结果 } }); } });} // 判断CPU架构function is64bit() { return Process.arch.indexOf('64') !== -1;} // 启动脱壳Java.perform(function() { var currentPackage = Java.use("android.app.ActivityThread").currentApplication().getPackageName(); hook_dex_dump(currentPackage); console.log("[*] Hooking libart.so for package: " + currentPackage);});
脱壳完成后,使用Jadx、JEB或Apktool反编译APK,分析Java/Smali代码及资源文件。
2,静态分析:
在代码中搜索网络请求相关类(如OkHttpClient、Retrofit、HttpURLConnection),定位发送/接收函数(如execute()、onResponse())。
通过字符串搜索接口URL或参数名,或通过正则表达式匹配URL模式。
第三步: 动态分析,定位加密与参数生成逻辑
1,加密算法分析:
若参数被加密(如MD5、DES、AES),需在代码中定位加密函数,通常通过搜索关键词(如Cipher、SecretKey)或Hook加密方法验证逻辑。
常用算法清单:
算法名称 | 类型 | 密钥长度/摘要长度 | 特点 | 常见模式/填充 |
---|---|---|---|---|
AES | 对称加密 | 128/192/256位 | 高效安全,广泛用于数据加密;需关注分组模式(如CBC、ECB)和填充方式 | 模式:CBC、ECB、CFB等;填充:PKCS5Padding、PKCS7Padding、NoPadding |
RSA | 非对称加密 | 1024/2048位 | 公钥加密、私钥解密;用于密钥交换或数字签名;需结合摘要算法(如SHA) | 填充:PKCS1Padding、NoPadding |
DES | 对称加密 | 56位 | 安全性低,易受暴力破解;已逐渐被淘汰,常见于遗留系统 | 模式:ECB、CBC;填充:PKCS5Padding |
3DES | 对称加密 | 112/168位 | DES的增强版,三次加密提升安全性;性能较低,适用于兼容性场景 | 模式:CBC、ECB;填充:PKCS5Padding |
MD5 | 消息摘要(哈希) | 128位 | 生成固定长度哈希值;存在碰撞漏洞,仅用于校验数据完整性 | 无模式或填充 |
SHA系列 | 消息摘要(哈希) | SHA-1(160位)等 | 安全性高于MD5(如SHA-256);用于签名、数据完整性校验 | 无模式或填充 |
Base64 | 编码 | 无 | 将二进制数据转为ASCII字符串;常用于加密后数据的传输或存储 | 标准编码/URL安全编码 |
Hex | 编码 | 无 | 二进制数据以十六进制表示;便于调试和显示 | 无特殊模式 |
ECC | 非对称加密 | 256/384/521位 | 基于椭圆曲线理论,安全性高且密钥短;适用于移动设备等资源受限环境 | 模式:ECDSA(签名)、ECDH(密钥交换);填充:无 |
对于Native层加密,需用IDA Pro分析SO库,定位JNI函数或JNI_OnLoad。
2,参数构造逻辑:
分析参数拼接方式(如时间戳、设备ID、签名),常见于工具类或拦截器(如Interceptor)。
动态调试(如Frida、Xposed)跟踪参数生成过程,验证加密算法与密钥。
3,代码混淆应对:
通过字符串解密工具或动态调试还原关键类名/方法名。
分析Proguard/R8规则(如mapping.txt)还原符号。
第四步: 提取API接口及参数
1,接口提取方法:
从抓包结果直接提取URL及参数结构。
在代码中搜索API配置类(如ApiConstants),或通过全局Map结构存储的接口路径。
分析RESTful接口设计,结合HTTP方法(GET/POST)及资源路径(如/user/{id})。
2,参数类型推断:
通过代码分析参数数据类型(如JSON字段、表单数据)及校验逻辑(如非空检查、格式校验)。
若参数为动态生成(如设备指纹),需结合设备信息(IMEI、MAC地址)分析生成逻辑
第五步: 动态验证与模拟请求
1,Hook验证:
使用Frida Hook网络请求函数(如OkHttp的Interceptor),打印完整请求参数。
修改参数值测试接口响应,验证参数合法性。
Java.perform(function() { // 获取OkHttp核心类 var OkHttpClient = Java.use('okhttp3.OkHttpClient'); var Request = Java.use('okhttp3.Request'); var Buffer = Java.use('okio.Buffer'); // Hook OkHttpClient的newCall方法 OkHttpClient.newCall.overload('okhttp3.Request').implementation = function(request) { // 解析请求信息 var url = request.url().toString(); var method = request.method(); var headers = request.headers().toString(); var body = request.body(); var bodyContent = ''; // 读取请求体内容 [[4, 16]] if (body) { try { var buffer = Buffer.$new(); body.writeTo(buffer); bodyContent = buffer.readUtf8(); buffer.$dispose(); } catch(e) { bodyContent = '无法解析的请求体类型'; } } // 打印请求信息 console.log('\n=== 请求捕获 ==='); console.log(`URL: ${url}`); console.log(`Method: ${method}`); console.log(`Headers: ${headers}`); console.log(`Body: ${bodyContent}`); console.log('================\n'); // 执行原始调用 return this.newCall(request); }; // Hook响应处理 var Response = Java.use('okhttp3.Response'); Response.body.implementation = function() { var body = this.body(); try { var content = body.string(); console.log('\n=== 响应捕获 ==='); console.log(`Status: ${this.code()} ${this.message()}`); console.log(`Response Body: ${content}`); console.log('================\n'); // 重建body对象避免消费问题 return Java.use('okhttp3.ResponseBody') .create(body.contentType(), content); } catch(e) { return body; } };});
2,模拟请求:
根据分析结果,用Python(requests库)或Postman/Curl命令模拟请求,复现加密逻辑。
对比模拟结果与真实请求,确保参数生成正确性。
如何用Curl模拟请求:
a, 从Charles导出cURL命令:右键点击抓包的请求,选择“Copy cURL Command”。
b, 调整命令:可能需处理特殊符号(如^
需转义为^^
或\^
)
最后,整理并输出API文档:
整理接口URL、请求方法(GET/POST)、参数列表(名称、类型、是否必填)、加密方式及示例请求。
标注敏感参数(如签名、Token)的生成规则。
(----------下面给个示例---------)
a. 用户登录接口
接口功能:用户身份认证,获取访问令牌
URL:[https://api.
wolfcard.com/v2/auth/login](https://api.
wolfcard.com/v2/auth/login)
请求方法:POST
参数列表:
参数名 | 类型 | 是否必填 | 说明 | 敏感参数 |
---|---|---|---|---|
username | String | 是 | 用户名 | 否 |
password | String | 是 | SHA256加密后的密码 | 是 |
timestamp | Long | 是 | 当前时间戳(毫秒) | 否 |
nonce_str | String | 是 | 16位随机字符串 | 否 |
signature | String | 是 | 请求签名(见生成规则) | 是 |
加密方式:
- 密码加密:
password = SHA256(原始密码 + timestamp)
- 签名生成规则(需逆向获取):
- 拼接参数:
raw_str = username + "|" + password + "|" + timestamp + "|" + nonce_str
- 加盐计算:
signature = HMAC_SHA256(raw_str, key="s3cr3tK3y")
- 结果转为大写:
signature = signature.toUpperCase()
示例请求:
POST /v2/auth/login HTTP/1.1Content-Type: application/json{ "username": "test_user", "password": "A3F291B8D45C...", "timestamp": 1735689200000, "nonce_str": "7x9a2b4c6d8e0f1", "signature": "E9D3A1B5F7C8..."}
b. 订单查询接口
接口功能:获取用户订单列表
URL:[https://api.
wolfcard.com/v3/orders/list](https://api.
wolfcard.com/v3/orders/list)
请求方法:GET
参数列表:
参数名 | 类型 | 是否必填 | 说明 | 敏感参数 |
---|---|---|---|---|
user_id | String | 是 | 用户ID(登录后返回) | 否 |
start_time | Long | 否 | 查询起始时间(毫秒) | 否 |
end_time | Long | 否 | 查询结束时间(毫秒) | 否 |
token | String | 是 | 登录令牌 | 是 |
sign | String | 是 | 动态签名(见生成规则) | 是 |
加密方式:
- 签名生成规则(基于逆向分析):
- 按参数名升序排列:
sorted_params = end_time, start_time, token, user_id
- 拼接键值对:
raw_str = "end_time=1735689200000&start_time=1735602800000&token=xxxx&user_id=1001"
- 加盐计算:
sign = MD5("secretPrefix" + raw_str + "secretSuffix")
- 结果转为大写:
sign = sign.toUpperCase()
示例请求:
GET /v3/orders/list?user_id=1001&start_time=1735602800000&end_time=1735689200000&token=eyJhbGci...&sign=8D7A2B4C6E9F0... HTTP/1.1
c. 数据加密接口(Native层)
接口功能:敏感数据加密传输
URL:[
wolfcard
https://api.wolfcard.com/native/encrypt](https://api..com/native/encrypt)
请求方法:POST
参数列表:
参数名 | 类型 | 是否必填 | 说明 | 敏感参数 |
---|---|---|---|---|
data | String | 是 | 原始JSON数据 | 是 |
encrypt_v | String | 是 | 加密版本(如v1/aes) | 否 |
request_id | String | 是 | 请求唯一标识 | 否 |
加密方式(逆向发现):
- AES加密流程:
- 生成随机IV:
iv = Random(16 bytes)
- 加密密钥:
key = SHA256(device_id + imei).substring(0, 32)
- 加密数据:
encrypted_data = AES_CBC_PKCS7(data, key, iv)
- 组合结果:
final_data = base64(iv + encrypted_data)
示例请求:
POST /native/encrypt HTTP/1.1Content-Type: application/octet-stream{ "data": "5tC1oP3x...", // Base64编码的加密数据 "encrypt_v": "aes_v2", "request_id": "req_20250417001"}
声明:本文章仅用于技术交流学习,所有用到的代码和数据均做了脱敏处理,请勿用于非法用途!
相关推荐
- C语言备忘录 - 09. 数组与字符串(c语言数组字符串长度)
-
C语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。一、数组定义/*定义一个一维数组数...
- Java 读取 xml 文件的五种方式(java读取xml工具类)
-
1、Java读取xml文件的五种方式在Java中读取XML文件有多种方法,这里列出五种常见的方式:DOM解析器(DocumentObjectModel):DOM是处理XML文...
- 如何获取一个APP的所有接口API和参数签名信息?
-
先给出所需的工具:步骤工具/技术抓包Charles、Fiddler、Wireshark、tcpdump反编译Jadx、JEB、Apktool动态调试Frida、IDAPro、Unidbg/Unico...
- 编辑距离算法详解:Levenshtein Distance算法
-
算法基本原理:假设我们可以使用d[i,j]个步骤(可以使用一个二维数组保存这个值),表示将串s[1…i]转换为串t[1…j]所需要的最少步骤个数,那么,在最基本的情况下,即在i等...
- RTCP协议详解(SR、RR、SDES、BYE、APP、NACK、TCC、PLI、SLI)
-
RTCP协议规范中定义了五种类型的RTCP包:接收方报告(RR)、发送方报告(SR)、源描述(SDES)、成员管理(BYE)和应用程序定义(APP)。SR:payload...
- javascript实现获取中文汉字拼音首字母
-
今天分享一个日常开发中可能会用到的一个小功能,简单说就是输入中文汉字可转换得到中文汉字拼音首字母。当然我可写不出这样的功能,源码来自于其他民间大神的分享,博主在此记录一下功能demo,方便日后复用,同...
- 记一次前端逻辑绕过登录到内网挖掘
-
前言在测试一个学校网站的时候发现一个未授权访问内网系统,但是这个未授权并不是接口啥的,而是对前端js的审计和调试发现的漏洞,这里给大家分享一下这次的漏洞的过程文章中涉及的敏感信息均已做打码处理,文...
- Node.js 是怎么找到模块的?(node.js有哪些模块)
-
大家好,我是前端西瓜哥,今天我们来看看Node.js模块查找的原理。模块种类模块有三种来源。核心模块:Node.js内置的包。比如http、fs、path;自定义模块:NPM包。比如axi...
- 细节确定成败!全网最详细的xxs夸脚本攻击以及测试方法(上)
-
XSS全称是CrossSiteScripting也是跨站脚本,他也分为三种类型存储型,反射型,DOM型。当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就...
- 简单易懂的KMP字符串匹配算法(实现kmp字符串匹配)
-
什么是KMPKMP算法是Knuth、Morris和Pratt三人设计的线性时间字符串匹配算法。算法的核心思想是尽可能地利用已知信息,减少尝试匹配的次数,从而降低时间复杂度。要想彻底地弄懂KMP算法,需...
- golang标准库每日一库之strings(golang 字符串操作)
-
以下为Go语言strings包的深度解析,涵盖字符串切割、替换、查找等核心操作及高效处理技巧:一、基础字符串操作1.字符串切割(Split)函数作用描述示例strings.Split(s,s...
- 开源轻量级BT下载器qBittorrent 5.1.1发布:改进Wayland会话
-
IT之家6月24日消息,科技媒体9to5Linux昨日(6月23日)发布博文,报道称开源轻量级BT下载器qBittorrent发布5.1.1版本更新,主要改进支持Lin...
- 晨雾轻散时!2 道 JS 面试题细解,静享知识慢时光
-
清晨的雾气渐渐散去,阳光透过纱窗洒在桌前,泡一杯温热的蜂蜜水,让我们在这宁静的氛围里,以轻松的节奏聊聊两道JavaScript高频面试题。就像在晨光中散步,不急不躁地探索知识,让学习成为一种治愈的...
- JS 写正则表达式,判断是否为手机号
-
以下是使用JavaScript写正则表达式,判断一个字符串是否为手机号的示例代码:在上述代码中,我们定义了一个isPhoneNumber函数,该函数接收一个字符串作为参数,使用正则表达式判断该...
- 不用任何 js 库,纯前端导出数据到 Excel / CSV 文件就简单几行代码
-
最近实现的导出数据为表格的需求,不需要工具库,也不要后端实现,mark一下。js导出excel表格最近工作中又遇到了将表格数据导出为excel表格的需求,我第一时间想到的是之前我的网站上推...
- 一周热门
- 最近发表
-
- C语言备忘录 - 09. 数组与字符串(c语言数组字符串长度)
- Java 读取 xml 文件的五种方式(java读取xml工具类)
- 如何获取一个APP的所有接口API和参数签名信息?
- 编辑距离算法详解:Levenshtein Distance算法
- RTCP协议详解(SR、RR、SDES、BYE、APP、NACK、TCC、PLI、SLI)
- javascript实现获取中文汉字拼音首字母
- 记一次前端逻辑绕过登录到内网挖掘
- Node.js 是怎么找到模块的?(node.js有哪些模块)
- 细节确定成败!全网最详细的xxs夸脚本攻击以及测试方法(上)
- 简单易懂的KMP字符串匹配算法(实现kmp字符串匹配)
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 选择器 (30)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)