当前位置: 首页 > news >正文

JS逆向进阶篇【去哪儿旅行登录】【下篇-逆向Bella参数JS加密逻辑Python生成】

目录:

  • 每篇前言:
  • 引子——本篇目的
  • 1、 代码混淆和还原
    • (1)单独替换:
    • (2)整个js文件替换:
  • 2、算法入口分析
  • 3、 深入分析
      • (0)整体分析:
      • (1)_0x4dd553:
      • (2)_0x15c356:
      • (3)_0x4fb8ac:
      • (4)_0x34877a:
      • (5)_0x5ad2bb:
      • (6)_0xc21476:
      • (7)_0x34c54c:
      • (8)至此,结束:
  • 4、Python还原算法
  • 5、整体测试

每篇前言:

  • 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者

  • 🔥🔥本文已收录于爬虫进阶+实战系列教程专栏:《爬虫进阶+实战系列教程》
  • 🔥🔥热门专栏推荐:《Python全栈系列教程》、《爬虫从入门到精通系列教程》、《爬虫进阶+实战系列教程》、《Scrapy框架从入门到实战》、《Flask框架从入门到实战》、《Django框架从入门到实战》、《Tornado框架从入门到实战》、《前端系列教程》。
  • 📝​📝本专栏面向广大程序猿,为的是大家都做到Python全栈技术从入门到精通,穿插有很多实战优化点。
  • 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
  • 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

在这里插入图片描述

引子——本篇目的

在中篇其实已经通过补浏览器环境的方式破解出了bella参数,但是如果补浏览器环境不行的时候该怎么办呢?
这就得一点点扣js了!
所以,本篇文章来扣一波!
逆向分析出bella参数的加密算法,全部基于Python来实现!!!

1、 代码混淆和还原

分析这个js文件,有很多形如_0x5a69('0x0')_0x5a69('0x1')这样的代码,其实这些最终得到的就是一个个对应的字符串。

很入门级的代码混淆,这时候要做的就是尝试解混淆,将这个js文件中这样的代码替换为对应的字符串,这样看着就会直观了!
在这里插入图片描述

上述红框部分就是代码混淆的实现逻辑;而下述整个try部分就是整个加密逻辑。

【很明显,这些最终的字符串,即上图红框中那个大数组中的值,都经过base64加密~】

(1)单独替换:

解这种混淆也非常简单,我们直接执行对应的函数,如_0x5a69('0x0')就可以得到其对应的字符串:
在这里插入图片描述

在这里插入图片描述
pyexecjs执行:
在这里插入图片描述

(2)整个js文件替换:

只需要处理整个try部分代码(放到js3.js文件中)即可~

import reimport execjswith open('js2.js', 'r') as f:JS = execjs.compile(f.read())res = JS.call("_0x5a69", "0x0")print(res)with open("js3.js", 'r', encoding='utf-8') as f1, open("js4.js", 'w', encoding='utf-8') as f2:for line in f1:match_list = re.findall(r"_0x5a69\(.*?\)", line)if not match_list:f2.write(line)continuefor mt_str in match_list:try:# arg = str(re.findall(r"\('(.*?)'\)", mt_str)[0])arg = mt_str[9: -2]line = line.replace(mt_str, f'"{JS.call("_0x5a69", arg)}"')except Exception as e:passf2.write(line)print(line.strip())

上述代码try的作用:

  • 这个js代码这么多,上述简单的替换逻辑肯定会有报错的时候,但是报错又没事,何必一个个扣报错,然后完善逻辑呢?
    等下面具体分析这部分js代码的时候,如果分析到了未替换成功的代码块,手动单独替换下不更方便吗?

2、算法入口分析

直接分析处理后的js文件即可~
在这里插入图片描述
在这里插入图片描述

分析,形参_0x29235d接收的是slideToken:
在这里插入图片描述
但是上一个调用栈其实是传过来了两个参数:
在这里插入图片描述
这就是JavaScript的一个神奇之出,当传给js函数的参数多于js函数的形参时并不会报错,而且在函数内部可以通过arguments加索引的方式取得对应的参数:

var _0x5d0961 = arguments["length"] > 0x1 && arguments[0x1] !== undefined ? arguments[0x1] : '';

所以上述这个三元运算就会赋值{v: 2}_0x5d0961

继续分析:
在这里插入图片描述
执行try的时候,第一句delete删除参数_0x29235d中的Bella,第二句_0x398212(_0x29235d, _0x5d0961)就是生成Bella的函数;
如果捕获到异常,就直接返回_0x2e61cb,而这是个固定值,我直接将Bella写死为这个值,也是没问题的!
【为啥会有这种奇怪的代码,直接写死就可以,这不就是个漏洞吗?
这是因为核心加密逻辑可能需要读取各种浏览器参数,而浏览器千千万,有些浏览器也许不适配,那么就会报错,但是不能影响到用户使用,所以就有了这个try】
下面深入剖析Bella的加密逻辑:

3、 深入分析

(0)整体分析:

在这里插入图片描述
分析都在注释:
在这里插入图片描述

在这里插入图片描述

(1)_0x4dd553:

var _0x4dd553 = _0x318499(_0x481ca8);

入参是:{slideToken: "80ed997a295a75f57e6d8cbe88d77a8b"}
结果是:

{"bParam": "80ed997a295a75f57e6d8cbe88d77a8b","keyArray": ["slideToken"]
}

(2)_0x15c356:

var _0x15c356 = (0x0, _0x5b06ff["default"])();解读:
var _0x15c356 = _0x5b06ff["default"]();

对应js函数:

