MiraiForum

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

    Karlatemp 发布的帖子

    • RE: 如何去除chat-command插件的"/"前缀?
      vim ./config/Console/Command.yml
      
      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: Java如何引入yml工具类实现对yml文件的读写?

      @stupidyang 你需要学习 gradle 如何管理依赖

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: Java如何引入yml工具类实现对yml文件的读写?

      导入包你没提供版本号,所以 reimport 项目失败

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: 问个很蠢的问题,到底怎么开发插件呢。。

      估计你还没有选择开发用的JDK, 或者正在 indexing JDK, 或者尝试 File -> Invalidate Cache (For IDEA)

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: 问个很蠢的问题,到底怎么开发插件呢。。

      https://docs.mirai.mamoe.net/console/ConfiguringProjects.html

      https://docs.mirai.mamoe.net/console/Plugins.html#jvm-平台插件接口-jvmplugin

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: 哭了,mirai官网竟然会算查重

      ?????

      发布在 摸鱼区
      Karlatemp
      Karlatemp
    • RE: 无法登录的临时处理方案

      @xbaimiao mirai-login-solver-selenium已经不能运行了

      发布在 官方公告
      Karlatemp
      Karlatemp
    • RE: 关于logger多余信息的过滤

      BotConfiguration 中设置 Net logger

      发布在 开发交流
      Karlatemp
      Karlatemp
    • [JVM][LowLevel][JDK 9+] JVM 权限逃逸技术

      前言: 仅研究 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
      Karlatemp
    • RE: 插件文档说明

      Command 语法 java 和 kotlin 差不多,只是继承的为 JSimpleCommand / JCompositeCommand / JRawCommand

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: Selenium不能在MiraiConsole启动?

      @cnawalol 在 Selenium不能在MiraiConsole启动? 中说:

      @karlatemp 在 Selenium不能在MiraiConsole启动? 中说:

      根据日志你应该是把selenium也一起打包了,你不应该一起打包,而是使用独立插件

      可以解释一下“独立插件”是什么意思吗?谢谢

      https://github.com/project-mirai/mirai-login-solver-selenium#在-miraiconsole-中使用

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: 大佬们,怎么在聊天里使用指令?

      https://mirai.mamoe.net/topic/71/常见问题-q-a

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: Selenium不能在MiraiConsole启动?

      根据日志你应该是把selenium也一起打包了,你不应该一起打包,而是使用独立插件

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: 在3K大群入设置了每分钟发言上限这个怎么判断呢

      如果超出限制发消息(sendMessage)时会得到一个error, try-catch 即可判断

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: 大佬们怎么上传群文件啊

      请认真阅读注释后再来提问

      发布在 开发交流
      Karlatemp
      Karlatemp
    • RE: windows server 2016安装失败

      Please report to https://github.com/iTXTech/mcl-installer/issues/new

      然后可以手动下载 JDK/JRE 和 mcl 完成环境配置

      发布在 BUG反馈
      Karlatemp
      Karlatemp
    • RE: 【闲聊】作为一个皇帝,怎样才能让名字比较响亮

      黄太君

      发布在 摸鱼区
      Karlatemp
      Karlatemp
    • 1
    • 2
    • 16
    • 17
    • 18
    • 19
    • 20
    • 18 / 20