MiraiForum

    • 注册
    • 登录
    • 搜索
    • 热门
    • 最新
    • 未解决
    • 标签
    • 群组
    • 友情链接
    1. 主页
    2. Karlatemp
    3. 主题
    • 资料
    • 关注 0
    • 粉丝 13
    • 主题 16
    • 帖子 389
    • 最佳 50
    • 有争议的 1
    • 群组 3

    Karlatemp 创建的主题

    • Karlatemp

      mirai-console-junit5
      项目发布 • • Karlatemp

      1
      0
      赞同
      1
      帖子
      426
      浏览

      Karlatemp

      JUnit5 Support for miria-console plugins!

      Project: mirai-console-junit5
      使用手册: 点我

      在 gradle 中编写 mirai-console 插件的测试单元!

      如何使用:

      添加

      plugins { id "com.kasukusakura.mirai-console-junit5" version "0.0.2" }

      预览图

      3a27702c-2571-4c84-96df-3eee608f788b-image.png

    • Karlatemp

      (WIP) java-flatlaf-style-setup ----- Java GUI look and feel setup
      其他项目发布 • • Karlatemp

      1
      1
      赞同
      1
      帖子
      184
      浏览

      Karlatemp

      优化 java gui 主题(显示)

      Maven: com.kasukusakura:java-flatlaf-style-setup

      Download (.mirai2.jar)

      GitHub: KasukuSakura/java-flatlaf-style-setup

      Snapshot:

      726e1f7d-96a9-4179-a07d-2f6967a53f1a-image.png

    • Karlatemp

      MiraiForum Markdown 额外语法
      官方公告 • • Karlatemp

      1
      3
      赞同
      1
      帖子
      1387
      浏览

      Karlatemp

      本帖子将展示 MiraiForum 的额外 markdown 语法

      隐藏文字

      这里是MiraiForum

      +=[要隐藏的内容]=+ 自定义文本颜色

      Colored Text Here

      %(#66ccff)[Colored Text Here] 折叠内容 ...

      要折叠的内容

      注: 咱不支持嵌套引用

      > ^fold > > 要折叠的内容 >
    • Karlatemp

      Mirai解密 - 2022/4/1 活动
      摸鱼区 • • Karlatemp

      12
      10
      赞同
      12
      帖子
      2457
      浏览

      Karlatemp

      欢迎来到Mirai解密 活动详细 持续时间 7天 开始时间 四月一日

      游戏形式类似信息安全中的ctf比赛,但是题目的设置并不完全是ctf的类型,这是为了让不会信息安全的玩家也能通过搜索引擎和动脑来参与到游戏中。

      前三位完成解密的玩家可以获得奖品一份,游戏为个人参加,请勿泄漏各种信息给其他人

      活动地址

    • Karlatemp

      MCL 无法使用的相关解决方法 - 2022/3/25
      官方公告 • • Karlatemp

      16
      5
      赞同
      16
      帖子
      6955
      浏览

      Karlatemp

      由于 gitee 停止 raw 的直接访问, 我们已经将 mirai-console-loader 的数据文件从 gitee 搬出

      要继续使用使用 mirai-console-loader, 您需要进行以下的配置

      1. 打开 $MCL/config.json
      2. 找到

      "mirai_repo": "....."

      将其地址修改为以下地址中的一个 (注意不要删除双引号 "" (英文半角))

      https://repo.mirai.mamoe.net/keep/mcl https://mirai.mamoe.net/assets/mcl https://mcl.repo.mamoe.net/ https://repo.itxtech.org/
    • Karlatemp

      Java 动态模块系统 | Java dynamic module system
      技术交流板块 • • Karlatemp

      1
      2
      赞同
      1
      帖子
      408
      浏览

      Karlatemp

      前言

      在使用高版本的时候, 总会不可避免的接触到模块系统, 比如反射操作 java.base 已经十分困难. 既然 JDK 内部可以享受到模块的保护, 那么我们自己的代码是否也可以享受到模块系统的保护呢

      当然可以,而且也不是非常麻烦。

      使用模块,你将面对以下问题

      得到反射保护, 外部代码将不能通过反射强行修改/调用私有成员 更严格的访问控制, 不能直接访问非 required 的模块 失去 --add-opens=....=ALL-UNNAMED 的归属判断 需要专门的 ClassLoader / 需要自行实现 ClassLoader

      使用模块的适用情况

      需要编写严格的附属(插件)系统 需要保护自身代码/保护自身内存空间 觉得弄着好玩 定义一个模块

      注: 此处的定义指的是, 通过运行时代码在运行时定义一个模块.
      而不是大多数资料说的直接写一个 module-info.java

      要定义一个模块, 首先需要一个模块的描述符文件 (ModuleDescriptor), 可以从以编码文件读取 (ModuleDescriptor.read(InputStream) <- module-info.class), 也可以在运行时动态生成一个(ModuleDescriptor.newModule("name_of_module").build())

      jvm 通过包来区分模块, 而一个模块的全部包都需要提前指定, jvm 才会为这些包分配到一个模块内

      var moduleDescriptor = ModuleDescriptor.newModule("my.custom_module") .packages(Set.of("io.github.karlatemp.jmse.main")) .exports("io.github.karlatemp.jmse.main") .build();

      这里我们已经拥有了一个模块的描述符, 现在我们还需要一个模块描述的引用, 以及一个模块查找器以让 jvm 可以找到我们的模块

      var myModuleReference = new ModuleReference( moduleDescriptor, null ) { @Override public ModuleReader open() throws IOException { throw new UnsupportedOperationException(); } } var myModuleFinder = new ModuleFinder() { @Override public Optional<ModuleReference> find(String name) { if (name.equals(moduleDescriptor.name())) { return Optional.of(myModuleReference); } return Optional.empty(); } @Override public Set<ModuleReference> findAll() { return Set.of(myModuleReference); } };

      最后,定义一个模块

      var bootLayer = ModuleLayer.boot(); var myConfiguration = bootLayer.configuration().resolve( myModuleFinder, ModuleFinder.of(), Set.of(moduleDescriptor.name()) ); var classLoader = ClassLoader.getSystemClassLoader(); var controller = ModuleLayer.defineModules( myConfiguration, List.of(bootLayer), $ -> classLoader ); Class.forName("io.github.karlatemp.jmse.main.ModuleMain", false, classLoader) .getMethod("launch") .invoke(null); ServiceLoader / Class.forName(Module, String)

      还记得 需要专门的 ClassLoader / 需要自行实现 ClassLoader 吗, 虽然在上文已经成功定义了一个模块,但是只要使用 ServiceLoader / Class.forName(Module, String), 那么将无法找到对应的类, 因为一般的 ClassLoader 并没有专门处理动态加载的模块

      Analyze

      通过进行调用分析, 最终可以发现以上两个东西最终都进入到了下面的方法

      public class ClassLoader { final Class<?> loadClass(Module module, String name) { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { c = findClass(module.getName(), name); } if (c != null && c.getModule() == module) { return c; } else { return null; } } } protected Class<?> findClass(String moduleName, String name) { if (moduleName == null) { try { return findClass(name); } catch (ClassNotFoundException ignore) { } } return null; } }

      不难发现, 由于默认没有处理模块, 导致指定搜索模块的时候将搜索不到动态定义的模块

      而 jdk.internal.loader.ClassLoader$AppClassLoader 并没有处理通过 ModuleLayer.defineModule 定义的模块, 于是也不能直接将模块定义到系统类加载器

      自行实现类加载器

      自行实现类加载器十分简单,只需要

      public class MyCustomClassLoader extends URLClassLoader { String moduleName; @Override protected Class<?> findClass(String moduleName, String name) { // System.out.println("Find class: " + moduleName + "/" + name); if (this.moduleName.equals(moduleName)) { try { return findClass(name); } catch (ClassNotFoundException ignored) { } } return super.findClass(moduleName, name); } } 使用 JDK 内置的类加载器

      只需要实现 ModuleReference.open(): ModuleReader, 然后使用

      var controller = ModuleLayer.defineModulesWithOneLoader( myConfiguration, List.of(bootLayer), ClassLoader.getSystemClassLoader().getParent() ); var classLoader = controller.layer().findLoader(moduleDescriptor.name());

      即可使用 JDK 内置的内加载器

      完整参考 java-module-system-explore BootModuleByStandard.java MyCustomClassLoader.java
    • Karlatemp

      GitHub PullRequest 自动审核合并
      技术交流板块 • • Karlatemp

      1
      0
      赞同
      1
      帖子
      506
      浏览

      Karlatemp

      众所周知, github actions 可以完成很多自动化任务, 比如代码持续CI, 版本发布自动化, new issue 内容检查等.

      当然,github actions 也可以用作 PR 自动审查合并, 不过, 要完成这些需要一些额外的配置..

      首先需要知道的是, on: pull_request 的 workflow 是只有 readonly 的权限的, 这也就意味着通过 on: pull_request 发起的 workflow 除了读取已公开的内容之外什么都干不了. 包括访问 ${{ secrets.XXXX }} 也是不被允许的

      需要完成自动合并, 需要更高权限(也意味着更危险的) workflow, pull_request_target

      pull_request_target 与 pull_request 的用法基本一致, 但是主要有以下的区别

      actions/checkout@v2 会签出到被 PR 的分支(也就是源仓库的内容), 而不是经过 PR 修改后的内容

      pull_request_target 拥有 write 权限, 可以写入源仓库, 访问 ${{ secrets.XXX }} (这是 pull_request 所不允许的)

      知道以上的主要区别之后就可以编写 PR 自动审查了

      首先需要获取源仓库的内容 (当然绝对不可以直接 checkout!!!)

      可以选择在当前目录来获取修改,或者创建一个新文件夹来获取修改

      # Way 1 - uses: actions/checkout@v2 with: ref: pull/${{ github.event.pull_request.number }}/head path: the_pr # Way 2 - run: git fetch origin pull/$PR_NUM/head:THE_PR env: PR_NUM: ${{ github.event.pull_request.number }}

      然后是提取该 PR 的修改

      BASE_SHA: ${{ github.event.pull_request.base.sha }} git rev-list --count "$BASE_SHA..THE_PR" > tmp/count cat tmp/count git --no-pager diff "$BASE_SHA..THE_PR" --no-color --output tmp/change-diff git --no-pager diff "$BASE_SHA..THE_PR" --name-only --output tmp/name-changed

      此时

      tmp/name-changed 存储着该 PR 修改的全部文件的文件路径 tmp/change-diff 则为 PR 与 base 的 diff 文件 tmp/count 为一个数字, 该数字代表 base 与 pr 直接相差的 commit 数量

      在进行一系列 PR 审核之后, 需要将审核结果返回出去 (Merge 或者 Reject(Request change))

      需要用到的两个 REST API 为 Create a review for a pull request, Merge a pull request

      通过 Create a review for a pull request 可以对一个 PR 进行自动审查, 可以是 Approve 或者 Reject(Request changes), 亦或者只是简单的评论 Comment

      然后就可以通过 Merge a pull request 完成全自动 PR 合并了, 唯一需要给定的参数 sha 为 PullRequest 的最后一个 commit 的 id, 可以通过执行 git rev-parse THE_PR 获得该参数的值

      额外话: 使用 ${{ secrets.GITHUB_TOKEN }} 合并后, 不会触发 workflow on: push
      如果需要 merge commit 也执行 on: push 的, 请使用 ${{ secrets.PR_REVIEWER_TOKEN }} 代替 GITHUB_TOKEN

      参考与应用

      auto-review-and-merge.yml check-pr.js
    • Karlatemp

      silk-codec -- 转换音频到 tx silk v3 格式
      其他项目发布 • • Karlatemp

      1
      0
      赞同
      1
      帖子
      527
      浏览

      Karlatemp

      Project https://github.com/KasukuSakura/silk-codec Bug report https://github.com/KasukuSakura/silk-codec/issues/new/choose Download binary https://github.com/KasukuSakura/silk-codec/releases/latest Platform supported Windows x64 Windows x86 Linux x64 Linux arm64 Android x86 Android x86_64 Android arm64 Mac OS Usage CLI ffmpeg -y -i $INPUT -acodec pcm_s16le -f s16le -ac 1 tmp.pcm pcm_to_silk tmp.pcm $HZ out.silk ffmpeg version git-2020-08-16-5df9724 Copyright (c) 2000-2020 the FFmpeg developers Input #0, mp3, from 'Conqueror.mp3': Stream mapping: Stream #0:0 -> #0:0 (mp3 (mp3float) -> pcm_s16le (native)) Press [q] to stop, [?] for help Output #0, s16le, to 'pipe:': Metadata: Stream #0:0: Audio: pcm_s16le, 44100 Hz, mono, s16, 705 kb/s ^~~~~ It is $HZ Java

      Jar was published as io.github.kasukusakura:silk-codec

      public class A { public static void normal() throws Throwable { // System.load(); // load native if necessary var simpleRate = 44100; var pcm = "src.pcm"; try (var som = new BufferedOutputStream(new FileOutputStream( "out.silk" ))) { SilkCoder.encode( new BufferedInputStream(new FileInputStream(pcm)), som, simpleRate ); } } public static void any() throws Throwable { // System.load(); // load native if necessary var threadPool = Executors.newCachedThreadPool(); var stream = new AudioToSilkCoder(threadPool); try (var fso = new BufferedOutputStream(new FileOutputStream("out.silk"))) { stream.connect("ffmpeg", "src.mp3", fso); } System.out.println("DONE"); threadPool.shutdown(); } }
    • Karlatemp

      常用资源整合
      官方公告 • • Karlatemp

      1
      2
      赞同
      1
      帖子
      26093
      浏览

      Karlatemp

      分区 title 链接 - 常见问题 QA https://mirai.mamoe.net/topic/71/ DEV 忽略某个用户的全部消息 https://mirai.mamoe.net/topic/327/ DEV 在 bot 发言前进行检查 https://mirai.mamoe.net/topic/599/ DEV 在 console 命令系统以外的地方使用权限系统 https://mirai.mamoe.net/topic/535/ DEV 发送网络图片 https://mirai.mamoe.net/topic/337/ DEV 在 MemberJoinEvent 发出的 @ 无法识别 https://github.com/mamoe/mirai/issues/1559 DEV 群名片修改事件没有触发 https://github.com/mamoe/mirai/issues/1570 DEV 自定义 mirai-console 日志系统 https://github.com/mamoe/mirai-console/issues/412 USE Mirai Console Loader https://mirai.mamoe.net/topic/177/ USE chat-command https://github.com/project-mirai/chat-command USE LuckPerms Mirai - 高级权限服务插件 https://mirai.mamoe.net/topic/68 USE 命令无法执行 https://mirai.mamoe.net/topic/184/ USE Mirai api http https://github.com/project-mirai/mirai-api-http DOC Mirai UserManual https://github.com/mamoe/mirai/blob/dev/docs/UserManual.md DOC SDK List https://github.com/mamoe/mirai/tree/dev/docs#社区-sdk

      Notes:

      此处列出的插件为最核心最常用的插件, 需要更多插件请查看 https://mirai.mamoe.net/category/6/ 如果有较为常见的问题此处没有列出的可以在本贴内回复
      zhoudu created this issue in mamoe/mirai closed 群内@机器人,mirai没有识别出该消息是At类型,识别成PlainText类型 #1559 Moyulingjiu created this issue in mamoe/mirai closed 群名片修改事件无法触发 #1570 LovesAsuna created this issue in mamoe/mirai-console closed 第三方日志系统接管 #412
    • Karlatemp

      关于 Bot is closed manually
      官方公告 • • Karlatemp

      6
      0
      赞同
      6
      帖子
      1781
      浏览

      Karlatemp

      About

      我们留意到部分用户在长时间运行 mirai 后会触发 Bot is closed manually 的错误

      为了修复此错误, 我们需要收集一些信息, 你可以选择直接在此贴回复 / 在 GitHub 创建新 issue

      开启 Debug 模式以便于我们修复 BUG

      添加以下 jvm 参数

      -Dmirai.network.handle.selector.logging=true -Dmirai.network.state.observer.logging=full -Dmirai.network.packet.logger=true Mirai Console

      使用专业文本编辑器 (如 vim, vscode, sublime, etc.) 编辑 config/Console/Logger.yml

      修改为以下内容

      # 日志输出等级 可选值: ALL, VERBOSE, DEBUG, INFO, WARNING, ERROR, NONE defaultPriority: ALL # 特定日志记录器输出等级 loggers: example.logger: NONE console.debug: NONE Bot: ALL MCL Windows

      Windows系统的 mcl 启动脚本名为 mcl.cmd, 使用任何文本编译器打开该文件, 并将 jvm参数 加到 -jar 前

      修改示例

      @echo off set JAVA_BINARY=java15 %JAVA_BINARY% ^ -Dmirai.network.handle.selector.logging=true ^ -Dmirai.network.state.observer.logging=full ^ -Dmirai.network.packet.logger=true ^ -jar mcl.jar %* Linux / MacOS

      Linux/MacOS 系列的 mcl 启动脚本名字直接为 mcl, 使用任何文本编辑器打开该文件, 并将 jvm参数 加到 -jar 前

      修改示例

      #!/usr/bin/env sh export JAVA_BINARY=java $JAVA_BINARY \ -Dmirai.network.handle.selector.logging=true \ -Dmirai.network.state.observer.logging=full \ -Dmirai.network.packet.logger=true \ -jar mcl.jar $* MiraiAndroid

      请直接在设置内打开debug日志即可

    • Karlatemp

      隐藏文字测试
      摸鱼区 • • Karlatemp

      9
      0
      赞同
      9
      帖子
      523
      浏览

      Karlatemp

      Hello Hidden text

      要使用隐藏文字,请使用以下代码

      +=[要隐藏的文字]=+
    • Karlatemp

      mirai-console-system-provider -- 常用类库前置
      其他项目发布 • • Karlatemp

      1
      0
      赞同
      1
      帖子
      267
      浏览

      Karlatemp

      很水的一个东西,整合了常用的各种前置,以允许 dev 不携带相关库

      Repo: https://github.com/KasukuSakura/mirai-console-system-provider

      Download: https://github.com/KasukuSakura/mirai-console-system-provider/releases

      Group Name Version com.google.code.gson gson 2.8.7 com.google.guava guava 30.1.1-jre com.zaxxer HikariCP 5.0.0 org.mongodb mongo-java-driver 3.12.9 org.yaml snakeyaml 1.28 org.postgresql postgresql 42.2.19 mysql mysql-connector-java 8.0.26 com.h2database h2 1.4.200 org.xerial sqlite-jdbc 3.36.0.1 redis.clients jedis 3.6.3 com.rabbitmq amqp-client 5.13.0 org.apache.commons commons-pool2 2.10.0 org.apache.commons commons-text 1.9 org.apache.commons commons-lang3 3.12.0 org.apache.commons commons-collections4 4.4 org.ktorm ktorm-core 3.4.1 org.hibernate hibernate-core 5.5.4.Final org.antlr antlr4-runtime 4.9.2 org.jetbrains.kotlin kotlin-reflect 1.4.32 org.jetbrains.kotlin kotlin-stdlib 1.5.10 com.google.guava failureaccess 1.0.1 com.google.guava listenablefuture 9999.0-empty-to-avoid-conflict-with-guava com.google.code.findbugs jsr305 3.0.2 org.checkerframework checker-qual 3.8.0 com.google.errorprone error_prone_annotations 2.5.1 com.google.j2objc j2objc-annotations 1.3 org.slf4j slf4j-api 1.7.31 com.google.protobuf protobuf-java 3.11.4 org.hibernate.common hibernate-commons-annotations 5.1.2.Final org.jboss.logging jboss-logging 3.4.2.Final javax.persistence javax.persistence-api 2.2 org.javassist javassist 3.27.0-GA net.bytebuddy byte-buddy 1.11.8 antlr antlr 2.7.7 org.jboss.spec.javax.transaction jboss-transaction-api_1.2_spec 1.1.1.Final org.jboss jandex 2.2.3.Final com.fasterxml classmate 1.5.1 org.glassfish.jaxb jaxb-runtime 2.3.1 javax.xml.bind jaxb-api 2.3.1 javax.activation javax.activation-api 1.2.0 org.jetbrains annotations 13.0 org.jetbrains.kotlin kotlin-stdlib-common 1.5.10 org.glassfish.jaxb txw2 2.3.1 com.sun.istack istack-commons-runtime 3.0.7 org.jvnet.staxex stax-ex 1.8 com.sun.xml.fastinfoset FastInfoset 1.2.15
    • Karlatemp

      [JVM][LowLevel][JDK 9+] JVM 权限逃逸技术
      技术交流板块 • jvm • • Karlatemp

      1
      3
      赞同
      1
      帖子
      616
      浏览

      Karlatemp

      前言: 仅研究 JDK 9+, JDK 8- 无研究意义

      从 Java 9 开始, Java 引入了一个新的概念, 模块(Module). 模块的存在, 限制了反射技术, 在 JDK 16 中, 直接反射越权修改 java.base 甚至会得到错误 java.lang.reflect.InaccessibleObjectException, 对于某些需要的 devops 而言意味着无法完成预期操作

      在阅读 java.lang.reflect.AccessibleObject 源码后, 有如下代码片段

      /** * If the given AccessibleObject is a {@code Constructor}, {@code Method} * or {@code Field} then checks that its declaring class is in a package * that can be accessed by the given caller of setAccessible. */ void checkCanSetAccessible(Class<?> caller) { // do nothing, needs to be overridden by Constructor, Method, Field } final void checkCanSetAccessible(Class<?> caller, Class<?> declaringClass) { checkCanSetAccessible(caller, declaringClass, true); } private boolean checkCanSetAccessible(Class<?> caller, Class<?> declaringClass, boolean throwExceptionIfDenied) { if (caller == MethodHandle.class) { throw new IllegalCallerException(); // should not happen } Module callerModule = caller.getModule(); Module declaringModule = declaringClass.getModule(); if (callerModule == declaringModule) return true; if (callerModule == Object.class.getModule()) return true; if (!declaringModule.isNamed()) return true; String pn = declaringClass.getPackageName(); int modifiers; if (this instanceof Executable) { modifiers = ((Executable) this).getModifiers(); } else { modifiers = ((Field) this).getModifiers(); } // class is public and package is exported to caller boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers()); if (isClassPublic && declaringModule.isExported(pn, callerModule)) { // member is public if (Modifier.isPublic(modifiers)) { logIfExportedForIllegalAccess(caller, declaringClass); return true; } // member is protected-static if (Modifier.isProtected(modifiers) && Modifier.isStatic(modifiers) && isSubclassOf(caller, declaringClass)) { logIfExportedForIllegalAccess(caller, declaringClass); return true; } } // package is open to caller if (declaringModule.isOpen(pn, callerModule)) { logIfOpenedForIllegalAccess(caller, declaringClass); return true; } if (throwExceptionIfDenied) { // not accessible String msg = "Unable to make "; if (this instanceof Field) msg += "field "; msg += this + " accessible: " + declaringModule + " does not \""; if (isClassPublic && Modifier.isPublic(modifiers)) msg += "exports"; else msg += "opens"; msg += " " + pn + "\" to " + callerModule; InaccessibleObjectException e = new InaccessibleObjectException(msg); if (printStackTraceWhenAccessFails()) { e.printStackTrace(System.err); } throw e; } return false; }

      有两个关键判断逻辑: declaringModule.isExported(pn, callerModule), declaringModule.isOpen(pn, callerModule)

      阅读 Module.java 后发现有 implAddExports 方法, 通过 IDEA 查找调用引用发现了 java.lang.System 有访问此方法的 JDK Internal API

      private static void setJavaLangAccess() { // Allow privileged classes outside of java.lang SharedSecrets.setJavaLangAccess(new JavaLangAccess() { public Module defineModule(ClassLoader loader, ModuleDescriptor descriptor, URI uri) { return new Module(null, loader, descriptor, uri); } public Module defineUnnamedModule(ClassLoader loader) { return new Module(loader); } public void addReads(Module m1, Module m2) { m1.implAddReads(m2); } public void addReadsAllUnnamed(Module m) { m.implAddReadsAllUnnamed(); } public void addExports(Module m, String pn, Module other) { m.implAddExports(pn, other); } public void addExportsToAllUnnamed(Module m, String pn) { m.implAddExportsToAllUnnamed(pn); } public void addOpens(Module m, String pn, Module other) { m.implAddOpens(pn, other); } public void addOpensToAllUnnamed(Module m, String pn) { m.implAddOpensToAllUnnamed(pn); } public void addOpensToAllUnnamed(Module m, Set<String> concealedPackages, Set<String> exportedPackages) { m.implAddOpensToAllUnnamed(concealedPackages, exportedPackages); } public void addUses(Module m, Class<?> service) { m.implAddUses(service); } }); }

      找到了 JDK 提供的后门之后, 我们只需要调用 SharedSecrets.getJavaLangAccess().addExports 就能开后门了....
      不对,目前还无法调用 SharedSecrets, 还需要一些手段....

      在 java.lang.reflect 中翻到了一个特别的东西, java.lang.reflect.Proxy, 她是破局的关键中心

      抱着好奇的心里, 我尝试了使用 Proxy 实现 jdk.internal.access 中的一个接口玩玩

      public static void main(String[] args) throws Exception { var obj = Proxy.newProxyInstance( Usffsa.class.getClassLoader(), new Class[]{Class.forName("jdk.internal.access.JavaLangAccess")}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } } ); System.out.println(obj); }

      没想到, 运行成功了(eg: 没有对应权限(Exported)是不能实现对应接口的), 迎接着激动的心情, 输出了更多的详细信息

      System.out.println(obj); System.out.println(obj.getClass()); System.out.println(obj.getClass().getModule()); System.out.println(Object.class.getModule().isExported("jdk.internal.access", obj.getClass().getModule())); null class com.sun.proxy.jdk.proxy1.$Proxy0 module jdk.proxy1 true

      破局点找到了, java.lang.reflect.Proxy 拥有打开模块访问的权利, 然后尝试对该模块进行注入

      public static void main(String[] args) throws Exception { var ccl = new ClassLoader(Usffsa.class.getClassLoader()) { Class<?> defineClass(byte[] code) { return defineClass(null, code, 0, code.length); } }; var obj = Proxy.newProxyInstance( ccl, new Class[]{Class.forName("jdk.internal.access.JavaLangAccess")}, (proxy, method, args1) -> null ); var writer = new ClassWriter(0); // org.objectweb.asm.ClassWriter writer.visit(Opcodes.V1_8, 0, obj.getClass().getPackageName().replace('.', '/') + "/Test0", null, "java/lang/Object", null ); var injectedClass = ccl.defineClass(writer.toByteArray()); System.out.println("Proxy Module : " + obj.getClass().getModule()); System.out.println("Injected Module : " + injectedClass.getModule()); System.out.println("Is Same Module : " + (injectedClass.getModule() == obj.getClass().getModule())); } Proxy Module : module jdk.proxy1 Injected Module : module jdk.proxy1 Is Same Module : true

      至此已经破开了 JVM 的模块限制的死局, 实际应用可参考 [Karlatemp/UnsafeAccessor]

    • Karlatemp

      mirai-api-http 文档更新
      HTTP API和第三方SDK • • Karlatemp

      3
      0
      赞同
      3
      帖子
      1032
      浏览

      Karlatemp

      据不可靠消息称, mirai-api-http 已经部署了更友好的文档

      文档戳我

    • Karlatemp

      常见问题 Q & A
      官方公告 • • Karlatemp

      65
      0
      赞同
      65
      帖子
      33181
      浏览

      Karlatemp

      不定期更新

      mirai-core BotFactory.INSTANCE.newBot出错 ClassNotFoundException: net.mamoe.mirai.internal.MiraiImpl

      运行时缺少 net.mamoe:mirai-core, 如为 Gradle, 请添加 testRuntimeOnly("net.mamoe:mirai-core:$VERSION")

      如为 Maven, 请添加 net.mamoe:mirai-core-jvm:$VERSION 依赖

      ExternalResource.create(InputStream)会生成大量临时文件

      https://github.com/mamoe/mirai/issues/1045

      MiraiCode 发送不完整

      https://github.com/mamoe/mirai/issues/1056

      java.security.NoSuchProviderException: JCE cannot authenticate the provider Cannot find error message, unknown login result type: 180

      如果正在使用 mirai-console-loader, 请更新至最新版本即可解决

      此原因为 mirai 使用 shadowJar 打包后, 没有签名导致, 解决方法为在运行时路径添加 org.bouncycastle:bcprov-jdk15on, 并确保该库第一个加载 (即保证该库比 mirai-core-all 先加载)

      https://search.maven.org/search?q=g:org.bouncycastle AND a:bcprov-jdk15on

      撤回消息报错 Failed(result=1001, errorMessage=No message meets the requirements)

      bot 没有管理员权限 / bot 正在尝试撤回群主的消息

      无法监听戳一戳 (NugedEvent)

      切换登录协议为 ANDROID_PHONE

      Error(title=禁止登录, message=当前上网环境异常,请更换网络环境或在常用设备上登录或稍后再试。, errorInfo=)

      刷新设备信息 (删除 device.json, 对于 mirai-console 位于 bots/**/ 内)

      @see also https://mirai.mamoe.net/topic/223/

      发送消息后无报错且看不到消息体

      服务器风控导致,通常情况下挂一个星期即可解决

      BotFactory.newBot 提示 Integer number too large

      使用搜索引擎搜索 Integer number too large

      mirai-console 执行命令时没有任何回应

      请确认:

      该命令以注册 (在 /help 中能找到该命令) 已经安装了 chat-command 拥有执行命令的权限 (在控制台执行 /permission 查看详情) 论坛相关 无法加载右上角的通知页面

      请关闭广告拦截插件并刷新网页

      待更新

      RrrrLin created this issue in mamoe/mirai closed 2.4.0 java长时间运行通过ExternalResource.create(InputStream)上传图片会生成大量临时文件 #1045 Nambers created this issue in mamoe/mirai closed 关于发送miraicode发不全 #1056
    • Karlatemp

      LuckPerms - Mirai - 高级权限服务插件
      插件发布 • jvm plugin kotlin permission • • Karlatemp

      70
      1
      赞同
      70
      帖子
      22141
      浏览

      Karlatemp

      LuckPerms - Mirai Repo: Karlatemp/LuckPerms-Mirai Original Repo: lucko/LuckPerms Issue report: new issue Platform request >= mirai-core 2.0-RC >= mirai-console 2.0-RC Download

      一款高级易使用的 mirai-console 权限服务插件

      Snapshot

      3.png
      0.png
      2.png
      1.png

      Install

      Way 1. By MCL: mcl --update-package io.github.karlatemp:luckperms --channel nightly --type plugin

      Way 2. Download release from Releases. Then put it into plugins

      Usages

      LuckPerms-Mirai 基于 LuckPerms 开发, 详细用法请百度/谷歌/阅读 LuckPerms wiki

      LuckPerms wiki

      LuckPerms-Mirai 的身份上下文使用 context 实现, 可以在聊天中使用
      /lp user <****> info 查看上下文

      下面是一些示例命令

      // 授予群聊管理员(包含群主)一项权限 /lp group default permission set AdminPermission admin=true // 授予群主一条权限 /lp group default permission set OwnerPermission level=owner // 授予管理员(不含群主)一条权限 /lp group default permission set OwnerPermission level=admin // 授予在某个群的所有人一条权限 /lp group default permission set PermissionInGroup group=1234567890 // 授予某个群的群聊管理员一条权限 /lp group default permission set PermissionInGroup group=1234567890 admin=true // 创建系统管理组 /lp creategroup root /lp group root permission set * /lp user 1234567890 parent set root // 开启权限调试模式 (debug(verbose) mode) // 查看具体权限名 // WARNING: Dont run this command in chatting /lp verbose on // 开启权限调试模式 (debug(verbose) mode), 并在 Web 查看 /lp verbose record //WAIT..... /lp verbose upload
    • 1 / 1