首页 > 其他分享 >day04-逆向基础案例

day04-逆向基础案例

时间:2023-10-17 14:45:35浏览次数:42  
标签:逆向 res print day04 案例 str imei password data

一 抓包逆向案例

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 补充(请求参数转字典,请求头转字典)

# 今日南川app登录

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))



### 请求头转字典
def header_str_to_dict(header_str):
    res = [item for item in
           header_str.split('\n')]  # ['user-agent	chuangqi.o.137.com.iqilu.app137/0.0.28.108','accept	*/*']
    # print(res)
    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
# 自行找收费的,注意别被骗,收费的都会带api接口

image-20231017141547103

1.2 爱安丘.apk

1.2.1 目标

#1 发送验证码登录(抓包)
#2 用户名密码登录(反编译,逆向加密函数)
# 注意:新版爱安丘加入了客户端证书校验,无法抓包,解决方案:LSposed + JustTrustMe
	-官网下载:LSposed https://github.com/LSPosed/LSPosed/releases
    -使用面具刷入
    -安装JustTrustMe
    -开启重启即可

1.2.2 IMEI

IMEI(International Mobile Equipment Identity)是【国际移动设备识别码】的缩写,它是一个唯一标识符,用于识别移动设备,如手机、平板电脑等。IMEI由15位数字组成,每一位都有特定的含义

# IMEI的规则如下:
前六位(TAC):型号核准号码,用于识别设备的制造商和设备类型。
接下来的两位(FAC):最终装配代码,表示设备的最终装配站。
后面的六位(SNR):串号,表示设备的序列号。
最后一位(SP):校验位,用于验证IMEI的有效性


def generate_imei():  # 跟useragent类似,要变换一下
    # # 生成随机的TAC(前六位)
    tac = ''.join(random.choices('0123456789', k=6))

    # 生成随机的FAC(接下来的两位)
    fac = ''.join(random.choices('0123456789', k=2))

    # 生成随机的SNR(后面的六位)
    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 = imei_base + str((10 - check_digit) % 10)

    return imei
    # return "".join(random.choices('0123456789abcdef', k=15))

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)

image-20231017141939683

image-20231017141947038

image-20231017142004718

image-20231017142016142

image-20231017142034492

hook.py

####1 手机端启动frida-serve
adb shell
su
cd /data/local/tmp/
ls
./frida-server-16.0.19-android-arm64 

####2 设置端口转发
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

# 3 前台运行的包名

  # 枚举手机上的所有进程 & 前台进程
  import frida
  # 获取设备信息
  rdev = frida.get_remote_device()
  # 枚举所有的进程
  processes = rdev.enumerate_processes()
  for process in processes:
      print(process)
  # 获取在前台运行的APP
  front_app = rdev.get_frontmost_application()
  print(front_app)
##############################

# 4 hook

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(前六位)
    tac = ''.join(random.choices('0123456789', k=6))

    # 生成随机的FAC(接下来的两位)
    fac = ''.join(random.choices('0123456789', k=2))

    # 生成随机的SNR(后面的六位)
    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 = imei_base + str((10 - check_digit) % 10)

    return imei
	# return "".join(random.choices('0123456789abcdef', k=16))


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):
    # 创建 AES 密码对象
    # cipher = AES.new(key, AES.MODE_CBC, iv)
    # 密钥(16 字节)
    key = b'6d6656a37cdb7977c10f6d83cab168e9'
    # 初始化向量(16 字节)
    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'))
    # qV+iHZqcr+cEWpKgOoDx8g==
    # qV+iHZqcr+cEWpKgOoDx8g==

二 抓包反编译案例

2.1 X大夫

2.1.1 目录

# 模拟登录

2.1.2 操作步骤

#1 请求地址
https://api.niaodaifu.cn/v4/site/loginnew
#2 请求体
devisetoken	1507bfd3f6dd1eafc0f
password	lqz12345
mobile	18953675222
channel	android
sign	afc1963626ccdb43d5b394017b206144
time	1687255476
mechanism	0
platform	1

#3 感觉,需要逆向的请求体中的字段devisetoken和sign,去掉devisetoken重新发包,发现正常响应,所以只需要逆向sign

#4  jadx打开X大夫

#5  搜索内容是:"sign"
#6 核心代码如下
# 获取当前秒级别的时间戳
    long currentTimeMillis = System.currentTimeMillis() / 1000;
    SafeUtils.getSign(currentTimeMillis)

# 6 代码如下 SafeUtils.getSign
   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 "";
        }
    }
# 7 转成python 代码为:
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)

image-20231017142209424

image-20231017142223207

image-20231017142233307

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 密码破解操作步骤

# 1 抓包
	-请求地址: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
 # 2 逆向
	根据 请求地址搜索: partnerLogin/login
    
 # 3 代码如下(使用了Retrofit2 模块,发送请求的,@ 是java的注解)
    @FormUrlEncoded
    @POST("api/v1/partnerLogin/login")
    Observable<HttpResult<LoginInfo>> submitLogin(@Field("phone") String str, @Field("password") String str2);
 # 4 只要 类名.submitLogin("18953675222","lqz12345"),就会向api/v1/partnerLogin/login发送请求,使用FormUrlEncoded编码格式
