一 抓包逆向案例
1.1 金树林.apk
1.1.1 目标
1.1.2 发送验证码
| import requests |
| |
| res=requests.get('https://miappshop.jshulin.com/memberLogin/phoneCode?phone=%s&serviceType=5'%'18953675222',verify=False) |
| print(res.text) |
1.1.3 注册
| data = {"phone": "18953675222", "fid": "", "password": "lqz12345", "phoneCode": "147426"} |
| res = requests.post('https://miappshop.jshulin.com/memberLogin/memberRegister', json=data, verify=False) |
| print(res.text) |
1.1.4 登录
| import requests |
| |
| data={"password":"1234567","username":"189536754431"} |
| res=requests.post('https://miappshop.jshulin.com/memberLogin/login',json=data,verify=False) |
| print(res.text) |
1.1.5 登录后查询红酒
| data = {"cityNo": "", "limit": 10, "orderByContent": "", "page": 1, "productCategoryId": "1649599340962672642", |
| "enabled": 1} |
| s=''' |
| Mobile-Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxNjcwODM4OTQ0MDY3ODU0MzM4IiwiZXhwIjoxNjg3MTk3NjIxLCJpYXQiOjE2ODcxOTQwMjEsInVzZXJJZCI6IjE2NzA4Mzg5NDQwNjc4NTQzMzgiLCJ1c2VybmFtZSI6IjE4OTUzNjc1MjIxIn0.QUvl4Gqbri-btL0HUbcfuQYvwtF3Flg4Y4DDJ6S6UPY |
| user-agent Mozilla/5.0 (Linux; Android 11; Pixel 2 XL Build/RP1A.201005.004.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/28.0) |
| Content-Type application/json |
| ''' |
| header=header_str_to_dict(s) |
| res = requests.post('https://miappshop.jshulin.com/pro/searchByPage',json=data,verify=False,headers=header) |
| print(res.json()) |
| |
| |
| def header_str_to_dict(header_str): |
| res = [item for item in header_str.split('\n')] |
| res = res[1:len(res) - 1] |
| |
| d = {item.split('\t')[0]: item.split('\t')[1] for item in res} |
| return d |
1.1.6 补充(请求参数转字典,请求头转字典)
| |
| |
| s='appId=32&hashSign=8356ebae71a0aa643f87ad4c5691a456&imgUrl=&lat=29.568295&lng=106.559123&loginName=18953675222&nickName=&openId=&place=%E9%87%8D%E5%BA%86&pwd=25d55ad283aa400af464c76d713c07ad&sessionId=392032c5-09c8-4c3c-bb17-16a1dc49f7fc&token=&type=' |
| |
| |
| def query_to_dict(s): |
| return { item.split('=')[0]:item.split('=')[1]for item in s.split('&')} |
| print(query_to_dict(s)) |
| |
| from urllib.parse import parse_qs, unquote |
| def parse(s: str) -> dict: |
| return {k: v[0] for k, v in parse_qs(s).items()} |
| |
| print(parse(s)) |
| |
| |
| |
| |
| def header_str_to_dict(header_str): |
| res = [item for item in |
| header_str.split('\n')] |
| |
| res = res[1:len(res) - 1] |
| |
| d = {item.split('\t')[0]: item.split('\t')[1] for item in res} |
| return d |
1.1.7 补充 url编码解码
| from urllib import parse |
| print(parse.quote('上海')) |
| print(parse.unquote('%E4%B8%8A%E6%B5%B7')) |
1.1.8 补充接码平台
| |
| https://w3h5.com/post/619.html |
| |
| |
| https://www.goinsms.xyz/cn.php |
| https://smscoders.com/china_phones |
| |
| |

