OrzLee - orzlee
type: channel
link: https://www.orzlee.com/author/1/
description: orzlee
items: 通过USB扩展坞代替KVM切换显示器输入源
items: 解决LG显示器无法通过DDC/CL切换输入源
items: JAVA RMI GDC每小时触发Full GC
items: 探索ChatGPT、NewBing和Google Bard：我与大型语言模型的初体验
items: telegram-終點站emby自动签到
items: 折腾京东APP签名-获取wskey相关签名参数
items: 京东cookie自动更新维护
items: Nginx SNI 分流（端口复用）使用Xray+VLESS+XTLS
items: openwrt-安装oh-my-zsh
items: openwrt-通过telegram bot自动创建启动jd-scripts docker容器

通过USB扩展坞代替KVM切换显示器输入源
type: item
date: 2025-03-04T00:34:00+08:00
description: 前言 入了台新电脑，揪心事情就来了。两台显示器、一套键鼠怎么在都开机的情况共用两台主机呢？而且还有来回切换的场景。 上网查，发现有东西叫KVM切换器，原理就是两台主机显示接口接入KVM的显示输入接口，USB输入接口，然后KVM在出两根视频线给显示器。切换的时候应把A主机视频信号切断，通过硬件让显示器接入B主机输出的视频信号。线多点无所谓，切换过程耗时也能接受，继续查各网友使用反馈。得到的结论就是国内这东西无异于工业垃圾... 二进二出KVM对高帧率支持有限，EDID（在Windows下切换屏幕后系统桌面程序窗口还是之前一样，没有EDID切回就乱了，mac就算拔掉一个显示器，插回去还会恢复...）寥寥无几，更别提各种黑屏闪屏乱七八糟的问题，倒是价格三五百也还好。反正网上没有说非常满意的，最多也就是个能用。 灵机一动，我买个USB切换器，写个程序监测鼠标键盘插入拔出，通过DDC/CI直接切换显示器输入源不久OJBK了吗？买个KVM我实在都没真心满意的。两台4K显示器，LG的144HZ，另一台60HZ。要放弃144HZ选择还多点，不然没办法。而且支持EDID只有一款双HDMI的支持，其他不支持。 搞起 显示器必须支持DDC/CI，不支持都不用搞了。大厂应该都支持，小作坊就不保证了。Dell、LG两个在查资料过程还是看到不少关于这两显示器问题的。下个control_my_monitor打开看看吧。 我本来想用go来写的，结果go在winodws监听USB输入输出事件没有很简单的方法，不成熟。不过找了这么多资料总有点结果，nodejs有usb包支持usb热插拔事件。既然能支持，还管它什么语言，能解决问题就是好语言。 当USB切换器切换当前主机的键盘和鼠标USB会拔出，反之另一台会插入。基本逻辑就是插入鼠标键盘，DDC/CI切换显示器输入源为当前主机视频接口，两台主机一边一套，这样理论上支持无限台主机数量。其实只要有切换器，不一定要鼠标或者键盘，随便插个什么USB都行。 LG显示器DDC/CI切换输入源比较麻烦，可以看我上一篇文章解决LG显示器无法通过DDC/CL切换输入源，其他显示器可以看看输入源端口代码。 windows这边好弄，但是mac有点麻烦。因为macBetterDisplay只能登陆后启动，不能开机直接启动（可能有办法解决，没深入研究）。然后通过USB扩展坞扩展的视频接口是个残缺DDC/CI接，没法切换输入源，调节他亮度声音倒没什么问题。难道又买一根type-C to HDMI的线？另一台直连HDMI接口的显示没有问题。 干脆就到windows上跑nodejs好了，反正只有两台主机，插入就切windows主机，拔出切回去。 我用到了winddcutil（control_my_monitor也可以，无非就是换下命令）。nodejs需要安装usb包。 直接上代码： const usb = require('usb').usb; const { exec } = require('child_process'); const os = require('os'); // const fs = require('fs'); // const path = require('path'); const platform = os.platform(); // const LOG_FILE = path.join(__dirname, 'usb_switch_monitor.log'); const DEVICE_VENDOR_ID = 1507; const DEVICE_PRODUCT_ID = 1552; const WINDOWS_DIR = 'D:\\xxx\\xxx\\'; // console.log('USB hot plug switch monitor service started...'); // console.log(usb.getDeviceList()); // 写入日志函数 // function writeLog(message) { // const timestamp = new Date().toISOString(); // const logMessage = `[${timestamp}] ${message}\n`; // fs.appendFile(LOG_FILE, logMessage, (err) => { // if (err) { // console.error(`无法写入日志: ${err}`); // } // }); // } //执行命令函数 async function executeCommand(command) { exec(command, (error,…