function _0x9beb5a() {var _0x2bb251 = document[_0x5a69('0xf9')](_0x5a69('0xfa'));var _0x4ba4c2 = _0x2bb251 && _0x2bb251[0x0] && _0x2bb251[0x0][_0x5a69('0xfb')];var _0x5a5787 = document['getElementsByName'](_0x5a69('0xfc'));var _0x4030ec = _0x5a5787 && _0x5a5787[0x0] && _0x5a5787[0x0][_0x5a69('0xfb')];var _0x5a2ba8 = document[_0x5a69('0xfd')];return [{'key': _0x5a69('0xfe'),'value': document['referrer'][_0x5a69('0xb7')]('?')[0x0][_0x5a69('0xd4')](/^http(s)?:\/\//, '')[_0x5a69('0xff')](0x0, 0x14) || ''}, {'key': _0x5a69('0x100'),'value': _0x89ccfe()}, {'key': _0x5a69('0x101'),'value': window['shirley'] || _0xd6c5e7[_0x5a69('0x8a')]['string']}, {'key': _0x5a69('0xfd'),'value': _0x5a2ba8 && _0x5a2ba8['slice'](-0xa) || _0xd6c5e7[_0x5a69('0x8a')][_0x5a69('0xcb')]}, {'key': _0x5a69('0xfa'),'value': _0x4ba4c2 && _0x4ba4c2[_0x5a69('0x1f')](-0xa) || _0xd6c5e7[_0x5a69('0x8a')]['string']}, {'key': _0x5a69('0xfc'),'value': _0x4030ec && _0x4030ec[_0x5a69('0xff')](0x0, 0x14) || _0xd6c5e7['default'][_0x5a69('0xcb')]}, {'key': _0x5a69('0x102'),'value': window[_0x5a69('0xd0')][_0x5a69('0x102')][_0x5a69('0xd4')](/^http(s)?:\/\//, '')[_0x5a69('0xff')](0x0, 0x14) || _0xd6c5e7[_0x5a69('0x8a')][_0x5a69('0xcb')]}, {'key': _0x5a69('0x103'),'value': _0x1916ab() || _0xd6c5e7[_0x5a69('0x8a')][_0x5a69('0xcb')]}];}

在这里插入图片描述

在这里插入图片描述
分析piccolo:

在这里插入图片描述

在这里插入图片描述
生成_0x113a55中随机16个字符拼接而成的字符串~

此参数结果:

[{"key": "referer","value": ""},{"key": "piccolo","value": "5879##420347A09BF3F723##1708962151096"},{"key": "shirley","value": "unknown"},{"key": "title","value": "unknown"},{"key": "keywords","value": "unknown"},{"key": "description","value": "unknown"},{"key": "host","value": "user.qunar.com"},{"key": "scriptSrc","value": ["qimgs.qunarzz.co","q.qunarzz.com/ho"]}
]

(3)_0x4fb8ac:

此参数结果:

{"referer": "","piccolo": "5879##420347A09BF3F723##1708962151096","shirley": "unknown","title": "unknown","keywords": "unknown","description": "unknown","host": "user.qunar.com","scriptSrc": ["qimgs.qunarzz.co","q.qunarzz.com/ho"]
}

(4)_0x34877a:

var _0x34877a = (0x0, _0xd98ca5["default"])();

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

生成_0x24b4d9中随机21个字符拼接而成的字符串~
此参数结果:

dWre6Dts7TLT1O2GkSeTZ

(5)_0x5ad2bb:

var _0x5ad2bb = _0x4dd553["bParam"] + _0x34877a + JSON["stringify"](_0x4dd553['keyArray']);

唯一注意的就是JSON["stringify"](_0x4dd553['keyArray'])的值是["slideToken"]

此参数结果:

3d8b8860db2bf9a6aef7f872979113dedWre6Dts7TLT1O2GkSeTZ["slideToken"]

(6)_0xc21476:

var _0xc21476 = _0x5625ac['default']["signature"](_0x5ad2bb);

在这里插入图片描述

很明显是将入参_0x5ad2bb使用sha1加密,最终将结果转换为十六进制字符串。
加密秘钥16进制表示为:
在这里插入图片描述
Python实现:

import binascii
import hmac
from hashlib import sha1key_str = '68386673614b337771652b696f4d7673'
key = binascii.a2b_hex(key_str)
data = 'b363b3f511bf0e3e556c29cb56dcf4c9hLHNl1SVxE8UR2ONt1-N9["slideToken"]'hmac_code = hmac.new(key, data.encode('utf-8'), sha1)
res = hmac_code.hexdigest()
print(res)

此参数结果:

df95bd703794a4cc96e611da8a53b87f2aadcb40

(7)_0x34c54c:

var _0x34c54c = (0x0, _0x38cd63["default"])(JSON["stringify"](_0x4fb8ac), _0x3d0fe0["default"]);等价于:var _0x34c54c = _0x38cd63["default"](JSON["stringify"](_0x4fb8ac), _0x3d0fe0["default"])
  • 函数第一个参数:
    将上述得到的_0x4fb8ac序列化;
  • 函数第二个参数:
    多次测试为固定值:
["B6F1YrNm+OA=sw","n8xbeLlzQ","p5M02SUHt/dog","cyfj-9kPKu","EX7VWaqJi","3CIGDRhTv4"
]

分析此函数:
在这里插入图片描述
看看_0x21da9c函数:
在这里插入图片描述
内部又调用_0x2d06ba函数,先来看看第一个参数:

_0x1414cd["charCodeAt"]()['toString'](0x2)

获得传进来的参数的unicode编码,toString后得到对应二进制字符串。

在这里插入图片描述
多次调试可发现_0x2d06ba函数的作用就是对传进来的第一个参数左边补0达到八位。

继续看_0x26cf34函数:
在这里插入图片描述
在这里插入图片描述
上述使用js列表的some方法,会对列表中的每个值执行给定函数,但凡有一个返回True则整体为True。

window["location"]["href"]
获取浏览器当前url。再.include("x")就是判断浏览器当前url中是否含有x。

在这里插入图片描述

(8)至此,结束:

拓展:js字符串和数组拼接知识点~
在这里插入图片描述

在JavaScript中,当你使用 + 运算符连接一个字符串和一个数组时,数组会被转换为字符串,并与原始字符串连接。这个过程被称为字符串拼接。

在上图中,"GuHanZhe" 是一个字符串,["Cool"] 是包含一个字符串元素的数组。当它们相加时,JavaScript会将数组转换为字符串,然后进行字符串拼接。这导致了结果 'GuHanZheCool'

4、Python还原算法

import binascii
import hmac
import json
import random
import string
import time
from hashlib import sha1
from urllib.parse import quote_plusdef hmac_sha1(data_string):key_str = "68386673614b337771652b696f4d7673"key = binascii.a2b_hex(key_str)# data_string = 'b363b3f511bf0e3e556c29cb56dcf4c9hLHNl1SVxE8UR2ONt1-N9["slideToken"]'hmac_code = hmac.new(key, data_string.encode('utf-8'), sha1)return hmac_code.hexdigest()def _0x26cf34(_0x4800e6, _0x572efb):_0x5ee954 = ['qunar', 'tujia']_0x403118 = "B6F1YrNm+OA=sw"_0x501116 = "n8xbeLlzQ"_0x3b5454 = "p5M02SUHt/dog"_0x251b31 = "cyfj-9kPKu"_0x222d7d = "EX7VWaqJi"_0x47c310 = "3CIGDRhTv4"_0x3af887 = "".join(_0x572efb) + (_0x403118 + _0x501116 + _0x3b5454 + _0x251b31 + _0x222d7d + _0x47c310);_0x3af887 = list(_0x403118 + _0x501116 + _0x3b5454 + _0x251b31 + _0x222d7d + _0x47c310)_0x4800e6 = quote_plus(_0x4800e6)while len(_0x4800e6) % 0x3 != 0x0:_0x4800e6 += '\x20'_0x933810 = [format(ord(i), "0>8b") for i in _0x4800e6]_0x2e4d85 = []for i in range(0, len(_0x933810), 3):end_index = min(i + 3, len(_0x933810))group = _0x933810[i: end_index]_0x2e4d85.append(group)_0x2a779b = ''for _0x28ee6c in _0x2e4d85:_0x572061 = "".join(_0x28ee6c)_0x351bb8 = []for j in range(0, len(_0x572061), 6):end_idx = min(j + 6, len(_0x572061))_0x351bb8.append(_0x572061[j: end_idx])new_0x351bb8 = []for _0x2a9721 in _0x351bb8:_0x2a9721 = "".join(["0" if char == "1" else "1" for char in _0x2a9721])idx = int(_0x2a9721, base=2)part = _0x3af887[idx]new_0x351bb8.append(part)_0x2a779b += "".join(new_0x351bb8)return _0x2a779bdef run():slide_token = "d8cc3d473f4d895b3af483e122f1ddc061ccb250"_0x4dd553 = {"KeyArray": ["slideToken"], "bParam": slide_token}total_string = string.digits + string.ascii_lettersrandom_string = "".join([random.choice(total_string) for _ in range(16)])_0x4fb8ac = {"referer": "","piccolo": f"{random.randint(1000, 9999)}##{random_string}##{int(time.time() * 1000)}","shirley": "unknown","title": "unknown","keywords": "unknown","description": "unknown","host": "user.qunar.com","scriptSrc": ["qimgs.qunarzz.co", "q.qunarzz.com/ho"]}total_string = '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA'_0x34877a = "".join([random.choice(total_string) for _ in range(21)])_0x5ad2bb = slide_token + _0x34877a + json.dumps(_0x4dd553['KeyArray'])_0xc21476 = hmac_sha1(_0x5ad2bb)_0x4fb8ac["sign"] = _0xc21476_0x4fb8ac["randomNum"] = _0x34877a_0x4fb8ac["t"] = int(time.time() * 1000)_0x572efb = ["B6F1YrNm+OA=sw","n8xbeLlzQ","p5M02SUHt/dog","cyfj-9kPKu","EX7VWaqJi","3CIGDRhTv4"]_0x34c54c = _0x26cf34(json.dumps(_0x4fb8ac, separators=(',', ':')), _0x572efb)june_v = "1683616182042"_0x112026 = june_v + '##' + _0xc21476 + '##' + _0x34c54c + '##' + _0x34877a + '##' + 'slideToken'print(_0x112026)if __name__ == '__main__':run()

在这里插入图片描述

5、整体测试

很简单~

相关文章:

JS逆向进阶篇【去哪儿旅行登录】【下篇-逆向Bella参数JS加密逻辑Python生成】

目录: 每篇前言:引子——本篇目的1、 代码混淆和还原(1)单独替换:(2)整个js文件替换: 2、算法入口分析3、 深入分析(0)整体分析:(1&am…...

【机器学习】生成对抗网络GAN

概述 生成对抗网络(Generative Adversarial Network,GAN)是一种深度学习模型架构,由生成器(Generator)和判别器(Discriminator)两部分组成,旨在通过对抗训练的方式生成逼…...

centos7安装kafka、zookeeper

安装jdk 安装jdk8 安装zookeeper 在指定目录执行下载命令 我是在/newdisk/zookeeper目录下 wget https://archive.apache.org/dist/zookeeper/zookeeper-3.5.8/apache-zookeeper-3.5.8-bin.tar.gz --no-check-certificate下载好后并解压 tar -zxvf apache-zookeeper-3.5…...

基于 STM32U5 片内温度传感器正确测算温度

目录预览 1、引言 2、问题 3、小结 01 引言 STM32 在内部都集成了一个温度传感器,STM32U5 也不例外。这个位于晶圆上的温度传感器虽然不太适合用来测量外部环境的温度,但是用于监控晶圆上的温度还是挺好的,以防止芯片过温运行。 02 问题…...

【比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据】操作批量新增、分页查询(三)

orm框架使用性能比较 比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据 环境: idea jdk17 spring boot 3.0.7 mysql 8.0测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本mybatis☑️☑️3.5.4sqltoy☑️☑️5.2.98lazy✖️☑️1.2.4…...

Leetcode 3068. Find the Maximum Sum of Node Values

Leetcode 3068. Find the Maximum Sum of Node Values 1. 解题思路2. 代码实现 题目链接:3068. Find the Maximum Sum of Node Values 1. 解题思路 这一题虽然标记为一道hard的题目,但其实就是一个脑筋急转弯的题目。 我们只需要想明白一点即可&…...

用 Dockerfile为镜像添加SSH服务

1、基础镜像ubuntu:18.04 2、替换为国内的安装源 3、安装openssh-server 4、允许root用户远程登陆 5、暴露端口22 6、服务开机自启动 1.创建目录 [rootopenEuler-node1 db]# mkdir sshd_ubuntu 2.创建 Dockerfile、 run.sh 、authorized_keys、vim aliyun.list 文件 [rootop…...

Maven能解决什么问题?为什么要用?

如果没有maven,我们在开发一个应用的时候,需要自己先确定要引入哪些第三方的jar包,并且要去找到这些jar包,把他们导入到项目中,而且最痛苦的时候各个jar包之间的兼容性和冲突的问题。 jar包弄好了之后,我们…...

【Golang星辰图】探索网络和HTTP的奇妙世界:使用Go语言打造高性能应用

提升Web开发效率:学会使用Go语言的网络和HTTP库 前言 随着互联网的快速发展,网络和HTTP成为了现代应用开发中必不可少的部分。Go语言作为一门快速、可靠和高效的编程语言,提供了丰富的网络编程和HTTP处理库,使得构建高性能的网络…...

[C语言]——操作符

目录 一.算术操作符:、-、*、/、% 1. 和 - 2.* 3./ 4.% 二.赋值操作符:和复合赋值 1.连续赋值 2.复合赋值符 三.单目操作符:、--、、- 1.和-- 1.1前置 1.2后置 1.3前置-- 2. 和 - 四.强制类型转换 一.算术操作符:…...

iview碰到的一些问题总结

iview tabs嵌套使用问题 tabs嵌套使用的时候不是直接套用行了&#xff0c;直接套用会出现内层tab都集成到一级tab去&#xff0c;需要设置该属性指向对应 Tabs 的 name 字段(需要版本大于3.3.1) <Tabs name"tab1" ><TabPane label"标签1" tab&qu…...

【Python笔记-FastAPI】后台任务+WebSocket监控进度

目录 一、代码示例 二、执行说明 (一) 调用任务执行接口 (二) 监控任务进度 实现功能&#xff1a; 注册后台任务&#xff08;如&#xff1a;邮件发送、文件处理等异步场景&#xff0c;不影响接口返回&#xff09;监控后台任务执行进度&#xff08;进度条功能&#xff09;支…...

力扣hot100:15.三数之和(双指针/哈希表)

分析&#xff1a; 三数和问题&#xff0c;这里和两数之和不一样&#xff0c;返回的是值&#xff0c;因此可以对其进行排序&#xff0c;使用双指针。 一、一层循环双指针 class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {sort…...

VMware虚拟机使用Windows共享的文件夹

虚拟机版本为 VMware Workstation 16 Pro:16.2.4&#xff1b;主机位Windows11&#xff1b;记录于2024-03-05   在个人使用时&#xff0c;经常会有一些数据集等大文件重复在不同实验中使用&#xff0c;但是不同系统中来回使用会导致占用虚拟机空间&#xff0c;该博文通过将主机…...

利用Python自动化日常任务

在快节奏的现代生活中&#xff0c;时间就是一切。幸运的是&#xff0c;Python提供了一系列强大的库和工具&#xff0c;可以帮助我们自动化那些乏味且重复的任务&#xff0c;从而释放我们的时间&#xff0c;让我们可以专注于更有创造性和有意义的工作。下面&#xff0c;我们将探…...

Android的多线程和异步处理

在Android开发中&#xff0c;多线程和异步处理是处理耗时操作、提高应用响应性和性能的关键技术。以下是一些关于Android多线程和异步处理的基本概念和实践&#xff1a; 1. **主线程&#xff08;UI线程&#xff09;**&#xff1a; - Android应用的主线程负责处理UI操作和事…...

MySQL-----视图

一 视图 ▶ 介绍 视图view是一个虚拟表&#xff0c;非真实存在&#xff0c;其本质是根据SQL语句获取动态的数据集&#xff0c;并为其命名&#xff0c;用户使用时只需使用视图名称即可获取结果集&#xff0c;并可以将其当作表来使用。 数据库中存放了视图的定义&…...

LeetCode-02

225. 用队列实现栈 用两个队列实现栈的功能&#xff0c;思路如下&#xff1a; 往空队列中放新元素把非空队列中的元素依次放入刚才添加了新元素的队列&#xff0c;直到非空队列变为空队列 class MyStack(object):def __init__(self):self.queue1 []self.queue2 []def push(…...

瑞_Redis_Redis的Java客户端

文章目录 1 Redis的Java客户端1.1 Jedis快速入门1.1.1 入门案例1.1.1.1 项目构建1.1.1.2 引入依赖1.1.1.3 建立连接1.1.1.4 释放资源1.1.1.5 测试1.1.1.6 完整测试类代码 1.1.2 Jedis连接池1.1.2.1 连接池工具类1.1.2.2 改造原始代码 1.2 SpringDataRedis1.2.1 RedisTemplate1.…...

Cmake的使用

第一步&#xff1a;安装Cmake 双击点开即可&#xff0c;无脑下一步。 第二步&#xff1a;编写一个简单的Cmake项目 CMakeLists.txt文件 # 设置最低的 CMake 版本要求 cmake_minimum_required(VERSION 3.10)# 设置项目名称 project(MyProject)# 添加可执行文件 add_executabl…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...