1.2 爱安丘.apk
1.2.1 目标
| |
| |
| |
| -官网下载:LSposed https://github.com/LSPosed/LSPosed/releases |
| -使用面具刷入 |
| -安装JustTrustMe |
| -开启重启即可 |
1.2.2 IMEI
| IMEI(International Mobile Equipment Identity)是【国际移动设备识别码】的缩写,它是一个唯一标识符,用于识别移动设备,如手机、平板电脑等。IMEI由15位数字组成,每一位都有特定的含义 |
| |
| |
| 前六位(TAC):型号核准号码,用于识别设备的制造商和设备类型。 |
| 接下来的两位(FAC):最终装配代码,表示设备的最终装配站。 |
| 后面的六位(SNR):串号,表示设备的序列号。 |
| 最后一位(SP):校验位,用于验证IMEI的有效性 |
| |
| |
| def generate_imei(): |
| |
| tac = ''.join(random.choices('0123456789', k=6)) |
| |
| |
| fac = ''.join(random.choices('0123456789', k=2)) |
| |
| |
| snr = ''.join(random.choices('0123456789', k=6)) |
| |
| |
| imei_base = tac + fac + snr |
| imei_list = [int(digit) for digit in imei_base] |
| check_digit = sum(imei_list[::-2] + [sum(divmod(d * 2, 10)) for d in imei_list[-2::-2]]) % 10 |
| |
| |
| imei = imei_base + str((10 - check_digit) % 10) |
| |
| return imei |
| |
1.2.3 验证码登录(老版本v228)
| import random |
| import requests |
| |
| |
| from utils import generate_imei |
| |
| |
| imei = generate_imei() |
| print(imei) |
| |
| session = requests.Session() |
| session.cookies.set("orgid", "137") |
| session.headers.update({ |
| "cq-agent": '{"os":"android","imei":"%s","osversion":"6.0.1","network":"none","version":"0.0.28.108","core":"1.6.4"}' % imei, |
| "user-agent": "chuangqi.o.137.com.iqilu.app137/0.0.28.108", |
| "orgid": "137" |
| }) |
| |
| phone_num = input("请输入手机号:") |
| |
| res = session.post( |
| url="https://app-auth.iqilu.com/member/phonecode", |
| json={ |
| "phone": phone_num |
| }, |
| verify=False |
| ) |
| res_dict = res.json() |
| print(res_dict) |
| key = res_dict['data'] |
| code = input("请输入手机接收到的验证码:") |
| |
| res = session.post( |
| url="https://app-auth.iqilu.com/member/login", |
| json={ |
| "phone": phone_num, |
| "code": code, |
| "key": key, |
| "password": "", |
| "captcha": "", |
| "captchaKey": "" |
| },verify=False |
| ) |
| print("登录结果->", res.text) |
1.2.4 验证码接收
1.2.5 手机号密码登录(新版本最新版)
反编译,找位置(根据地址:member/login)





