首页
留言
动态
归档
推荐
音乐
工具
Search
1
Emby公益服-上万部电影电视剧免费看
62,710 阅读
2
openwrt-docker部署lxk0301京东自动签到脚本
12,596 阅读
3
QuantumultX-京东签到撸京东豆
10,969 阅读
4
LXK0301京东签到脚本-自动提交互助码
9,356 阅读
5
微信-域名被封监测以及自动更换被封域名
9,022 阅读
随便写写
科学上网
Web开发
瞎折腾
Search
标签搜索
quantumultx
laravel
openwrt
laravel nova
laradock
telegram
薅羊毛
google adsense
jd_scripts
京东签到
ubuntu
oh-my-zsh
web开发环境
nginx
工具
shadowsocks shadowsocksR
RBAC
权限管理
内网穿透
Python
orzlee
累计撰写
44
篇文章
累计收到
595
条评论
首页
栏目
随便写写
科学上网
Web开发
瞎折腾
页面
留言
动态
归档
推荐
音乐
工具
搜索到
28
篇与
瞎折腾
的结果
2023-04-04
探索ChatGPT、NewBing和Google Bard:我与大型语言模型的初体验
前言 最近ChatGPT很火爆,不过我还是近几天才知道,平时也没怎么看新闻,有点孤陋寡闻了!既然都发布了那我也来试试看人工智能到底有多智能!这不,一口气体验三款AI,chatGP、Bing AI,还有Google Bard。 一个ChatGPT出来,后面就会有千千万万个ChatGPT如脱缰野马般涌现,那么那些跟趋势蹭流量的ChatGPT到底是人工智能还是"人工智障"? 注册ChatGPT 刚接触到ChatGPT那就不得不提注册了。虽然注册也没什么难点,但是还是有限制,例如你的IP、手机号码等。当然伟大的国人总是能想到各种方法来解决问题。 IP问题科学上网就行了,我还是推荐多使用欧美地区节点,香港都不行,和大陆一视同仁了,唉~~~! 注册也没什么难点,主要是短信验证,对号码有要求,国内、香港的反正是不行的,只能用其他国家。电话验证接码我使用的是sms-activate 【链接包含我的Ref,介意的话不要点击】,当然有很多选择,这个倒是无所谓。openai好像也只是用来验证你是真人,也没看见那里能设置或修改电话,目前来说应该是没有什么其他用途。 sms-activate必须要充值后才能使用,充值支持支付宝、银联卡等。 点击右上角充值: 选择支付宝即可,当然也可以用银联卡,什么方便用什么: 充值完了就可以选号码开始注册了,在右边搜索openai: 选择印度尼西亚(你可以试试其他的,但是不保证能收到验证码,没收到码一般也不会扣费),一般在openai验证手机号时等个3-5分钟,如果还没有接收到验证码,就可以X掉再换一个号码了,没收到验证码是会把扣费返还的: 他们甚至都为其出了官方教程:sms-activate注册openAI。 注册openai后就可以正常使用了,chatGPT-web版是免费的。听说是有次数限制的,这两天使用还是没有触碰到上限。 体验ChatGPT chatGPT-web版在对话中经常出现错误的情况,之前我以为是访问人数太多导致,这两天换了一个相对稳定的翻墙节点后稳定许多,否则会一直出错,需要刷新网页才能恢复,非常难受。 ChatGPT自然语言处理非常出色,精通多国语言,非常流利。最让人惊讶的是上下文关联,每次对话都会结合本轮对话上下文做出回答。 打个比方,你先问它"乔布斯是谁",再问它"他对苹果公司有什么贡献",这里的【他】是指我上一次问题里面的"乔布斯"。别小看了上下文关联以为很简单,其实对于提取上下文里面与本次对话有关联的关键词是非常困难的。这就类似于人类的记忆功能,你和刚会说话的小朋友对话时,他就可能经常出现"丢失上下文关联",不理解你说的是指什么。 它甚至都能写论文、诗词、程序,在编程开发中,遇到BUG、异常它都能给出可能涉及的问题。这可比在搜索引擎里面一个个翻找答案的效率可快多了。何况中文垃圾站真是一片一片的,大大降低效率。提供给它的任何日志,让它总结分析,它都说得头头是道,有理有据。这确实在某些情况下对我有很大的帮助。 目前网上也出现了很多Chrome浏览器的ChatGPT扩展,总体来说体验还是不够好。 一些基于web获取chatGPT-web版的Cookie和Token,在chatGPT-web版中对话都经常断线要刷新网页才能继续,放到扩展中也一样断线,体验非常不好。 还有一种基于OpenAI-API,这种体验非常好,但是OpenAI-API收费。目前注册ChatGPT账号有5美金的体验金,而OpenAI-API的收费是按照字数来收取的,称之为Token,以下是价格: 关于token消耗,以下引用ChatGPT3.5回答: 在 OpenAI API 中,每个模型的 Token 数量限制是不同的,因此“1,000 tokens 约等于 750 个单词”这个说法的具体计算方式也可能因模型而异。一般来说,这种说法是根据一个平均单词长度为五个字符的假设得出的。在这种情况下,一个包含 1,000 个 Token 的输入文本大约包含 200 个单词。而根据英语写作的经验,每个单词的平均长度约为 4-6 个字符,因此约 200 个单词的文本约有 750 到 1,200 个字符,这就是通常将 1,000 个 Token 与 750 个单词联系起来的原因。但需要注意的是,这只是一个大致的估计,并不适用于所有情况。 这个token是双向计费,你提问的字数和AI回答的字数都是会消耗掉token的(包括标点符号等一系列其他符号)。虽然GPT3.5 1000Token只需要0.002美金,但是1000Token消耗非常快,特别是中文字符。如果使用上下文关联,需要用到会话ID,那本次对话所关联的会话也会再算一次token,你想想这个消耗有多大。个人使用都能感觉到肉疼,但是公开使用那就更不用说了。你看现在网上大把的免翻墙免费用ChatGPT的那些,如果真是ChatGPT API搭建,然后免费给你用,你觉得现在还有这种"好心人"吗?如果不是ChatGPT,那它是个什么东西相信大家都应该想得到! 目前我在使用的Chrome浏览器扩展只有一款,chatGPTBox,相对于其他的体验比较好,而且开源。目前划词功能、配合搜索引擎比较实用,其他的我觉得也还好,使用情况不多。有兴趣可以点进去看看。 ChatGPT还有Plus版,可以抢先体验新功能,目前plus版可以使用GPT4: 我目前还没有去体验Plus版,chatGPT-web版使用的比较少,但是我准备使用openAI API,所以弄了张美国虚拟信用卡用来绑定。目前国内推荐的虚拟信用卡大多都是depay和nobepay。免费版在高峰期会提示We're experiencing exceptionally high demand. Please hang tight as we work on scaling our systems.,需要刷新网页更频繁,plus应该会好许多,但是我没用过也不能确定。 起初我想使用depay,无奈连个像样的官网都没有,注册也有BUG,我发送验证码始终没有反应。而且充值有点麻烦。有手续费、月费、不想实名需要10美金卡费。 nobepay注册需要邀请码,这个邀请码自己上网找找,我也是网上找的 (989B08,用不了的话自己上网找找吧),没有还注册不了。 需要实名认证,注册时微信ID那一栏一定要已经实名认证的微信,到时候充值和实名认证都是要用该微信。 注册时最低充值500RMB,支付宝充值有1%手续费,开卡有手续费和最低充值金额(每张卡可能不一样)。充值的RMB,开卡是扣费也要选择RMB账户,汇率偏高,我开卡时汇率时6.8,他那边显示7.0!556766卡段开卡要充值最低30美金,需要扣除手续费、开卡费、汇率转换差不多2.X美金。556766卡段能绑定openai,开卡时地址找找美国免税州地址,网上搜搜美国地址生成器,生成一个即可,信用卡姓名可自定义。 openai使用的是Stripe收款,开卡时需要注意,你的ip最好是信用卡开卡国的,否则大概率被拒绝。如果你使用nobepay 556766卡段,选美国节点去绑定,一般是没有什么问题的。 目前支持卡段(已验证): OpenAI/ChatGPT Plus 支持的卡段: 591393 ( DePay ) 556766 ( NobePay ) OpenAI/ChatGPT Plus 不支持的信用卡: 国内招行 VISA/MASTERCARD 、全币卡 全球付香港虚拟卡 万里汇香港虚拟卡 绑定成功后一般是从信用卡 PENDING 5美金,然后每月有账单,用多少扣多少!先用后付。 体验NEW BING Bing在众多搜索引擎中一直不怎么起眼,毕竟Google才是大头。虽然Google搜索引擎早已涉及自然语言AI领域,但是却是微软的Bing AI先出来。 微软在早期忽略搜索引擎,自家的IE也是爱用不用的态度,直到Google的出现,无论是搜索引擎还是浏览器,那个曾经有巨大优势的微软反应过来才发现已经被人家甩得太远。而微软近几年的操作一直在布局,从收购Github,组建Azure云服务, 投资OpenAI实验室,直到今天ChatGPT,微软在AI领域已经走在了前面。 Bing AI相对于ChatGPT最大的优势就是拥有互联网能力,目前的Bing AI使用GPT4模型,并且结合自家搜索引擎能更快更好的找到答案。Google虽然借助自然语言处理来完善搜索引擎,但是返回的大量搜索结果中去找答案还是非常耗时的,而Bing AI却已经缩短了从搜索结果中到找到答案之间的时间,这让Google搜索引擎感受到了压力。 在和Bing AI对话时发现,对于已知问题它会直接给你答案,未知问题,它会通过搜索引擎去结果中总结答案。可惜也需要科学上网才能使用。总体体验相对于chatGPT-web版反应稍慢,有可能时因为使用GPT4模型的关系。 Bing AI必须使用自家的Edge浏览器,不过可以通过修改请求User Agent来模拟Edge。Chrome浏览器可以使用ModHeader扩展来修改: Edge浏览器user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.57 你甚至可以添加X-Forwarded-For头部然后指定国外IP来免除科学上网,但毕竟不是长久之计。 Bing AI虽然可以联网进行搜索,但是表现起来比ChatGPT要呆,很多时候一直给出重复答案,就算你强调关键字也是如此,甚至它会结束当前对话,脾气还不小。像是给它一份报告,让它分析,他就完全不如ChatGPT那样会给出总结和分析。看来Bing AI可能被屏蔽某些功能。 体验Google Bard 其实,我还是很看好Google的Bard AI,用了这么多年Google搜索引擎,Google搜索引擎的关键词纠错能力还是很亮眼的。我相信很多人在打字输入比较快的的时候,容易出现很多谐音词,当它输入到Google的搜索引擎的时候,你会发现基本上已经被Google纠错,并且在搜索引擎结果上面返回已经纠正的关键词,你是不是要找 xxxxx,红色高亮。ChatGPT和Bing也是有纠错能力的,只是我更想试试Bard。 2023-04-05 我已经获得了Bard AI的体验资格,很遗憾,它目前支持英文... Bard它说它支持关键词纠错,并且善于互联网搜索(我英语一塌糊度,这都是我用Google翻译的...) 你甚至可以将文章链接丢给它,它去帮你分析总结。我先是发生文章地址让它帮我做SEO优化,然后让它分析总结这篇文章。但是我发现它的回答有些问题,我把我这篇文章丢给它分析,它把New Bing说成是Google Ai的新搜索引擎... 当然它的中文还在训练中,这都可以理解。 Bard回复体验不像ChatGPT和Bing两个AI,它是一次返回全部答案,而其他两个是一个个字输出。Bard什么都敢说,什么都敢答,只要你敢问! 有时候回答能明显比之前回答慢,我估计它是自己在互联网搜索,并且分析搜索结果。Bard虽然自己说会用到各种搜索引擎,但是我认为它多数时候都是使用Google,毕竟是自家的,不可能放着自家世界上最大的搜索引擎不用,去用其他搜索引擎。配合Google搜索引擎简直如虎添翼,这也让我更看好Bard未来的发展。 我立即去问Bard来验证,果不其然它回答确实优先使用Google,但是他这回答总感觉有点王婆卖瓜的感觉... 随即我又问它出现的原因是不是因为ChatGPT,连Google两位创始人都回来了,虽然我也认为它的潜力很大,希望它自己的回答也不是在讲大话! 就目前来看,它没有像chatGPT-web版一样频繁断线需要刷新网页,体验感稍微好点,但是它的中文还在训练中,不知道还要多久。没有发现禁止某些地区使用,只是体验需要申请。 结语 目前我已经简单体验了ChatGPT、Bing AI和Google的AI Bard。目前人类在人工智能领域已经走出了一大步,相信在人工智能的帮助下,进步会越来越快。openai API价格比较贵,就个人而言勉强能接受,但是如果用它来做公共服务前期投入还是比较大的。ChatGPT和Bing AI可能是两个完全不同的产品,Bing AI明显更偏向解决关于搜索类型问题,虽然基于GPT4,但表现出来连GPT3.5都不如(阿三的锅?)。而Google AI Bard虽然还没发布,但是消息模型功能上感觉比其他两款要强大,看看Bard的后续进展吧! 我这两天只玩了下消息模型,还有很多图片、语音等模型还没机会,就拿图片模型来说,提取图片中的文字功能就可能绕过目前大部分简单图片验证码。 AI是新鲜事物,能力有限,目前最多也是辅助使用,远没有达到代替的程度。它无论是写代码,还是写论文,都基于大数据。 但这仅仅是目前...
2023年04月04日
225 阅读
0 评论
0 点赞
telegram-終點站emby自动签到
2022年01月05日
5,805 阅读
12 评论
4 点赞
2022-01-05
前言 之前写过一篇文章Emby公益服-上万部电影电视剧免费看,如今账号快到期了,需要考核后才能延长账号有效期。正准备去考核时发现不是三天一次考核机会了,而是每日签到获取积分后才能考核,一次考核需要40积分,每日签到获取的积分不固定,好像1-5分都有!考核失败还是需要72小时后才能再次考试! 这就有点蛋疼了,他们bot签到是需要回答问题验证的,之前好像没有。本想实现自动签到,就用telegram-cli试了一下,发现根本不支持内联键盘消息!!!毕竟好几年前的代码了,作者也没有在维护。那么现在只能找找其他的telegram client api集成包玩玩了! 皇天不负有心人,找到了一个python包python-telegram,赶紧上手试试看支不支持内联键盘消息! 开搞 python-telegram命名空间和python-telegram-bot有冲突,如果装了两者没法用。 有两种解决办法,要么卸载掉python-telegram-bot,要么使用virtualenv环境隔离。 python-telegram没办法在windows下使用,还不支持! 先来将环境隔离,创建一个工作目录,然后在目录下安装隔离venv是隔离环境名称: mkdir python-telegram-client cd python-telegram-client virtualenv venv # 进入隔离环境 source venv/bin/activate # 安装python-telegram pip install python-telegram # 建个文件写代码 nano server.py 退出隔离环境使用: # 退出隔离环境 deactivate 安装python-telegram 在Github看了下作者的例子和文档,随便找了个试一试。tg.get_chats()返回的都是chat_id,找不到哪个chat_id对应的群组/bot。想了个办法,查看每个chat_id最后一条消息,然后自己一个个找: from telegram.client import Telegram import re,time ... tg = Telegram(...) tg.login() result = tg.get_chats() result.wait() if result.error: print(f'get chats error: {result.error_info}') else: print(f'chats: {result.update}') # 查看所有会话的最后一条消息,用来查找对应的chat_id chat_ids = result.update['chat_ids'] for chat_id in chat_ids: chat_history = tg.get_chat_history(chat_id=chat_id,limit=1) chat_history.wait() print(f'chat id:{chat_id},message:{chat_history.update["messages"][0]["content"]}\n') ... 找到了对应的chat_id就可以和签到bot交互了。在发送签到命令之前,还需要监听新消息: tg.add_update_handler('updateNewMessage', send_verification_code) def send_verification_code(update): # 所有的新消息都会被监听,增加判断只监听自己感兴趣的 if 123456789 == update['message']['chat_id']: # print(update) # 提取问题并且计算 question = update['message']['content']['text']['text'] print(question) a = re.findall(r"\s\s(.+?)\+", question, re.M) b = re.findall(r"\+(.+?)=", question, re.M) if a and b: print(a, b) c = int(a[-1].strip()) + int(b[-1].strip()) answers = update['message']['reply_markup']['rows'][0] print(f'{a} + {b} = {c}') # 用答案和内联键盘值做匹配,一旦匹配执行按钮点击效果 for answer in answers: print(f'答案:{answer["text"]}') if int(answer['text']) == c: payload = { '@type': 'callbackQueryPayloadData', 'data': answer['type']['data'], ##每一个内联键盘都带有data数据 } # 发送答案(点击内联键盘) result = tg.call_method(method_name='getCallbackQueryAnswer', params={'chat_id': update['message']['chat_id'], 'message_id': update['message']['id'], 'payload': payload}) result.wait() if result.error: print(f'getCallbackQueryAnswer error: {result.error_info}') else: print(f'getCallbackQueryAnswer: {result.update}') break 以下是签到验证内联键盘消息部分报文: ... 'content': {'@type': 'messageText', 'text': {'@type': 'formattedText', 'text': '签到需要确认问题并选择您认为正确的答案:\n\n25 + 1 = ?\n\n请在 30 秒内作答', 'entities': [{'@type': 'textEntity', 'offset': 22, 'length': 10, 'type': {'@type': 'textEntityTypeBold'}}, {'@type': 'textEntity', 'offset': 37, 'length': 2, 'type': {'@type': 'textEntityTypeBold'}}]}}, 'reply_markup': {'@type': 'replyMarkupInlineKeyboard', 'rows': [ [ {'@type': 'inlineKeyboardButton', 'text': '26', 'type': {'@type': 'inlineKeyboardButtonTypeCallback', 'data': 'Y2hlY2tpbi1RbWFYT3Z5SzlKb0VMZmtmUURMN3ZYcVZMeFIxNk1CRQ=='}}, {'@type': 'inlineKeyboardButton', 'text': '22', 'type': {'@type': 'inlineKeyboardButtonTypeCallback', 'data': 'Y2hlY2tpbi1PVkdOSjliZTJncXgxdDdmQTFQdnc5b2RtTXoxNlJ4WA=='}}, {'@type': 'inlineKeyboardButton', 'text': '85', 'type': {'@type': 'inlineKeyboardButtonTypeCallback', 'data': 'Y2hlY2tpbi1EV1gwTDYxTzRvWmxqRjFmYTlkMThBcFZ4OW1ZbmR5Sg=='}}, {'@type': 'inlineKeyboardButton', 'text': '66', 'type': {'@type': 'inlineKeyboardButtonTypeCallback', 'data': 'Y2hlY2tpbi1WR05KOWJlMmdxeEUxaTdmQTFQdnc5b2RtTXoxNlJ4WA=='}}, {'@type': 'inlineKeyboardButton', 'text': '68', 'type': {'@type': 'inlineKeyboardButtonTypeCallback', 'data': 'Y2hlY2tpbi1sNUJrbVBOd1hxQnhWZnpmMmJBUVZMclFKN0RSOXlqeA=='}}]]}}} 最后发送签到命令: result = tg.send_message( chat_id=123456789, ##chat_id自己找一找,虽然都一样! text="/checkin", ) result.wait() tg.idle() 这就完成了一个账号的签到,如果是多个账号使用tg.idle()就不行了,tg.idle()会堵塞当前进程,需要终止信号终止。要跑多个账号只能等待一段时候后自动停止,然后再执行下一个账号。需要修改下代码,让他可以跑多个账号: accounts = ['+123456789', '+456789123', '+789456123' ...] for account in accounts: tg = Telegram(... phone=account, ...) tg.add_update_handler('updateNewMessage', send_verification_code) tg.login() ... print(f'当前账号:{account}') print(f'等待15秒,接收签到验证信息并且验证签到') time.sleep(15) tg.stop() python-telegram是支持多账户的,会保存用户凭证,所以登陆一次即可,新账户登陆还是需要输入验证码的。 现在我们将他打包成可执行程序: pip install pyinstaller 打包 pyinstaller -F server.py 打包完成在dist文件夹下。 如果直接跑起来会报错:..../libtdjson.so的话可以下载作者编译好的libtdjson.so,也可以自己编译td build。libtdjson.so的位置可以在代码中指定: tg = Telegram(...,library_path='/path/to/libtdjson.so') 这时候退出隔离环境deactivate,跑一下../dist/server,没有其他问题的话加入crontab, 设定每天执行一次即可自动签到! 结语 我个人感觉python-telegram在可编程上比telegram-cli要好用,之前LXK0301京东签到脚本-自动提交互助码一文中使用telegram-cli虽然也可以达到效果,但是不如直接敲代码来得舒服。telegram-cli更多的还是作为一个linux的telegram客户端。 python-telegram用来做签到只是个引子,更多的还是各种自动化非常简单了,毕竟官方提供了所有API。本来以为要自己集成实现API,还好有大佬做好了!
2021-09-06
折腾京东APP签名-获取wskey相关签名参数
前言 前几天随手撸了个自动上传京东open token(open token其实就是用户cookie)的脚本(有兴趣可以看看:京东cookie自动更新维护),虽然可以自动上传了,但是每天都得去打开京东APP才行,而且两次打开时间不能超过24小时,不然open token就过期了。这方法怎么看都不是很省事! 最近一直在找替代方法,发现Zy143L大佬脚本中提到wskey可以申请open token,wskey有效期应该比较长,我使用好几天之前抓包到的wskey依然可以获取到open token。wskey在APP抓包中经常看到,使用wskey的请求里面都有签名,感觉签名方法应该是一样的。通过genToken的接口获取open token,那个签名方法虽然短时间可以重复使用(请求只需要变动wskey就好,签名没有加入wskey做计算),但是还不清楚有效期,如果一直靠抓包获取签名的话那比上面直接抓包open token还恶心! 分析 wskey很重要,京东APP很多敏感接口都是使用wskey,不要泄露!!! 既然可以通过wskey获取open token,wskey有效期有比较长,那么它是一个很好代替每天上传open token的方法。 我的思路: 不定期通过手机app抓包wskey上传到服务器,服务器接收到后写入wskeys.list。 每天定时通过wskey换取open token(open token 24小时有效期,应该每天获取两次比较保险),并且写入cookies.list。 目前还不清楚wskey有效期,所以在第二步中wskey过期及时发送通知以便重新上传wskey。 经过一下午折腾,确实可行。但是看Zy143L大佬源码发现genToken接口中的签名是请求coding.net返回的(应该是大佬自建部署的吧!)!这个动作引起了我的好奇心,没有公布签名算法,究竟是何等高级的玩意儿?请求没有任何数据,就一个get请求即可返回所有签名参数,难道签名参与计算的值都是固定的吗? 这类资料比较少,不过还是有乐于分享的大佬。找到几篇文章: JD app sign 加密参数破解 - unidbg 逆向工具之unidbg(在pc端模拟执行so文件中的函数) Unidbg使用指南(一) Unidbg模拟执行大厂so实操教程(一) 先把框架搭起来 Unidbg模拟执行大厂so实操教程(二) 借鸡生蛋之SandHook的使用(一) 借鸡生蛋之某电商App签名so的使用(二) 借鸡生蛋之某电商App签名so的使用(三) 对于我来说难度比较大,涉及知识面广,不过如果有信心那就没问题。 我总结了一下经过步骤: 首先得搭建一个android开发环境。 下载京东安卓APP,apk文件可以当作压缩文件打开,从lib里面提取出libjdbitmapkit.so。 用ida修改libjdbitmapkit.so文件,需要修改一些地方屏蔽错误。 使用unidbg载入libjdbitmapkit.so,调用签名方法签名。 打包编译,部署到服务器。 步骤虽然简单,但是操作过程对于一个从来没有接触过andriod、汇编的人来说每一步都掉坑!!! 过大坑纪要 Exception in thread "main" java.lang.IllegalStateException: Illegal JNI version: 0xffffffff,这个问题坑了我好久,起初我以为自己环境有问题,因为根本找不到什么资料。其实就是so文件问题,如果你没有使用unidbg-0.9.1版本的话会出现这个错误,引发错误的根本原因就是先按借鸡生蛋之某电商App签名so的使用(三)对so文件打补丁,如果按上文推荐的文章顺序阅读那么就会被卡住,建议全部读一遍后再动手。 打补丁使用的ida软件,对于汇编是一脸懵逼的,借鸡生蛋之某电商App签名so的使用(三)一文中把修改位置写得很明白了,但是ida真心不会用,其中包括安装ida插件: keystone中下载msi安装文件,Version 0.9.1有提供32位和64位装一个就行。安装过程一定要勾选安装pthon2.7,我就取消了,最后插件无法使用,还是自己手动去安装的,如果你也是手动安装记得安装six模块:pip install six。 把keypatch代码复制,到ida plugins目录建一个新文件Keypatch.py,把代码复制进去。 ida中Options-General-Disassembly-Number of opcode bytes设置成16,以十六进制显示字节码: 使用keypatch插件修改sourceDir部分,JNI_OnLoad部分使用ida功能Edit-Patch program-Change byte就好了。000037CC 04 25 C0 F2 01 05 MOVS R5, #0x10004这段我是用keypatch一直报错,浪费一两个小时,使用Patch program替换中间字节就行了: 修改摘要: 00002D08 40 F0 40 81 BNE.W loc_2F8C -> 00002D08 40 E1 B loc_2F8C 00002F8C 6F F0 02 00 MOV R0, #0xFFFFFFFD -> 00002F8C 4F F0 01 00 MOV.W R0, \#1 000037C8 FF F7 96 F9 BL check_status -> 000037C8 FF F7 96 F9 BL check_status 000037C8 FF F7 96 F9 BL check_status 000037CC 80 46 MOV R8, R0 000037CE 00 28 CMP R0, \#0 000037D0 67 D1 BNE loc_38A2 -> 000037C8 FF F7 96 F9 BL check_status 000037CC 04 25 C0 F2 01 05 MOVS R5, #0x10004 000037D2 2A E0 B loc_382A; 打包一定要看Unidbg使用指南(一),所有操作都是在test文件夹完成的,不然会缺少包,装又装不上!打包也要载入test文件夹! 搭建服务 如果你能坚持到这步就已经成功了,只要能获取到签名参数想怎么玩就怎么玩!我还是用http服务比较顺手,网上找了个java socket代码一顿改!!! 在JD app sign 加密参数破解 - unidbg文中代码基础上修改,加入socket模拟http: ... public static void service(final Socket socket, final JingDong jd) { InputStream inSocket; try { //获取HTTP请求头 inSocket = socket.getInputStream(); int size = inSocket.available(); byte[] buffer = new byte[size]; inSocket.read(buffer); String request = new String(buffer); System.out.println("ClientBrowser:\n" + request + "\n" + "------------------------------------------------------------------"); String httpCode = "200 OK"; String result = ""; if (request.length() > 0) { try { JSONObject data = JSON.parseObject(request.substring(request.lastIndexOf("\r\n")).trim()); if (data != null) { String uuid = data.getString("uuid"); String functionId = data.getString("functionId"); try { String body = new URLCodec().decode(data.getString("body")); String version = data.getString("version"); if (!uuid.isEmpty() && !functionId.isEmpty() && !body.isEmpty() && !version.isEmpty()) { result = convert(jd.runJni(uuid, functionId, body, version)); System.out.println(result); System.out.println(convert(result)); } } catch (DecoderException e) { e.printStackTrace(); } } } catch (JSONException e) { e.printStackTrace(); result = "{\"code\": \"400\", \"message\": \"Invalid param\"}"; httpCode = "400 Bad Request"; } } //将响应头发送给客户端 String responseFirstLine = "HTTP/1.1 " + httpCode + "\r\n"; String responseHead = "Content-Type:application/json\r\n"; OutputStream outSocket = socket.getOutputStream(); System.out.println("ServerResponse:\n" + responseFirstLine + "\n" + responseHead + "\n" + result + "\n" + "--------------------------------------------------------------------"); System.out.println("current thread:" + Thread.currentThread().getName()); System.out.println("threads count:" + Thread.activeCount()); outSocket.write(responseFirstLine.getBytes()); outSocket.write(responseHead.getBytes()); outSocket.write("\r\n".getBytes()); outSocket.write(result.getBytes()); outSocket.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { //獲取參數,服務監聽地址和端口 //java -Daddress=0.0.0.0 -Dport=9999 -jar unidbg-android.jar address = System.getProperty("address", "127.0.0.1"); port = Integer.parseInt(System.getProperty("port", "8668")); threadCount = Integer.parseInt(System.getProperty("thread", "10")); //綫程池 ExecutorService executorService = Executors.newFixedThreadPool(threadCount); final ServerSocket serverSocket; final JingDong jd = new JingDong(); try { //建立服务器Socket,监听客户端请求 serverSocket = new ServerSocket(port, 50, InetAddress.getByName(address)); System.out.println("Server is running on " + serverSocket.getLocalSocketAddress()); //死循环不间断监听客户端请求 while (true) { final Socket socket = serverSocket.accept(); System.out.println("biuld a new tcp link with client,the cient address:" + socket.getInetAddress() + ":" + socket.getPort()); //并发处理HTTP客户端请求 executorService.execute(new Runnable() { @Override public void run() { service(socket, jd); } }); } } catch (Exception e) { e.printStackTrace(); } finally { jd.destroy(); executorService.shutdown(); } } ... 网上七拼八凑折腾出来这么个玩意,使用: java -Daddress=127.0.0.1 -Dport=8668 -DthreadCount=5 -jar xxx.jar address:绑定地址,port:绑定端口,threadCount:线城数量。 请求参数: //没有限制请求方法,GET POST随意,以下是请求body {"uuid":"随机字符串,随机生成就行了","functionId":"接口(genToken)","body":"URI编码的json,不要带任何多余东西","version":"安卓版本"} //返回结果 { "uuid": "9d53afe389f6ae5f", "st": "1630922926986", "sign": "0a9b72a4fc6ffd5d799642dd295623f8", "sv": "111" } 然后外面再套一层nginx反代,或者和自己jd_script同服务器,内网请求。你要是绑定0.0.0.0暴漏出去也行! 结语 为了个签名折腾了好久,整个签名使用了functionId,body,uuid,client,clientVersion五个参数,client基本可以固定android了。使用ida汇编长了不少知识。 至此应该是不用在操心京东登陆方面的问题了,只要使用京东APP全部都自动更新了!
2021年09月06日
6,427 阅读
23 评论
0 点赞
2021-09-02
京东cookie自动更新维护
前言 薅羊毛门槛越来越高了,京东cookie目前有效期只有一天,有些甚至更短。之前扫码登陆目前看来已经获取不到cookie了,现在获取cookie相对麻烦不少。 前段时间很忙,最近闲下来折腾下。看到github上有些脚本,可以抓包获取京东APP请求中cookie,突然有个大胆的想法。如果我让脚本把获取的cookie发送到自己的服务器,服务器自动更新维护cookies.list文件,那么每天打开下APP即可。像IOS有快捷指令APP,让它自动化,每天按时打开京东APP更新cookie,让后服务器自动维护岂不美哉!缺点就是每个用户都得有个可以执行脚本的APP。 废话不多说,干就完了 由于我用的是软路由,openwrt上跑docker(没错,还是LXK0301大佬的那套,自不过修修补补勉强用着,不过目前蛮多用什么面板的!),所以要复杂一点,服务器上部署可以少很多步骤。在openwrt上需要开启frp客户端,然后要映射docker容器端口到本地。还需要一台服务器搭建frp,主要是服务端会搭建在openwrt上,方便外网访问API。在openwrt上部署服务端,接收请求更新本地cookie文件就好了。 服务端 服务端不需要太复杂,用node.js弄个简单的就好了,根据cookie中的pt_pin来替换整行cookie(没有新增哦,只能提换已存在的): const http = require('http') const fs = require('fs'); const path = require('path') const file = path.resolve(__dirname, '../logs/cookies.list') //路径不同需要改改,你当期间脚本文件相对路径 function writeCookie(pt_key, pt_pin) { const re = new RegExp('.*'+ pt_pin +'.*', 'g') const cookie = `${pt_key};${pt_pin};` // console.log(re) fs.readFile(file,'utf8',function(err,data){ // console.log('替換前' + data) let result = data.replace(re, cookie); // console.log('替換後' + result) fs.writeFile(file, result, 'utf8', function (err) { if (err){ console.log(err) } }); }) } const server = http.createServer(function(request, response) { const contentType = request.headers['content-type'] // response.setHeader('Content-type', 'application/json') // && contentType === 'application/json' if (request.method === 'POST' && request.url === '/cookie/update') { let body = []; request.on('data', (chunk) => { body.push(chunk); }).on('end', () => { // console.log(Buffer.concat(body).toString()) try { body = JSON.parse(Buffer.concat(body).toString()); if (body.pt_key && body.pt_pin) { writeCookie(body.pt_key, body.pt_pin) // console.log(body.pt_key) response.end('OK'); } else { response.statusCode = 400; response.end('Invalid param'); } } catch (e) { response.statusCode = 400; response.end('Invalid param'); } }); } else { response.statusCode = 404; response.end(); } }) const port = 8888 const host = '0.0.0.0' server.listen(port, host) console.log(`Listening at http://${host}:${port}`) 运行 node 脚本名即可启动服务,对于服务器上部署,我还是推荐使用 pm2 来管理 (至于有什么有点,点进去官网了解下吧!): # 安装 $ npm install pm2@latest -g # or $ yarn global add pm2 # 运行 pm2 start 脚本名 客户端 脚本在此 jd_appopen.js, 只需要稍作修改即可: /* 杀掉后台后打开京东app获取app_open 在脚本日志查看值 [MITM] hostname = api.m.jd.com ===========Surge================= [Script] jd_appopen = type=http-request,pattern=^https:\/\/api\.m\.jd\.com\/openUpgrade, max-size=0, script-path=jd_appopen.js ===================Quantumult X===================== [rewrite_local] # jd_appopen ^https:\/\/api\.m\.jd\.com\/openUpgrade url script-request-header jd_appopen.js =====================Loon===================== [Script] http-request ^https:\/\/api\.m\.jd\.com\/openUpgrade script-path=jd_appopen.js, timeout=3600, tag=jd_appopen */ const $ = new Env("app_open") if ($request.headers) { let cookie = ($request.headers.Cookie || $request.headers['Cookie'] || $request.headers['cookie'] || '') let pt_key = cookie.match(/(pt_key=[^;]*)/)[1] let pt_pin = cookie.match(/(pt_pin=[^;]*)/)[1] if (pt_key && pt_pin) { console.log('================') console.log(`${pt_key};${pt_pin};`) console.log('================') const options = { "url": `换成你的域名/cookie/update`, 'body': JSON.stringify({ "pt_key": pt_key, "pt_pin": pt_pin }) } $.post(options, (err, resp, data) => { try { if (err) { $.msg("app_open获取成功!", `更新cookie失败: ${JSON.stringify(err)}`) console.log(`pp_open获取成功,更新cookie失败: ${JSON.stringify(err)}`) } else { console.log(`更新cookie: ${data}`) } } catch (e) { $.logErr(e, resp) } }) } } $.done($request.headers) ... 然后使用你手机APP(Surge、Quantumult X、Loon、shadowrocket)添加即可,shadowrocket我试过也可以,成本相对其他app应该便宜点! IOS快捷指令 在快捷指令APP中添加个自动化,运行前询问看自己情况开启,这里的shadowrocket可以换成其他执行脚本APP,如果你跑脚本的APP常驻打开那么就可以删掉shadowrocket部分,启动此自动化需要打开: 快捷指令有个缺点,不是所有自动化都可以锁屏运行,像这个也是,但是会发送通知,点击通知就可以,或者自己不使用,每天自己手动也是一样的! 结语 没有写很详细,这些也就是大概思路,还有很多值得优化的地方。京东这次动作能刷下不少代挂了,操作成本太高了。对于三五个好友玩玩还行。如果喜欢折腾的应该能按照思路完善吧,写得太详细有时候真不是件好事!
2021年09月02日
4,412 阅读
0 评论
0 点赞
2021-04-13
Nginx SNI 分流(端口复用)使用Xray+VLESS+XTLS
前言 Xray已经出来一段时间了,之前一直使用VLESS+tls+ws方式科学上网,其实都够用,没什么问题。但是了解了下XTLS黑科技,再看看Xray性能测试,这货简直爆炸,性能是TLS的数倍。 其实之前折腾过一次,但是Xray要监听443端口(不监听也行,但是不完美啊),影响做站。虽然有解决方法,但是不够完整,我一不小心就跳坑里面去了。Xray已经带了SNI回落功能(教程看这里:通过 SNI 回落功能实现伪装与按域名分流),Nginx也带SNI功能,我还是觉得用Nginx的比较好,免得折腾Xray影响网站运行。 这里我不会写如何安装Xray,因为教程实在是太多了,嫌麻烦还有一键脚本:Xray_onekey(V2ray脚本别用这个作者的哈,特别是服务器有站点的!!!Xray脚本这个大佬的还不错)。 坑 因为服务器上有几个站点,装完Xray后实现SNI分流,过程非常顺利,但是chrome上有问题,几个二级域名访问的内容全部和第一个访问的域名一样。 例如:我先访问 a.example.com 然后在访问 b.example.com,b.example.com 响应内容和 a.example.com 一模一样,然后再访问 c.example.com 还是和 a.example.com 一样。开chrome隐身模式直接访问 c.example.com 正常,然后访问 a.example.com 或 b.example.com 内容又全是 c.example.com 的(不一定会每次都这样,要看浏览器是否使用现有连接或服务器是否断开了之前的连接)。 这个问题折腾我很长时间,最后发现和HTTP/2有关,我所有站点不使用HTTP/2就会正常,只要有一个站点使用了HTTP/2,你先访问HTTP/2站点,那么后面的其他子域名都会变成它的内容。这个情况没有仔细测试证明,无法确定。 最开始我使用Xray的SNI也是这样,我还以为是Xray SNI的问题,之后换成Nginx使用SNI还是这样。chrome中有这个问题,用手机safari浏览器完全正常。 经过网上一番搜刮,终于找到了问题根源:通配符域名证书。 首先你得了解什么是SNI,个人理解:SNI就是通过证书区分服务。多个二级域名使用通配符域名证书的话,相同的证书无法区分具体想访问的服务,因为它们的证书都一样。 用下人家的图(原作者文章:Multiplex TLS Traffic with SNI Routing): *由于原始服务器10.0.3.2使用的TLS证书具有通配符名称 .example.com,因此Web浏览器可以建立服务器名称为 b.example.com 的 TLS连接,并对HTTP/2请求使用相同的连接到 a.example.com。这可能会在网站和应用程序中导致未定义的行为。** 因为HTTP/2会保持TCP连接,导致你访问了 a.example.com 后,在访问 b.example.com 的时候使用的同一个连接,SNI跟失效了一样,直接使用该连接访问之前的服务。我在Xray的调试日志中发现访问错误的域名没有获取到,是空的! 两个域名使用同一个连接(红框内是连接ID),可以很清楚的看到两个域名使用同一个连接,返回的内容也是一模一样: 解决办法两种: 不使用HTTP/2。不确定是否HTTP2的问题,但是你可以试一试 不使用通配符域名证书,站点域名证书一个个申请。 配置Nginx SNI 使用Nginx首先得安装(如果服务器自带就不用折腾了),不会安装Nginx可以看我之前的文章:Ubuntu 安装nginx(如果使用Xray_onekey脚本,那他已经帮你全部弄好了,你都不用折腾)。 nginx.conf配置追加: stream { map $ssl_preread_server_name $orzlee { a.example.com a; b.example.com b; c.example.com c; } upstream a { server 127.0.0.1:60088; ### A站点监听端口,xray xtls伪装站点 } upstream xtls { server 127.0.0.1:4443; ### 你的Xray端口 } upstream b { server 127.0.0.1:60001; ### B站点监听端口,业务站点 } upstream c { server 127.0.0.1:60002; ### C站点监听端口,业务站点 } server { listen 443 reuseport; listen [::]:443 reuseport; proxy_pass $orzlee; ssl_preread on; proxy_protocol on; } server { ### Xray XTLS listen 127.0.0.1:60088 proxy_protocol; proxy_pass xtls; } } a.example.com.conf配置(伪装站点): server { listen 80; listen [::]:80; server_name a.example.com; return 301 https://$http_host$request_uri; } server { ### 伪造站点由Xray处理SSL listen 127.0.0.1:60003 proxy_protocol; ### xray http/1.1 listen 127.0.0.1:60004 http2 proxy_protocol; ### xray http/2 set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; port_in_redirect off; ###重定向去掉端口号 server_name a.example.com; index index.html index.htm index.php default.php default.htm default.html; root /var/www/a.example.com; ... } b.example.com.conf配置(其他业务站点配置照葫芦画瓢): server { listen 80; server_name b.example.com; rewrite ^(.*) https://b.example.com$1 permanent; } server { listen 127.0.0.1:60001 proxy_protocol ssl http2; set_real_ip_from 127.0.0.1; ### 获取真实客户IP,不然全是127.0.0.1 real_ip_header proxy_protocol; port_in_redirect off; ###重定向去掉端口号。不然类似 try_files nginx帮你重定向时,你浏览器上都带了60003这样的端口 ssl_certificate b.example.com.cer; ### 证书换成你的 ssl_certificate_key b.example.com.key; ### 证书换成你的 server_name b.example.com; root /var/www/b.example.com; index index.php index.html index.htm; ... } 配置Xray 服务端配置: { "log": { "access": "/var/log/xray/access.log", "error": "/var/log/xray/error.log", "loglevel": "warning" }, "inbounds": [ { "listen": "127.0.0.1", "port": 4443, "protocol": "vless", "settings": { "clients": [ { "id": "你的UUID", "flow": "xtls-rprx-direct" } ], "decryption": "none", "fallbacks": [ { "dest": 60003, "xver": 1 }, { "dest": 60004, "alpn": "h2", "xver": 1 } ] }, "streamSettings": { "network": "tcp", "security": "xtls", "xtlsSettings": { "alpn": [ "h2", "http/1.1" ], "minVersion": "1.3", "certificates": [ { "certificateFile": "b.example.com.cer 记得换证书", "keyFile": "b.example.com.key 记得换证书" } ] } }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls" ] } } ], "outbounds": [ { "protocol": "freedom" } ] } 客户端看作者说明吧,值得一看:Outbounds 可用协议列表-VLESS,flow仔细看看。 结语 本来折腾Xray的,结果Nginx折腾大半天。虽然掉坑里了,总算是爬出来了,受益匪浅! 通配符证书用起来省事,碰到坑了一下还不好找问题。就今天这个坑上网找都不知道怎么描述,基本上找不到相关问题,比较冷门。之前参考其他博主Nginx SNI配置发现有其他同学也有这样的问题,但是无从查起,不了了之! 遇到这个坑不长记性都难。
2021年04月13日
7,918 阅读
52 评论
3 点赞
2021-03-14
openwrt-安装oh-my-zsh
前言 openwrt的shell连上次会话历史记录都没有,很是蛋疼。不如换成oh-my-zsh,还有很多插件可以玩。 VPS上安装可以看之前的文章:oh-my-zsh强大的zsh配置管理 安装 操作前记得备份你得openwrt配置,现在很多用的都是改版openwrt,不确定会发生什么奇奇怪怪的问题,但是大部分是没有问题的,备份一下保险。 登陆到openwrt ssh,首先安装依赖: opkg update && opkg install wget unzip zsh ca-certificates 安装oh-my-zsh: sh -c "$(wget -O- https://raw.githubusercontent.com/felix-fly/openwrt-ohmyzsh/master/install.sh)" 这时候已经安装完成了,还差设置默认shell为zsh: which zsh && sed -i -- 's:/bin/ash:'`which zsh`':g' /etc/passwd 到此结束,退出当前会话然后重新登陆ssh看看是不是已经默认为zsh了。 有了历史记录再配合命令补全、命令高亮插件简直不能太爽!!! 自动补全插件或其他插件安装方法还是请看:oh-my-zsh强大的zsh配置管理 自动补全插件: 命令高亮插件: 如果你要卸载oh-my-zsh的话: sh -c "$(wget -O- https://raw.githubusercontent.com/felix-fly/openwrt-ohmyzsh/master/uninstall.sh)" 结语 装完oh-my-zsh感觉没有束缚了,这样的终端爽的飞起。之前所有的服务器都装了oh-my-zsh,习惯了,没有oh-my-zsh总感觉太单调了,敲起来不顺手。
2021年03月14日
1,986 阅读
0 评论
0 点赞
openwrt-通过telegram bot自动创建启动jd-scripts docker容器
2021年03月13日
2,625 阅读
8 评论
0 点赞
2021-03-13
前言 使用lxk0301大佬的jd_scripts-docker脚本后突发奇想,如果利用telegram bot获取用户京东cookie,然后自动创建docker容器并且启动容器跑脚本,这个流程一气呵成,以后京东cookie过期就可以很方便的处理,然后自己朋友也可以扫京东登陆二维码就部署整个签到脚本了。 在openwrt折腾可以看我之前的文章:openwrt-docker部署lxk0301京东自动签到脚本 2021-03-22更新:作者已经更新docker容器,详细说明:增加bot交互,spnode指令(jd_docker仓库被Gitee封了,最新地址jd_docker)。容器已经自带telegram bot,大量与docker容器配套的命令以及获取cookie功能。有兴趣可以玩玩看。 运行环境和思路 我使用的是openwrt软路由(CPU J4105, 8G, 128G SSD),由于性能过剩,不折腾点东西不舒服,所以没有放VPS上。软路由固件使用的是eSir大佬的高大全版本,eSir大佬固件盘。记得扩容overlay分区,然后opt容量也要注意下,我在openwrt-docker部署lxk0301京东自动签到脚本文章中提到过。 由于部署在路由器上,telegram bot webhook发到路由可能会遇到GFW的干扰(不确定是否会干扰入境流量,可以试试看),我使用frp(eSir openwrt自带)做内网穿透,frp服务端需挂在境外服务器上,这样外网问题就能解决。但是路由器还是需要科学上网的。 telegram bot开发使用python,还有少部分lua,因为openwrt上的dockerman插件语言也是lua语言,启动docker时还是希望能在dockerman中管理,所以还是折腾了lua。 整个流程: 用户在telegram bot发送命令 telegram bot返回一个京东登陆二维码(以下图片中的login命令是测试时候的) 用户扫码二维码,服务器获取用户京东cookie 服务器拿到cookie创建(或删除重建)一个jd_scripts-docker容器,并且启动 提示用户启动成功或失败 成功后可以在openwrt web端docker-容器看到新加入的用户docker容器,还可以在openwrt的dockerman插件中管理容器。 思路: 用户发送命令给telegram bot,服务器接收到后进入配置好的容器,执行/scripts/getJDCookies.js脚本获取脚本生成的京东登陆链接,用链接生成二维码,通过telegram bot返回给用户。二维码有效期三分钟,脚本也会持续三分钟。用户扫码后服务器会捕获到脚本回显,提取京东cookie。 拿到cooki后判断用户是否已经创建容器,创建了多久,超过N天的删除旧容器,然后再创建一个新的容器启动,没有使用过的用户直接创建一个新的。由于我想兼容dockerman,所以用lua语言折腾了一个简版创建和管理docker命令行脚本。懒得折腾了,服务器直接复制一份已存在的jd_scripts-docker脚本配置新建,环境变量和脚本可以自行配置就行了。启动成功捕获命令行回显容器ID,容器ID和用户信息,京东cookie存Sqlite数据库。 由于防止用户频繁提交,使用reids存下已经获取二维码的telegram用户ID,必须等待三分钟或者jd_scripts-docker成功后再次获取。 本来是想使用一个容器,然后在容器里面修改JDCOOKIE环境变量,配置多个cookie。但是目前有两个缺点: 单容器多用户跑脚本时会一个个跑,并不是并发跑,人数一多脚本执行时间会很长(如果限制单容器用户人数也许是个办法,比如说一个容器只允许5个用户,多出来的再建个新容器,以后再说吧!)。 脚本通知(多账号)只能发给一个环境变量配置好的接收用户。 不过最近lxk0301大佬更新了单容器多用户脚本会自动互助的功能,只能自己再想办法折腾下了。 脚本说明: 2021-03-16更新:添加单容器追加cookie功能,这样VPS应该能用了(我没有测试,但是不涉及到dockerman容器管理应该是没有问题的!): 仓库地址:Github env.config文件添加两个配置,主要是add_user_mode添加用户模式,默认是create,单容器是attach: [telegram_bot] ... [jd_scripts] ... auto_delete_docker_by_days=30 //目前没有实现自动删除过期用户容器功能,只是attach模式中过滤超过N天的用户cookie add_user_mode=attach //创建容易方式:attach 附加,create 创建,附加只会追加cookie到existed_docker_container_name配置容器里,create每一个用户都会创建一个新的docker容器 [sqlite] ... 如果使用attach模式,会在当前目录生成一个cookies.sh文件,执行该文件会导入所有通过telegram bot加入的有效用户cookie到环境变量。 使用attach模式方法: 现在开始准备新建一个容器,挂载cookies.sh文件到jd_scripts_docker容器(export_jd_cookies_script_orz.sh挂载文件名要改的话下面的脚本内容也要跟着修改): 你的目录/cookies.sh:/scripts/docker/export_jd_cookies_script_orz.sh 添加一个自定义脚本: 先挂载本地脚本(名称目录自定,但是挂载后的不要改了,不然又要改脚本内容。如果远程脚本就不用挂载了): 你的目录/docker_shell.sh:/scripts/docker/docker_shell.sh 添加环境变量(远程脚本不用上面的挂载docker_shell.sh步骤): CUSTOM_SHELL_FILE=/scripts/docker/docker_shell.sh 脚本内容,意思是每分钟执行update_crontab.sh脚本: if ! [ ! -f "/scripts/docker/export_jd_cookies_script_orz.sh" ]; then echo "* * * * * sh +x /scripts/docker/update_crontab.sh 2>&1" >> /scripts/docker/merged_list_file.sh fi 挂载update_crontab.sh脚本 你的目录/update_crontab.sh:/scripts/docker/update_crontab.sh 脚本内容: FIND_FILE="/scripts/docker/merged_list_file.sh" FIND_STR="export_jd_cookies_script_orz.sh" # merged_list_file.sh定时任务加入cookies环境变量脚本 if ! [ `grep -c "$FIND_STR" $FIND_FILE` -ne '0' ];then sed -i 's/\/scripts\/logs\/auto_help_export\.log/\/scripts\/logs\/auto_help_export\.log \&\& \. \/scripts\/docker\/export_jd_cookies_script_orz\.sh/g' $FIND_FILE ## 更新定时任务列表 crontab $FIND_FILE fi CRZAY_JOY_COIN_FILE="/scripts/docker/proc_file.sh" # joy coin脚本加入cookies环境变量脚本 if ! [ `grep -c "$FIND_STR" $CRZAY_JOY_COIN_FILE` -ne '0' ];then sed -i 's/node \/scripts\/jd_crazy_joy_coin\.js/\. \/scripts\/docker\/export_jd_cookies_script_orz\.sh \&\& node \/scripts\/jd_crazy_joy_coin\.js/g' $CRZAY_JOY_COIN_FILE sh -x /scripts/docker/proc_file.sh fi 该脚本主要是每分钟执行,但是只修改一次merged_list_file.sh定时任务文件,并且立即更新crontab list,为每个京东任务定时脚本执行前先更新JD_COOKIE环境变量,这样你得脚本执行才能正确获取cookie。第二个是joy coin脚本,这个脚本没有在定时任务列表中,每天只会执行一次,所以要单独修改后并启动。 因为是每分钟执行,所以可以很大程度上避免cookie没有导入的尴尬。 你过你还需要其他环境变量或者磁盘挂载记得自己加。 单容器只有创建容器时配置好的通知环境变量接收通知,没法多个用户分发的。而且人数一多执行单个脚本时间会延长。优点就是可以添加环境变量配置ENABLE_AUTO_HELP=true开启单容器多用户互助。 2021-03-16更新结束。 脚本地址:jd_scripts telegram bot python3.8, python3.9都没问题,其他环境没测试,我使用python3.9开发,openwrt上是3.8没有发现问题。 openwrt上安装pip请点击get-pip。 之前python用的qrcode包生成二维码,但是默认只有svg格式,想生成png,jpg就需要Pillow包,但是这个包在openwrt上安装一直报错,确少zlib库,这个好解决,安装zlib-dev就好了,然后又提示缺少jpeg,这个库openwrt已经用libjpeg-turbo替换了libjpeg库,就算安装了libjpeg-turbo也还是不行,所以换成segno包了。 需要安装包(不知道是不是有遗漏): pip install segno python-telegram-bot peewee redis 脚本已经撸出来了,做个说明吧!自己用也没太多讲究(记得删除注释): [telegram_bot] token = 88888888:AAAAAAAAAAAAAAAA //这是telegram bot token port = 8080 //监听端口, frp请填写web端本地端口(local_port),openwrt别配置80端口,不然都无法启动telegram脚本,因为openwrt web端已经占用了80端口 admins=88888888,8888888 //管理员用户,如果指定了管理员就只能管理员使用京东docker命令,获取自己的userid看这里https://gitee.com/lxk0301/jd_docker/blob/master/backUp/TG_PUSH.md url=https://telegram.bot/ // telegram bot webhook发送域名 redis_cache_prefix=telegram_bot: //redis缓存前缀,可以随便改 commands=jd_script_start:登陆京东并且创建docker容器 //命令,可以自行添加,命令格式 命令:命令说明,命令:命令说明,命令:命令说明 多命令逗号隔开 [jd_scripts] existed_docker_container_name = jd_scripts_orzlee //已经创建好的容器名称,主要用于执行`/scripts/getJDCookies.js`脚本给用户登陆 existed_docker_container_id=1919c3ff9e45ee6d1ca58xxxxxxxxxxxxxx5a8d //已经创建好的容器id,主要用于复制配置文件 docker_container_prefix = jd_scripts_ //新建docker容器名称前缀 tg_bot_token=88888888:AAAAAAAAAAAAAAAA //jd_scirpts 脚本推送通知bot token,可以和上面一样,可以使用其他token,推送用户就是谁请求的二维码,通知就会推送给谁 min_login_days=10 //最少登陆多少天才能重新使用,这个是怕已经成功创建容器后,用户一直用同一个京东账户扫码,然后服务器不停的删除容器创建容器,单位是天,可自行修改,0就是不设置 max_docker_num=50 //最大用户数量,这是判断Sqlite数据库用户数量决定的,不是你本地docker容器数量 auto_delete_docker_by_days=30 //目前没有实现自动删除过期用户容器功能,只是attach模式中过滤超过N天的用户cookie add_user_mode=attach //创建容易方式:attach 附加,create 创建,附加只会追加cookie到existed_docker_container_name配置容器里,create每一个用户都会创建一个新的docker容器 [sqlite] database=telegram_bot_jd_scripts.db //数据库文件名称 环境变量和挂载我给写死了,需要自己修改下吧! 命令由于有"号,所以要转义,在shell中要转义\",代码中就必须转义\和",所以环境变量和挂载磁盘都需要\\\"环境变量=xxx(挂载参数:xxx)\\\"包含起来,因为这个基本不会改变,所以没有放入配置文件,你可以继续加或者删掉部分,像JDCOOKIE和TG_USER_ID这些都是用户的变量,所以还是留下吧: from src.config import * from src import common def createAndStartContainer(cookie, tgUserId, name): ##lua newcontainer.lua -n jd_scripts_test -e \"JD_COOKIE=pt_key=AAJgSIA0ADC-1mV_7uCjZK2kIBxYN4sdb1L9PyAktQewf5Hse7QHaFJVBE3egdRZugQF0FeiWvI\;pt_pin=fangxueyidao\;\",\"RANDOM_DELAY_MAX= ##600\",\"TG_BOT_TOKEN=644204874\:AAETxq7Wr2-rXEijjKYJqn3vXsCijG6xm-w\",\"TG_USER_ID=490884842\",\"CUSTOM_SHELL_FILE=https://raw.githubusercontent.com/jianminLee/jd_scripts/main/docker_shell.sh\" -m \"/opt/jd_scri ##pts/logs:/scripts/logs\" ## 拼接参数 n = env['jd_scripts']['docker_container_prefix'] + name e = '\\\"JD_COOKIE='+cookie.strip()+'\\\",\\\"RANDOM_DELAY_MAX=600\\\",\\\"TG_BOT_TOKEN=' \ +env['jd_scripts']['tg_bot_token'] \ +'\\\",\\\"TG_USER_ID='+str(tgUserId)+'\\\"' m = '\\\"/opt/jd_scripts/logs/'+ str(tgUserId) +':/scripts/logs\\\"' command = ("cd "+ os.path.abspath('lua/') +" && lua "+ os.path.abspath('lua/dockerman.lua') +" -n " + n + ' -e ' + e + ' -m ' + m + ' -d ' + env['jd_scripts']['existed_docker_container_id']).replace(';','\\;') print(n+'\n'+e+'\n'+m+'\ncommand:'+command) result = common.run_command(command) for res in result: if res.startswith('id:'): #返回容器ID return res[3:] return -1 def stopAndDeleteContainer(containerId): command = 'cd '+os.path.abspath('lua/')+' && lua '+os.path.abspath('lua/dockerman.lua')+' -D '+containerId result = common.run_command(command) for res in result: if res == 0: #返回容器ID return 0 return -1 lua管理docker命令参数说明: { "-m, --mount", help = "容器挂载目录" }, { "-d, --duplicate", help = "容器ID 复制容易配置,复制后依然可以使用其他选项覆盖" }, { "-D, --delete", help = "容器ID 删除容器" }, { "-n, --name", help = "容器名称" }, { "-e, --env", help = "容器环境变量" }, 运行的话使用python serve.py。 frp服务配置 eSir的openwrt高大全版本固件中服务-frp内网穿透可以看到frp工具(服务器下面的端口是1234,和frps.ini中的bind_port一致): 添加一个客户端,自定义域名随便起,不用注册,内网使用: 服务器安装可以看之前的文章frp内网穿透,但是我这里使用nginx反向代理安装。 frps.ini配置: [common] bind_port = 1234 vhost_http_port = 8080 token = AAAAAAAAAA type = http custom_domains = orzlee.test //这个域名和客户端自定义域名一致 nginx反向代理配置: server { listen 80; server_name 你的域名; ###rewrite ^(.*) https://$server_name$1 permanent; charset utf-8; location / { proxy_pass http://127.0.0.1:8080; ##端口是frps.ini中的vhost_http_port端口 proxy_set_header Host orzlee.test; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; } ##location = /favicon.ico { access_log off; log_not_found off; } ##location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log off; sendfile off; location ~ /\.ht { deny all; } } server { listen 443 ssl http2; server_name 你的域名; ssl_certificate 证书目录/xxx.cer; ssl_certificate_key 证书私钥xxx.key; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; #屏蔽不安全的加密方式 ssl_prefer_server_ciphers on; index index.html index.htm index.php; charset utf-8; client_max_body_size 5M; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host orzlee.test; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; } ##location = /favicon.ico { access_log off; log_not_found off; } ##location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log off; sendfile off; location ~ /\.ht { deny all; } } 这样frp就通了,然后本地telegram-bot就可以接收webhook通知了。 结语 后续还有很多需要实现的功能,例如自动删除一个月以后的docker容器,因为可能cookie过期了,再继续跑下去也没有什么意义,还占用资源。等之后有时间在弄吧,折腾这个把openwrt弄挂了,还好有备份!
2021-03-03
LXK0301京东签到脚本-京喜工厂解决无法签到异常
前言 LXK0301大佬的京喜工厂自动签到脚本不知怎么一直提示:亲,活动太火爆了,请稍后再试吧!,基本无法使用,任务也不自动做了。 上网查了一下,全是说黑号,真蛋疼。因为脚本无法做任务什么的,但是手动完全没有问题,根本不是黑号,网上一股脑说黑号。 我就不信邪,app能做任务脚本就不行,肯定是脚本有问题。 2021-03-25 第二次更新,已经不需要自己抓包获取签名参数了,脚本会在每次执行时自动获取签名参数。已经联系作者,等作者更新吧!(推荐使用作者脚本,修复了参团问题) 2021-03-25更新,今天更新了下脚本,应该可以获取自己的签名参数使用了,有时间的朋友可以测试一下!仓库地址:jd_scripts-orzlee 2021-03-23更新,自己获取签名的方法可能无效,作者已经跟新脚本,目前使用我提供的签名参数可以正常做任务和领取电力,后续可能还需要研究。更新作者脚本即可! 原因 最根本的原因就是脚本发送请求链接签名有问题,这个好像只针对了部分用户,有的用户没问题,有的就会一直提示:亲,活动太火爆了,请稍后再试吧!。 起初发现问题是在手机上用QuantumultX抓包京喜APP,点击地上的零件,再抓包脚本,然后找出usermaterial/PickUpComponent请求来对比。开始我还以为是cookie问题,我替换cookie重试请求还是太火爆错误,再重发一下抓包京喜APP的请求,依然成功。再替换替换脚本请求的url参数为抓包app的,莫名奇妙的成功了。这个锅必须脚本背了! 脚本中decrypt函数是负责请求链接签名的,但是目前脚本有问题,很多签名key都是没有值的,因为根本没有获取值,只有少部分定义了默认值。来看一下代码(目前是1535行): function decrypt(time, stk, type) { if (stk) { const random = 'pmUmA8IyRcDp'; //这些常量其实每个用户都可能不一样 const token = `tk01wd4571d58a8nT0tkdXczeW94f5x4qjWs44kcPCTXeWKa2xXY+ZxHaOtbRxmyw6vrIF4RDFwwTUfwy1pIqNE0oyWW`; //这些常量其实每个用户都可能不一样 const fingerprint = 8410347712257161; //这些常量其实每个用户都可能不一样 //这个时间转换和现在的不一样,现在是new Date(time).Format("yyyyMMddhhmmssSSS");,转换结果不一样,加密出来也不一样 const timestamp = new Date(time).Format("yyyyMMddhhmmssS"); const appId = 10001; //这个是活动id 是固定的 const str = `${token}${fingerprint}${timestamp}${appId}${random}`; const hash1 = $.CryptoJS.HmacSHA512(str, token).toString($.CryptoJS.enc.Hex); //这里加密算法有可能不一样 let st = ''; stk.split(',').map((item, index) => { //下面的签名参数只有些默认值,很多都是空的,但是链接上又带了有效值,服务器验签估计不合法(但是有的用户却没有问题,搞不懂) st += `${item}:${item === '_time' ? time : item === 'zone' ? 'dream_factory' : item === 'type' ? type || '1' : ''}${index === stk.split(',').length -1 ? '' : '&'}`; }) const hash2 = $.CryptoJS.HmacSHA256(st, hash1).toString($.CryptoJS.enc.Hex); console.log(`st:${st}\n`) // console.log(`hash2:${JSON.stringify(["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)])}\n`) console.log(`h5st:${["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";")}\n`) return ["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";") } else { return '20210121201915905;8410347712257161;10001;tk01wa5bd1b5fa8nK2drQ3o3azhyhItRUb1DBNK57SQnGlXj9kmaV/iQlhKdXuz1RME5H/+NboJj8FAS9N+FcoAbf6cB;3c567a551a8e1c905a8d676d69e873c0bc7adbd8277957f90e95ab231e1800f2' } } 研究过程我就不再多说了,京东那边全是混淆的JS,真的很头疼,我弄了一下午才摸清楚他的逻辑。 整个流程大概是这样(官方的js混淆了,乱七八糟的就不贴代码了): 第一次进入活动页面会发送POST请求:https://cactus.jd.com/request_algo?g_ty=ajax,将返回结果储存在本地(这个默认应该没有有效期,但是京喜工厂里面的JS会设置有效期,过期会重新获取)。已经更新脚本自动获取签名参数了。 请求参数: { appId: "10001" expandParams: "" //fingerprint //pc浏览器我试过,就算拿到所有数据跑脚本依然不行,还是太火爆错误。所以保险还是去京喜APP抓包吧! fp: "5525701123405161" platform: "web" timestamp: 1614687205087 version: "1.0" } 接口会返回: { data: { result: { //加密函数 algo: "function test(token,fingerprint,timestamp,appId,algo){const random='jQ1SS0VI2Vuw';const str=`${token}${fingerprint}${timestamp}${appId}${random}`;return algo.SHA512(str)}" //加密token tk: "tk01w91541b51a8nWURUM3hiZk9HHRKep5j4FeOg/jHOQoGSDcsasdSOZ+83iz4uf/YBXHcK6xMIUqqv5/iJv6F0aooT5Nd3" } version: "1.0" message: "" status: 200 } } 这个接口会返回所有签名需要的参数,也就是脚本中decrypt中的参数,其实照着值样子都知道怎么替换了。 当前时间格式转换new Date(time).Format("yyyyMMddhhmmssSSS")这个时间是和链接参数中的'_time匹配'。 字符串拼接${token}${fingerprint}${timestamp}${appId}${random}。 第一次签名,将第三步的字符串用SHA或者MD5加密,这个主要参考第一步中的机密函数: function test(token,fingerprint,timestamp,appId,algo){ const random='jQ1SS0VI2Vuw'; const str=`${token}${fingerprint}${timestamp}${appId}${random}`; return algo.SHA512(str) } 这个函数提供了加密方法和随机字符串,官方直接用它做闭包函数第一次签名。 第一次签名完成后,开始第二次了,这个参数每个接口可能不同,它会按照请求url中的_stk参数来提供签名参数,例如&_stk=_time,pin,placeId,zone,那么就需要将参数拼接成time:xxxx&pin:xxxx&placeId:xxxx&zone:xxx这样子。stk参数的值也会包含在url中,例如: https://m.jingxi.com/dreamfactory/usermaterial/PickUpComponent?zone=dream_factory&placeId=1&pin=91DCBu8VvYt6rEdezHZ_VQ%3D%3D&_time=1614622722731&_stk=_time%2Cpin%2CplaceId%2Czone&_ste=1&h5st=20210302021842732%3B6099600123439161%3B10001%3Btk01wa66691cafa8nSmV1UDN2SWtZAiPI1uR1EAuPwYDaw36v9gQGhJz5Ac4h2cjfkeCQexVweqwa6%2BsjvERwkVU6wxTK%3Ba795we798qwe789789qe8262584d49f9449a1ce0194bb26c72049eef428f5e23e1043a641d&_=1614622722744&sceneval=2&g_login_type=1&callback=jsonpCBKR&g_ty=ls 第二次签名加密的算法是固定的,SHA256。 最后拼接: ["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";") 抓包 2021-03-04 更新可以免去抓包和修改脚本操作了: 一旦有一个设备的url签名参数更新,其他设备都会失效,如果多设备跑同一个账号要保持一直,否则还是会失败的!!! 我更新了脚本,不需要手动抓包了,QuantumultX可以添加url_sign_params.conf重写引用,其他平台可能需要自己写一下。然后删除京喜APP,重新下载后进入京喜工厂(最好重下APP,不然有可能还是太火爆异常,如果没有提示退出京喜工厂再进一次,多试试!): 折腾好了就只使用京喜APP进入京喜工厂(url签名参数会被京喜工厂里面的JS设置过期时间,过期会重新获取),以免从京东APP进入京喜工厂跳转到京喜APP重新获取覆盖,京东APP里面的京喜工厂获取的url签名参数也不能执行成功!只能使用京喜APP的url签名参数! 日志可以查看url签名参数: 以下为未更新之前的方法: 找到了问题就好解决了,抓包京喜APP一个请求就行了,抓包之前建议先删除APP,因为签名参数会存在本地,基本上弄不到了。删掉APP再进入京喜工厂之前,准备好抓包工具,IOS可以用QuantumultX、Surge等,PC抓包太多了,一搜一大把。 准备好抓包工具之后,进入京喜工厂,等待完全进入工厂,最好再捡下零件。没有报错就可以关掉抓包工具了。 搜索algo,找到签名参数请求: 请求JSON和响应JSON都要看,不然你不知道fingerprint参数,是一串数字,在请求JSON里: 复制返回请求中的参数: 修改脚本 脚本我修改了很多处,但是很简单: 新增一个获取url参数的函数: /** * 新增url参数获取函数 * @param url_string * @param param * @returns {string|string} */ function getUrlQueryParams(url_string, param) { let url = new URL(url_string); let data = url.searchParams.get(param); return data ? data : ''; } 时间函数与官方不一致,会导致签名结果错误(这函数是官方混淆JS里面扒出来的): /* 修改时间戳转换函数,京喜工厂原版修改 */ Date.prototype.Format = function (fmt) { var e, n = this, d = fmt, l = { "M+": n.getMonth() + 1, "d+": n.getDate(), "D+": n.getDate(), "h+": n.getHours(), "H+": n.getHours(), "m+": n.getMinutes(), "s+": n.getSeconds(), "w+": n.getDay(), "q+": Math.floor((n.getMonth() + 3) / 3), "S+": n.getMilliseconds() }; /(y+)/i.test(d) && (d = d.replace(RegExp.$1, "".concat(n.getFullYear()).substr(4 - RegExp.$1.length))); for (var k in l) { if (new RegExp("(".concat(k, ")")).test(d)) { var t, a = "S+" === k ? "000" : "00"; d = d.replace(RegExp.$1, 1 == RegExp.$1.length ? l[k] : ("".concat(a) + l[k]).substr("".concat(l[k]).length)) } } return d; } decrypt函数也要修改,我加了一个url参数,在拼接签名参数需要的值可以在url中拿(实在不想动太多代码,怎么方便怎么来吧): /* 签名函数 签名信息获取地址:https://cactus.jd.com/request_algo?g_ty=ajax 方法: POST 参数:{ appId: "10001" expandParams: "" fp: "5525701123405161" //fingerprint platform: "web" timestamp: 1614687205087 version: "1.0" } 返回结果:{data: { result: { algo: "function test(token,fingerprint,timestamp,appId,algo){const random='jQ1SS0VI2Vuw';const str=`${token}${fingerprint}${timestamp}${appId}${random}`;return algo.SHA512(str)}" //加密函数 tk: "tk01w91541b51a8nWURUM3hiZk9HHRKep5j4FeOg/jHOQoGSDcsasdSOZ+83iz4uf/YBXHcK6xMIUqqv5/iJv6F0aooT5Nd3" //token } version: "1.0" message: "" status: 200 } } 将返回参数替换: const random : data.result.algo字符串中的const random='xxxxxx' const token : data.result.tk const fingerprint : 通过抓包APP获取 const hash1加密方法(例子:algo.SHA512、algo.MD5,主要看签名信息获取地址返回结果data.result.algo) */ function decrypt(time, stk, type, url) { stk = stk || (url ? getUrlQueryParams(url, '_stk') : '') if (stk) { const random = '1gy8nc5oDM+y'; const token = `tk01w9a771c1aa8nd1k2NUo4UmNaahBe0/qh61gMNV9222JdJwlR0wyO9gko9dFTogSpvPIpqxstZJ9tl8JM9ONKNJWk`; const fingerprint = 5525701217505161; const timestamp = new Date(time).Format("yyyyMMddhhmmssSSS"); const appId = 10001; const str = `${token}${fingerprint}${timestamp}${appId}${random}`; const hash1 = $.CryptoJS.HmacSHA512(str, token).toString($.CryptoJS.enc.Hex); let st = ''; stk.split(',').map((item, index) => { // st += `${item}:${item === '_time' ? time : item === 'zone' ? 'dream_factory' : item === 'type' ? type || '1' : ''}${index === stk.split(',').length -1 ? '' : '&'}`; st += `${item}:${getUrlQueryParams(url, item)}${index === stk.split(',').length -1 ? '' : '&'}`; }) const hash2 = $.CryptoJS.HmacSHA256(st, hash1).toString($.CryptoJS.enc.Hex); console.log(`st:${st}\n`) // console.log(`hash2:${JSON.stringify(["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)])}\n`) console.log(`h5st:${["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";")}\n`) return ["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";") } else { return '20210121201915905;8410347712257161;10001;tk01wa5bd1b5fa8nK2drQ3o3azhyhItRUb1DBNK57SQnGlXj9kmaV/iQlhKdXuz1RME5H/+NboJj8FAS9N+FcoAbf6cB;3c567a551a8e1c905a8d676d69e873c0bc7adbd8277957f90e95ab231e1800f2' } } 最后一步了,搜索${decrypt(关键字,大概有8处要修改,主要是团长这部分多,主要还是没有解耦: 参团部分(每一个api不一样,只要剥离出&h5st=${decrypt(xxxxx就行了,单独拼接): //可获取开团后的团ID,如果团ID为空并且surplusOpenTuanNum>0,则可继续开团 //如果团ID不为空,则查询QueryTuan() function QueryActiveConfig() { return new Promise((resolve) => { //option中的url拉出来替换如下 let url = `https://m.jingxi.com/dreamfactory/tuan/QueryActiveConfig?activeId=${escape(tuanActiveId)}&_time=${Date.now()}&_=${Date.now()}&sceneval=2&g_login_type=1&_ste=1` url += `&h5st=${decrypt(Date.now(), '', '', url)}` const options = { 'url': url, //改成变量 "headers": { ... taskurl和newtasksysUrl函数部分: function taskurl(functionId, body = '', stk) { let url = `${JD_API_HOST}/dreamfactory/${functionId}?zone=dream_factory&${body}&sceneval=2&g_login_type=1&_time=${Date.now()}&_=${Date.now()}&_ste=1` url += `&h5st=${decrypt(Date.now(), stk, '', url)}` if (stk) { url += `&_stk=${stk}`; } ... function newtasksysUrl(functionId, taskId, stk) { let url = `${JD_API_HOST}/newtasksys/newtasksys_front/${functionId}?source=dreamfactory&bizCode=dream_factory&sceneval=2&g_login_type=1&_time=${Date.now()}&_=${Date.now()}&_ste=1`; if (taskId) { url += `&taskId=${taskId}`; } if (stk) { url += `&_stk=${stk}`; } //传入url进行签名,加入位置不要错了,不然有些签名参数获取不到值 url += `&h5st=${decrypt(Date.now(), stk, '', url)}` ... 大功告成,发到手机上或者node跑一下试试: 结果非常完美。 docker处理 手机端好办,docker麻烦一点,放到远程或者本地都行,具体看说明jd_scripts docker。docker提供了一个环境变量CUSTOM_SHELL_FILE(你也可以用CUSTOM_LIST_FILE挂载本地定时任务列表,只是更新要手动,要自动还是需要脚本的)可以跑远程shell脚本,jd_scripts docker说明中还有示例,照葫芦画瓢即可。我在github上弄一份自用,你可以参考或者fork一份自己用,地址:jd_scripts-orzlee。只需替换decrypt函数部分常量就好了,shell脚本最好看看我写的注释。然后在环境变量中加入shell脚本地址CUSTOM_SHELL_FILE=https://raw.githubusercontent.com/xxx/xxx.sh即可。 如果用我仓库的远程脚本,务必docker配置环境变量RANDOM_DELAY_MAX=600, 600的值可以自己设置非零正整数,意思是所有脚本每天随机延迟0-600秒执行。 结语 经过不懈努力,终于还是折腾好了,这半个月都是手动点击脚本,人家升级都比我快,没办法手动哪里有脚本那么按时呢!混淆JS浪费不少时间,眼睛都能看瞎。
2021年03月03日
7,197 阅读
75 评论
9 点赞
2021-02-24
LXK0301京东签到脚本-自动提交互助码
前言 今天24号,刚好是LXK0301助力码清除日期,晚上给忘记了,到中午才发现今天互助码重置。 瞬间感觉错误一个亿,之前就想过要折腾个自动提交互助码的脚本,就是太懒了。今天亡羊补牢,折腾折腾。有兴趣可以用阅读我之前的文章QuantumultX-京东签到撸京东豆、openwrt-docker部署lxk0301京东自动签到脚本。 安装Telegram-Cli 此安装环境是VPS,openwrt上安装用docker,当然VPS也可以使用docker! 科学上网必备,没有一个良好的网络环境为前提都是白折腾!!! docker安装(推荐,省去一大堆麻烦事): 镜像地址:ugeek/telegram-cli 安装镜像: docker create --name telegram-cli -e TZ=Asia/Shanghai -v 挂载本地目录:/root/.telegram-cli ugeek/telegram-cli:amd64 启动docker: docker start telegram-cli 执行telegram-cli命令行交互(先执行一次登陆,输入telegram注册的手机号码,号码记得加区号。) docker exec -it telegram-cli telegram-cli -N -W 以下为编译安装步骤(docker或者编译二选一即可): 克隆telegram-cli: cd /root/work/telegram ### 或者你自己想要存放的目录 git clone --recursive https://github.com/vysheng/tg.git && cd tg 编译安装 ### ubuntu sudo apt-get update sudo apt-get -y install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make ./configure make 如果编译安装出现如下错误: 解决方法: apt-get install -y libgcrypt20-dev libssl-dev ./configure --disable-openssl --prefix=/usr CFLAGS="$CFLAGS -w" make 申请Telegram APP Key并且登陆telegram-cli 首先到telegram-apps里申请一个telegram App key(登陆时电话号码记得加国际区号)。 复制Public keys: 创建一个文件保存Public keys: nano /root/work/telegram/bot_key.pub ###鼠标右键粘贴 ctrl+o ##保存 按完记得敲车键 ctrl+x ##退出 登陆telegram-cil /root/work/telegram/tg/bin/telegram-cli -k /root/work/telegram/bot_key.pub ###输入账号绑定的手机号码,记得加区号 ###输入telegram App收到的验证码 IOS锁屏就会提示offline,打开手机telegram app就会提示online。 测试一下命令: telegram-cil频道名称如果有空格用下划线代替。 发送命令格式/root/work/telegram/tg/bin/telegram-cli -W -e "msg 频道名称 命令" ### 发送一条统计当前互助码池命令 /root/work/telegram/tg/bin/telegram-cli -W -e "msg Turing_Lab_Bot /count_activity_codes" 回显信息比较乱,自己看手机或PC telegram APP Turing_Lab_Bot机器人 消息就好了。 编写脚本 把互助码准备好,编写脚本: ### 创建一个文件,保存脚本 nano /root/work/telegram/submit_activity_codes.sh 2021-05-08 优化加载会话列表,resolve_username 只加载需要发送命令的两个BOT,避免会话太多出现奇奇怪怪的问题。 2021-03-08 优化了定时任务脚本,速度更快,不会中断了,之前的脚本有问题,会经常中断(原因是因为脚本中执行发送消息命令太快-W参数加载消息会话列表没有完成就已经发出命令,导致命令出错!)。 复制以下内容,互助码自己替换,其他活动互助码自己添加(多个互助码用&拼接): #!/bin/bash telegramPath=TG Path #记得替换你telegram-cli目录/xxx/tg/bin ( echo "resolve_username TuringLabbot" echo "resolve_username LvanLamCommitCodebot" sleep 5 ### @Turing_Lab_Bot ###京喜财富岛 echo "msg Turing_Lab_Bot /submit_activity_codes jxcfd 互助码" ###京东闪购盲盒 echo "msg Turing_Lab_Bot /submit_activity_codes sgmh 互助码" ###京东环球挑战赛 echo "msg Turing_Lab_Bot /submit_activity_codes jdglobal 互助码" ###惊喜工厂 echo "msg Turing_Lab_Bot /submit_activity_codes jxfactory 互助码" ###东东工厂 echo "msg Turing_Lab_Bot /submit_activity_codes ddfactory 互助码" ###东东萌宠 echo "msg Turing_Lab_Bot /submit_activity_codes pet 互助码" ##种豆得豆 echo "msg Turing_Lab_Bot /submit_activity_codes bean 互助码" ###东东农场 echo "msg Turing_Lab_Bot /submit_activity_codes farm 互助码" ### @Commit_Code_Bot ###JD签到领现金 提交助力码 echo "msg Commit_Code_Bot /jdcash 互助码" ###JD签到领现金 提交助力码 echo "msg Commit_Code_Bot /jdcrazyjoy 互助码" echo "safe_quit" ) | ${telegramPath}telegram-cli -D -D参数关闭了输出,调试的时候可以删除该参数(虽然没什么用,因为你命令发出去还没有等回显就已经结束命令了)。 docker 用户将最后一行脚本替换成) | docker exec -i telegram-cli telegram-cli -N,删除telegramPath=TG Path #记得替换你telegram-cli目录/xxx/tg/bin即可 保存脚本 ctrl+o ##保存 按完记得敲回车键 ctrl+x ##退出 赋予脚本可执行权限 chmod +x /root/work/telegram/submit_activity_codes.sh 测试的时候记得注释大部分命令,留一到两个就行了,频繁提交小心被Bot Ban号。 bash /root/work/telegram/submit_activity_codes.sh 看看手机接收到的通知,一般接收到通知无非就是提交成功或助力池已满。 添加crontab定时任务 助力池每次清空日期为每月1,8,16,24号,延迟10分钟后执行: crontab -e 10 0 1,8,16,24 * * bash /root/work/telegram/submit_activity_codes.sh 结语 其他Bot签到什么的可以举一反三。 这下一劳永逸,省的忘记错过一个亿。最近京东活动也比较多,没有助力活动任务很难完成,助力才是京东活动的灵魂。
2021年02月24日
9,356 阅读
233 评论
7 点赞
2021-02-24
Emby公益服-上万部电影电视剧免费看
前言 过年这段时间比较无聊,找找电影看,之前从其他影视站找片源然后使用Airplay投放到AppleTV观看。说实话这些影视站片源广告多不说,质量不好,投影到电视上勉强能看,体验很差。 无意中Google到Emby终点站,这是个Telegram群组,家庭影院从这里开始。 加入Emby终点站 Emby终点站是目前片源最多、服务器最多的Emby公益服了。注册很严格,需要进行考核,考核随机40道题目,90分及格,考核失败必须72小时以后才能再次考试(需要每日签到获取积分,40积分考核一次,每次签到1-5积分不等。telegram-自动签到有能力可以实现自动签到)。而且及格后不一定立即能注册,需要等待开放注册。 2021-02-26(元宵节)会开放注册,开放时间随机 加入群组 群组链接:Emby终点站。 加入群组后一点要验证,验证失败两分钟秒后可以再次验证(最好等待验证通过后再进行考核,不然考核到一半Bot提示没有加入群组就很浪费时间了!)。 创建账号 考核Bot: EmbyPublicBot。 添加机器人后使用/create命令创建账号,如果没有考核会提示考核: 考核有点难度,一定要多看Emby终点站-Wiki,再结合Google,失败一次可是要72小时之后才能重新考核的。并且需要40积分才能重新考核。 毕竟是公益服,这样能拦下来大多数机器人注册,**[Emby终点站-Wiki][Emby终点站-Wiki]**多看几遍,写的很详细了,操作步骤都是图文结合。考核配合google,群组公告最好都看一下,管理很严格,容易Ban号。 如果你考试通过了,等待注册开放时间,再私聊[EmbyPublicBot][EmbyPublicBot],使用`/create`命令创建账号: ![创建账号.jpg](https://www.orzlee.com/usr/uploads/2021/02/2294919326.jpg) 按提示输入,创建成功后会返回服Emby务器地址和随机密码(要修改密码必须登陆到Emby客户端后修改,由于各个服务器之间不同步,所以每个服务器都需要单独修改密码)。 客户端 Emby终点站-Wiki已经包含很多平台客户端操作,我目前使用AppleTV,苹果设备Infuse6无疑是最好的了,就是价格感人。Emby官方客户端DTS音频是个问题。 infuse最好购买终身版Pro,可以先选年度订阅免费试用一个月后再做打算,以下是添加Emby服务器操作步骤: Infuse同步很坑爹,必须保持在视频库页面等待同步完成才行,中途退出APP或者浏览器他APP内页面、手机黑屏那么重来一次。像Emby终点站这样的大型公益服,片源很多最好找个好点的梯子,快的话半小时以内一个服务器的资源就同步完了。Emby官方客户端不存在同步问题。最坑爹的是手机同步完了到AppleTV又要同步一次!!! 添加的emby服务器越多,时间越长,好在第一次同步完后,之后更新会缩短不少时间,还是要看服务器新片更新量。 搜索功能一定要等待同步完成后才能用,否则是搜索不到emby服务器资源的 如果你添加多个Emby服务器,难免有重复的影片,那么影片也会重复显示的。这样有个好处,如果服务器1挂了或者网络不畅可以选第二个片源播放,麻烦的就是同步而已。 一直提示xxx目录错误多试几次,或者换其他emby服务器、梯子、取消合集,播放列表后面的勾,然后刷新视频库即可。一般来说尽量换emby服务器线路或者梯子。CF线路限制国家了,仅限 中国大陆及港澳台、日本、韩国、新加坡、澳大利亚、新西兰 的 IP 访问。( 使用 GCP 自建梯子的基本都是美国广播 IP,这些可能不能访问 )。就算其他公益服也差不多。 AppleTV Infuse 如果手机也使用Infuse,默认会通过iCloud同步所有emby服务器信息,只需点击APP右上角齿轮-媒体库中等待同步即可(千万别让AppleTV睡眠了,没事摸摸遥控器,或者干脆设置不自动睡眠)。 AppleTV infuse电影墙还是很不错的: 点击对应的服务器可以查看该服务器上的所有影片: 其他Emby公益服 卷毛鼠 Bot:卷毛鼠Bot 使用/register命令可以创建账户,这个公益服不用考试,直接创建账户即可。 普拉斯 通知频道: 普拉斯影业资源发布 这个公益服没有开放私人注册,作者之前尝试过,但是人数一多会对服务器造成很大压力放弃了。看频道公告使用公共账号。该公益服与很多机场合作,如果使用合作机场会有机场专线,可提供私人账号注册,但是机场服务器片源与公益服同步就不知道什么时候一次了,机场一般也不会保证,毕竟机场不是专门弄影片给用户看的。 AGA公益服(中国电信可直连观看) https://emby.plusmedia.site 端口: 443 CF公益服(仅限挂代理观看) https://emby-cf.plusmedia.site 端口: 443 备用服1: https://emby.xeton.dev 端口: 443 备用服2: https://jellyfin.xeton.dev 端口: 443 备用服3: https://movie.xeton.dev 端口: 443 备用服4: https://servers.xeton.dev 端口: 443 账号:普拉斯影业 密码:plusisbest 注: 使用方法见上图 (#备用服 仅限 Emby, Infuse 等客户端挂梯子登录观看) otakudrive 群组:OtakuDrive-EMBY https://emby.otakudrive.life (AGA) https://emby.neko.edu.rs (Direct HTTPS) http://emby.ok.edu.hk (Direct Non-HTTPS) 有NSFW内容 用户名: Guest 密碼: 1234 无NSFW内容 用户名: Guest2 密碼: 1234 客戶端: http(s)://(server address/伺服器链接) port: 443/80 公共账号唯一的缺点就是播放记录很乱,比如说你看了一半的电影,下次再看没法接着播放了(除非你记得播放时间,手动跳转),因为可能其他人也看了这部影片。播放记录也是乱七八糟的。 结语 公益服大多数片源质量很高,片源刮削也比较完整,虽然有些中文字幕没有刮削完整,凭借Infuse的刮削能力也可以很方便的获取字幕。要使用公益服还是自己准备好梯子,直连不能保证全天时间段都流畅播放。公益服承诺用不收费,都是大佬们自掏腰包。三个emby公益服加一次片源更加丰富了,最新电影肯定没有,因为公益服一般只折腾优质片源。 配合AppleTV或其他盒子,一个家庭影院就轻松完成了,完全省去NAS,自己折腾电源刮削都让人崩溃,耗时费力。
2021年02月24日
62,710 阅读
28 评论
18 点赞
1
2
3