解决LG显示器无法通过DDC/CL切换输入源
type: item
date: 2025-03-01T22:30:00+08:00
description: 前言 LG虽然是大厂，但是显示器DDC/CL却无法设置输入源。声音亮度等设置却没有问题，这是我目前最想要的功能。我有两个系统，共用两个显示器，不想买二进二出KVM切换器。国内这些KVM也就是个能用的程度。高刷和EDID几乎没有，就算有也不是所有接口都支持。 所以我有个想法，让系统来通过显示器DDC/CI控制切换，我再买个USB二进二出切换器，共用键盘和鼠标。写个程序监听USB设备，插入就通过电脑执行DDC/CI切换显示器输入源。 这样比KVM二进二出切换器多了很多优点： 少了连根视频线 显示器和主机直连兼容性更好 USB切换器便宜 支持高刷等显示器特性（EDID的话我目前切换没有乱桌面布局，我不确定） 我的两台显示器，一台是AOC，好多年了，DDC/CI没有任何问题。还有台LG 27GP95RP，这两年入的，DDC/CL能控制大部分功能，唯独输入源控制不了。国内LG DDC/CI相关讨论都很少，国外还是有讨论关于LG显示器DDC/CI的问题。 开搞 DDC/CI不支持，国外有大佬通过GPU来控制显示器切换。我不太懂，你可以看看这篇文章。虽然里面只列出少部分LG显示器型号，但是自己试试说不定也支持，27GP95RP上面就没有列出，但是确实可行。 先上输入源代码，其实很好区分，你先确定你的LG显示器有什么接口，例如两个HDMI和一个DP，HDMI就是0x90开始递增，DP接口就是0xD0递增，至于type-c就要自己找找了，应该是通过0xD0来递增，我这台显示器没有。 Input Source Value MONITOR_AUTO 0x0 MONITOR_DP1 0xD0 MONITOR_DP2 0xD1 MONITOR_DP3 0xD2 MONITOR_USB_C 0xD2 MONITOR_HDMI1 0x90 MONITOR_HDMI2 0x91 英伟达显卡可以通过NVapi-write-value-to-monitor项目来执行输入源切换。 你只需要修改两个参数，第一个参数0来选择显示器的序号，第二个参数是显示器的输入源（这里是切换到HDMI1，你要修改成自己想切换的输入源，看上面代码）。后面的0xF4 0x50不能动。我的是AMD显卡，具体显示器序号和他功能可以去项目里看作者的说明。 writeValueToDisplay.exe 0 0x90 0xF4 0x50 ADM显示可以通过amdddc-windows项目来执行输入源切换。可以执行文件在issue中找到，作者上传的txt文件，下载下来修改后缀exe即可。 先通过detect命令来查看显示器位置： amdddc-windows.exe detect 我这里适配器索引5，LG显示器是0，要切换的端口DP1 0xD0。你只用修改最后三个参数。下面通过命令来切换输入源到DP1接口： amdddc-windows.exe --i2c-source-addr 0x50 setvcp 5 0 0xD0 intel可以看看这个issue MAC OS mac os可以使用BetterDisplay或者m1ddc来控制，同一个作者。m1ddc我在M4 pro上使用过了没用，不管是不是LG显示器都无法切换，没有做过多研究。 BetterDisplay没有问题，但是发现了一个坑。如果使用扩展坞带的视频接口，那么大概率是残血DDC/CI，或者干脆不支持的。网上资料说是由于usb占用了两个引脚，导致功能残缺。我这边是发现不能切换，但可以调亮度和声音，这还是另一台支持DDC/CI切换输入源的显示上测试的。所以要转视频接口建议买质量好的type-C直接转HDMP或者DP，不要附带其他扩展接口。LG用HDMI直连所有功能都正常。 BetterDisplayLG显示器输入源：DisplayPort 1: 208, DisplayPort 2: 209, HDMI 1: 144, HDMI 2: 145, USB-C / DP 3: 210。CLI文档可以看文档。 显示器设备名称 UUID等信息去APP中可以看到，命令行的话看文档找找。 除了namelike，还有name uuid都可以指定显示器，ddcAlt就是输入源端口代码了。非LG显示器切换去掉两个参数Alt字母就好了--ddc=15 --vcp=inputSelect。 /Applications/BetterDisplay.app/Contents/MacOS/BetterDisplay set --namelike=ABC --ddcAlt=208 --vcp=inputSelectAlt 如果安装了betterdisplaycli可以简化命令，但是BetterDisplay不仅要装，还要启动，否则不行： betterdisplaycl…