hook.py
| |
| adb shell |
| su |
| cd /data/local/tmp/ |
| ls |
| ./frida-server-16.0.19-android-arm64 |
| |
| |
| adb forward tcp:27042 tcp:27042 |
| adb forward tcp:27043 tcp:27043 |
| |
| |
| |
| |
| import frida |
| |
| rdev = frida.get_remote_device() |
| |
| processes = rdev.enumerate_processes() |
| for process in processes: |
| print(process) |
| |
| front_app = rdev.get_frontmost_application() |
| print(front_app) |
| |
| |
| |
| |
| import frida |
| import sys |
| |
| |
| rdev = frida.get_remote_device() |
| |
| session = rdev.attach("爱安丘") |
| |
| scr = """ |
| Java.perform(function () { |
| |
| // 包.类 |
| var EncryptUtil = Java.use("com.iqilu.core.util.EncryptUtil"); |
| |
| EncryptUtil.getMD5.implementation = function(str){ |
| console.log("明文:",str); |
| var res = this.getMD5(str); |
| console.log("md5加密结果=",res); |
| return res; |
| } |
| |
| }); |
| """ |
| |
| script = session.create_script(scr) |
| |
| |
| def on_message(message, data): |
| print(message, data) |
| |
| |
| script.on("message", on_message) |
| |
| script.load() |
| sys.stdin.read() |
用户名密码登录代码
| import requests |
| from utils import generate_imei, header_str_to_dict, encrypt_data |
| |
| session = requests.session() |
| imei = generate_imei() |
| header_s = ''' |
| encrypt 1 |
| version 1.0.5 |
| orgid 137 |
| User-Agent null chuangqi.o.137.com.iqilu.app137/1.0.5 |
| platform android |
| imei bae6495482efee22 |
| CQ-AGENT {"os":"android","brand":"google","imei":"%s","osversion":"11","network":"unknown","version":"1.0.5","core":"2.2.1.1"} |
| cq-token |
| Content-Type application/json; charset=UTF-8 |
| Content-Length 93 |
| Host app-auth.iqilu.com |
| Connection Keep-Alive |
| Accept-Encoding gzip |
| Cookie orgid=137 |
| ''' % imei |
| header = header_str_to_dict(header_s) |
| phone = input('请输入手机号:') |
| password = input('请输入密码:') |
| |
| password = encrypt_data(password) |
| data = {"codeKey": "", "password": password, "code": "", "phone": phone, "key": ""} |
| res = session.post('https://app-auth.iqilu.com/member/login?e=1', headers=header, json=data,verify=False) |
| print(res.text) |
utils.py
| import random |
| from Crypto.Cipher import AES |
| import base64 |
| |
| |
| def generate_imei(): |
| |
| tac = ''.join(random.choices('0123456789', k=6)) |
| |
| |
| fac = ''.join(random.choices('0123456789', k=2)) |
| |
| |
| snr = ''.join(random.choices('0123456789', k=6)) |
| |
| |
| imei_base = tac + fac + snr |
| imei_list = [int(digit) for digit in imei_base] |
| check_digit = sum(imei_list[::-2] + [sum(divmod(d * 2, 10)) for d in imei_list[-2::-2]]) % 10 |
| |
| |
| imei = imei_base + str((10 - check_digit) % 10) |
| |
| return imei |
| |
| |
| |
| def query_to_dict(s): |
| return {item.split('=')[0]: item.split('=')[1] for item in s.split('&')} |
| |
| |
| def header_str_to_dict(header_str): |
| res = [item for item in header_str.split('\n')] |
| res = res[1:len(res) - 1] |
| |
| d = {item.split('\t')[0]: item.split('\t')[1] for item in res} |
| return d |
| |
| |
| |
| |
| |
| def pad_data(data): |
| |
| pad_len = AES.block_size - (len(data) % AES.block_size) |
| |
| padding = bytes([pad_len] * pad_len) |
| padded_data = data + padding |
| return padded_data |
| |
| |
| |
| def encrypt_data(password): |
| |
| |
| |
| key = b'6d6656a37cdb7977c10f6d83cab168e9' |
| |
| iv = b'0000000000000000' |
| cipher = AES.new(key, AES.MODE_CBC, iv) |
| |
| padded_data = pad_data(password.encode('utf-8')) |
| print(padded_data) |
| |
| encrypted_data = cipher.encrypt(padded_data) |
| return base64.b64encode(encrypted_data).decode('utf-8') |
| |
| |
| if __name__ == '__main__': |
| print(encrypt_data('1234567')) |
| |
| |
| |
二 抓包反编译案例
2.1 X大夫
2.1.1 目录
2.1.2 操作步骤
| |
| https://api.niaodaifu.cn/v4/site/loginnew |
| |
| devisetoken 1507bfd3f6dd1eafc0f |
| password lqz12345 |
| mobile 18953675222 |
| channel android |
| sign afc1963626ccdb43d5b394017b206144 |
| time 1687255476 |
| mechanism 0 |
| platform 1 |
| |
| |
| |
| |
| |
| |
| |
| |
| long currentTimeMillis = System.currentTimeMillis() / 1000; |
| SafeUtils.getSign(currentTimeMillis) |
| |
| |
| public static String getSign(long j) { |
| try { |
| MessageDigest instance = MessageDigest.getInstance("MD5"); |
| String substring = HexDump.toHex(instance.digest(("niaodaifu" + j).getBytes())).substring(12, 30); |
| String substring2 = HexDump.toHex(instance.digest((channel + j).getBytes())).substring(12, 26); |
| return substring + substring2; |
| } catch (Exception unused) { |
| return ""; |
| } |
| } |
| |
| import hashlib |
| |
| |
| def md5(data_string): |
| obj = hashlib.md5() |
| obj.update(data_string.encode('utf-8')) |
| return obj.hexdigest() |
| |
| j = "1687256602" |
| |
| v1 = md5(f"niaodaifu{j}")[12:30] |
| v2 = md5(f"android{j}")[12:26] |
| sign = v1 + v2 |
| print(sign) |