# 5 查找用例submitLogin
# 6 找到loginWithToken---》使用查找用例找不到,直接全局搜索
# 7 找到buildObservable
 	@Override // com.yltx.oil.partner.mvp.domain.UseCase
    public Observable<HttpResult<LoginInfo>> buildObservable() {
        return this.mRepository.loginWithToken(this.name, this.pwd);
    }

# 8 查找密码设置位置
   public void submitLogin(String str, String str2) {
        this.mLoginUseCase.setName(str);
        this.mLoginUseCase.setPwd(Md5.md5(str2));
        this.mLoginUseCase.execute(new LoginSubscriber(this.view));
    }
# 9 确认是md5

image-20231017142543676

image-20231017142552971

image-20231017142618168

2.2.3 签名的破解步骤

# 1 搜索 X-Sign
# 2 当前类中找哪里使用:private static final String PARAM_SIGN = "X-Sign";
# 3 找到getRequestHeaders方法
    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();
    }
# 4 根据this.sign 找到
 private String sign(String str) {
        return Md5.md5(this.token + this.reqTime + this.noncestr.substring(2) + str).toLowerCase();
    }

# 5 使用python编写
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)

image-20231017142732662

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)

标签:逆向,res,print,day04,案例,str,imei,password,data
From: https://www.cnblogs.com/hanfe1/p/17769627.html

相关文章

  • app逆向day03-反编译工具和hook框架
    一反编译工具1.1常见反编译工具常见的反编译工具:jadx(推荐)、jeb、GDA反编译工具依赖于java环境,所以我们按照jdk1.2JDK环境安装#官方地址:(需要注册-最新java21)https://www.oracle.com/java/technologies/downloads/1.2.1win平台安装#1下载jdk-8u371-windows-x64.e......
  • 【0-1】从0.1开始学Android逆向-APK基本结构概要分析
    概要最近在进行Android的逆向,在这里整理知识点和分享Android逆向知识。如果文章中有任何勘误,诚挚的邀请师傅们批评改正!0.什么是逆向?逆向工程(ReverseEngineering)是一种分析和解剖已有产品、系统或软件的过程,以了解其内部工作原理、设计、功能或源代码。逆向工程可以应用于多个......
  • 【1.0】Js逆向补充之Js混淆
    【一】什么是Js混淆JavaScript混淆是一种将JavaScript代码进行某种处理的方式,目的是使代码难以被阅读和理解。whydothat?JavaScript大都是运行在浏览器端,这就导致任何人都可以直接对网站的代码进行查看如果代码没有进行任何处理就会导致直接暴露源码,他人便可轻而易......
  • 【2.0】Js逆向补充之Ob混淆
    【一】什么是Ob混淆OB混淆是指将JavaScript代码中的变量名、函数名、字符串等替换为无意义的字符串,从而增加代码的保护性和防止代码的逆向分析。此外,它还可以在代码中添加死代码、无用的函数等,增加代码的复杂度和难以理解性,从而增加代码的保密性。官网:https://obfuscato......
  • java实现大文件多线程上传案例
    当机器内存大小为4G,需要上传一个大小为50G的文件时,为了避免内存溢出,可以采用分片上传的方式,即将大文件切分成多个小片段进行并发上传。以下是一个详细的方案和代码实现示例:方案说明:将大文件切分成多个大小适当的片段(例如每个片段大小为100MB)。创建一个线程池来管理并发上传任务,......
  • Python爬虫:抖音 JS XB逆向解析
    哈喽兄弟们,抖音现在有JS加密,以前的方法爬不了饿了,今天来实现一下某音短视频的JS逆向解析。知识点动态数据抓包`在这里插入代码片`requests发送请求X-Bogus 参数逆向环境模块python 3.8               运行代码pycharm 2022.3           辅......
  • google gtest框架入门使用案例
    通过本文可以收获:googlegtest急速入门、googlegtest资源网站。googlegtest是什么googlegtest是谷歌开源的c++单元测试框架,非常的好用。起码个人感觉和springboot自带的测试框架功能差不太多。安装略过,请参考:GitHub-google/googletest:GoogleTest-GoogleTesting......
  • LeetCode Day04 24&19&02.07&142
    24. 两两交换链表中的节点这题使用虚拟头结点会更好做,因为有虚拟头结点我们交换结点的时候步骤会更加清晰。操作此类有指针类型的题目要注意:1.画图避免混乱2.注意指针先后顺序classSolution{publicListNodeswapPairs(ListNodehead){ListNodedumyhea......
  • 总结整合案例前端页面展示+axios异步请求数据
    页面显示: vue+axios+element<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title&g......
  • Spring Cloud建筑工地智慧平台源码,自主版权+实际应用案例
    建筑工地智慧平台源码,施工管理端、项目监管端、数据大屏端、移动APP端全套源码技术架构:微服务+Java+SpringCloud、Vue+UniApp+MySql+自主版权+实际应用案例+演示   建筑工地智慧平台已应用于线上巡查、质量管理、实名制管理、危大工程管理、运渣车管理、绿色施工、视频监......