JAVA RMI GDC每小时触发Full GC
type: item
date: 2024-05-06T21:16:00+08:00
description: 前言 最近倒腾Java，发现JVM并行收集器在还有大量堆内存的时候就开始触发老年代的回收，通过GC日志发现每小时都会执行GC和Full GC回收，回收是通过System.gc()调用。 那每小时都调用一次Full GC，我添加启动参数-Xms11g -Xmx11g分配11G堆内存只是为了好看吗？每次Full GC耗时在600ms，并行收集器老年代内存使用还不足5%，真是发神经了！ 过程就不做记录了，无聊又蛋疼。以下是在使用了RMI或者其他NIO对象的情况。 RMI DGC每小时触发一次Full GC 原因：DGC代码中调用System.gc()导致并行收集器触发Full GC。 解决办法： 修改DGC调用System.gc()执行时间，默认一小时，单位ms。启动参数添加： -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 禁止程序中的System.gc()，添加启动参数： -XX:+DisableExplicitGC 使用支持并发的收集器（CMS、G1、ZGC或Shenandoah），并且添加启动参数： -XX:+ExplicitGCInvokesConcurrent 方法1，治标不治本，延长时间触发Full GC会导致STW时间更长，可以配合并行收集器使用-XX:+ExplicitGCInvokesConcurrent来控制频率。 方法3，启用-XX:+ExplicitGCInvokesConcurrent参数可以尝试在垃圾收集时使用并发收集来减少STW时间，从而提高应用程序的响应性。 不建议使用-XX:+DisableExplicitGC来限制System.gc()。 因为从Java 7开始，Java提供了基于NIO的RMI实现，称为NIO-based RMI。这种实现利用了NIO的非阻塞I/O模型，能够更高效地处理大量的并发连接，减少了线程资源的消耗，并提高了性能和可伸缩性。通过使用NIO，NIO-based RMI能够更好地适应高并发和大规模的网络通信场景。 DirectByteBuffer是一种在堆外内存中分配的ByteBuffer，它与NIO密切相关，因为它可以直接映射到操作系统的内存中，从而避免了在Java堆和本地内存之间进行复制。在NIO编程中，使用DirectByteBuffer可以提高I/O操作的性能和效率，特别是在处理大量数据时。在基于NIO的RMI实现中，使用NioServerSocketChannel和NioEventLoopGroup通常涉及到DirectByteBuffer的使用。 虽然 DirectByteBuffer 对象本身是由 JVM 管理的，它们存储在 Java 堆内存中，但是 DirectByteBuffer 对象所持有的实际数据存储在堆外内存中。 JVM 通过 DirectByteBuffer 对象来管理对堆外内存的访问和操作。当 DirectByteBuffer 对象被垃圾回收时，它所持有的堆外内存也会随之被释放。 因此，触发 Full GC 通常是为了回收已经失去引用的 DirectByteBuffer 对象，进而释放掉它们所占用的堆外内存。 Full GC 在回收过程中会扫描整个堆内存，包括其中的对象和引用。当发现 DirectByteBuffer 对象已经没有引用指向时，JVM 就会将其标记为可回收， 待下次 Full GC 执行时进行回收。这样，间接地通过 Full GC 回收了 DirectByteBuffer 对象，也就释放了相应的堆外内存。 如果禁用了System.gc()，那么不会及时的清理 DirectByteBuffer 或者其他 NIO 对象导致堆外内存也不会释放。虽然最后也可能因为JVM堆内内存不足触发Full GC 来释放，但没必要冒险。参阅 监控程序调用System.gc()堆栈 可以使用 async-profiler 跟踪System.gc调用者： 预先开始分析： profiler.sh start -e java.lang.System.gc <pid> 发生一种或多种System.gc情况后，停止分析并打印堆栈跟踪： --- Execution profile --- Total samples : 6 Frame buffer usage : 0.0007% --- 4 calls (66.67%), 4 samples [ 0] java.lang.System.gc [ 1] java.nio.Bits.reserveMemory [ 2] java.nio.DirectByteBuffer.<init> [ 3] java.nio.…

探索ChatGPT、NewBing和Google Bard：我与大型语言模型的初体验
type: item
date: 2023-04-04T23:20:00+08:00
description: 前言 最近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，你想想这个消耗有多大。个人使用都能感觉到肉疼，但是公开使用那就更不用说了。你看现在网上大把的免翻墙免费用Ch…

telegram-終點站emby自动签到
type: item
date: 2022-01-05T17:14:00+08:00
description: 前言 之前写过一篇文章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(an…

折腾京东APP签名-获取wskey相关签名参数
type: item
date: 2021-09-06T19:28:00+08:00
description: 前言 前几天随手撸了个自动上传京东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就好了。00…

京东cookie自动更新维护
type: item
date: 2021-09-02T17:01:00+08:00
description: 前言 薅羊毛门槛越来越高了，京东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…

Nginx SNI 分流（端口复用）使用Xray+VLESS+XTLS
type: item
date: 2021-04-13T04:36:00+08:00
description: 前言 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_protoc…

openwrt-安装oh-my-zsh
type: item
date: 2021-03-14T14:34:00+08:00
description: 前言 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总感觉太单调了，敲起来不顺手。

openwrt-通过telegram bot自动创建启动jd-scripts docker容器
type: item
date: 2021-03-13T22:53:00+08:00
description: 前言 使用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 创建，附加只会…