2.2.3 实现代码
| import requests |
| from utils import query_to_dict |
| import time |
| import hashlib |
| |
| |
| def md5(data_string): |
| obj = hashlib.md5() |
| obj.update(data_string.encode('utf-8')) |
| return obj.hexdigest() |
| |
| |
| def get_sign(): |
| t = int(time.time()) |
| v1 = md5(f"niaodaifu{t}")[12:30] |
| v2 = md5(f"android{t}")[12:26] |
| sign = v1 + v2 |
| return sign |
| |
| |
| print(get_sign()) |
| |
| phone = input('请输入手机号:') |
| password = input('请输入密码:') |
| sign = get_sign() |
| print('----',sign) |
| q = 'password=%s&mobile=%s&channel=android&sign=%s&time=%s&mechanism=0&platform=1' % ( |
| password, phone, sign,int(time.time())) |
| data = query_to_dict(q) |
| |
| res = requests.post('https://api.niaodaifu.cn/v4/site/loginnew', json=data, verify=False) |
| print(res.json()) |
| |
2.2 油联合伙人
2.2.1 目标
2.2.2 密码破解操作步骤
| |
| -请求地址:https://chinayltx.com/app/api/v1/partnerLogin/login |
| -请求体: |
| phone 18953675222 |
| password 166acc691782f077c5c7c7c10fa39b1c |
| -请求头: |
| X-App native |
| X-Noncestr 123456 |
| X-OS partnerApp_android |
| X-Req-Time 1687258564222 |
| X-Sign 869a52194c795e272475b4e50d4e80fa |
| X-Token |
| X-UserID |
| Content-Type application/x-www-form-urlencoded |
| Content-Length 59 |
| Host chinayltx.com |
| Connection Keep-Alive |
| Accept-Encoding gzip |
| User-Agent okhttp/3.10.0 |
| |
| 根据 请求地址搜索: partnerLogin/login |
| |
| |
| @FormUrlEncoded |
| @POST("api/v1/partnerLogin/login") |
| Observable<HttpResult<LoginInfo>> submitLogin(@Field("phone") String str, @Field("password") String str2); |
| |
| |
| |
| |
| @Override // com.yltx.oil.partner.mvp.domain.UseCase |
| public Observable<HttpResult<LoginInfo>> buildObservable() { |
| return this.mRepository.loginWithToken(this.name, this.pwd); |
| } |
| |
| |
| public void submitLogin(String str, String str2) { |
| this.mLoginUseCase.setName(str); |
| this.mLoginUseCase.setPwd(Md5.md5(str2)); |
| this.mLoginUseCase.execute(new LoginSubscriber(this.view)); |
| } |
| |



2.2.3 签名的破解步骤
| |
| |
| |
| public Headers getRequestHeaders(Headers headers) { |
| Headers.Builder newBuilder = headers.newBuilder(); |
| newBuilder.add(PARAM_APP, this.appType); |
| newBuilder.add(PARAM_NONCESTR, this.noncestr); |
| newBuilder.add(PARAM_OS, this.clientType); |
| newBuilder.add(PARAM_REQ_TIME, this.reqTime); |
| newBuilder.add(PARAM_SIGN, this.sign); |
| newBuilder.add(PARAM_TOKEN, this.token); |
| newBuilder.add(PARAM_USER_ID, this.userId); |
| return newBuilder.build(); |
| } |
| |
| private String sign(String str) { |
| return Md5.md5(this.token + this.reqTime + this.noncestr.substring(2) + str).toLowerCase(); |
| } |
| |
| |
| import hashlib |
| |
| token = "" |
| reqTime = "1657201079926" |
| nonce_str = "123456" |
| nonce_str_sub_2 = nonce_str[2:] |
| body_string = "phone=18630099999&password=4297f44b13955235245b2497399d7a93" |
| |
| encrypt_string = f"{token}{reqTime}{nonce_str_sub_2}{body_string}" |
| |
| obj = hashlib.md5() |
| obj.update(encrypt_string.encode('utf-8')) |
| res = obj.hexdigest() |
| print(res) |
| |

2.2.4自动登录代码如下
| import requests |
| import hashlib |
| import time |
| |
| phone = input('请输入手机号') |
| password = input('请输入密码') |
| |
| |
| def get_md5(data_string): |
| obj = hashlib.md5() |
| obj.update(data_string.encode('utf-8')) |
| return obj.hexdigest() |
| |
| |
| password = get_md5(password) |
| data = { |
| 'phone': phone, |
| 'password': password |
| } |
| token = '' |
| req_time = str(int(time.time() * 1000)) |
| nonce_str = "123456" |
| nonce_str_sub_2 = nonce_str[2:] |
| body_string = f"phone={phone}&password={password}" |
| sign = encrypt_string = f"{token}{req_time}{nonce_str_sub_2}{body_string}" |
| sign = get_md5(encrypt_string) |
| |
| header = { |
| "X-App": "native", |
| "X-Noncestr": nonce_str, |
| "X-OS": "partnerApp_android", |
| "X-Req-Time": req_time, |
| "X-Sign": sign, |
| "X-Token": token, |
| "X-UserID": "" |
| } |
| res = requests.post('https://chinayltx.com/app/api/v1/partnerLogin/login', data=data, verify=False, headers=header) |
| |
| print(res.text) |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)