流量分析之题型解析 | 风尘孤狼
0%

流量分析之题型解析

练一下文件分析的一些题型,掌握一下Wireshark工具的使用方法

报错版流量包

先做一下第一届 “百度杯” 信息安全攻防总决赛里面的find the flag的这个题,文件地址放这了。

https://static2.ichunqiu.com/icq/resources/fileupload/CTF/BSRC/2017/BSRC3-1/findtheflag.cap

用Wireshark直接打开报错了image-20220311195627114

可以使用http://f00l.de/hacking/pcapfix.php修复流量包image-20220311195822356

再次打开,在流量包中有提示image-20220311200444184

image-20220311200649590

按照同样的方式连接后面相连数据包的id字段,找到最终的flag!

盲注流量-回显全200解法(二分法)

流量分析SQL注入流量

重点去看响应包,也就是HTTP/1.1 200 OK (text/html)里面的内容,如下

Frame 3568: 726 bytes on wire (5808 bits), 726 bytes captured (5808 bits) on interface \Device\NPF_{E6CE0565-F179-4A52-B211-621FF8EEBA4F}, id 0
    Section number: 1
    Interface id: 0 (\Device\NPF_{E6CE0565-F179-4A52-B211-621FF8EEBA4F})
    Encapsulation type: Ethernet (1)
    Arrival Time: Feb 14, 2024 20:06:04.593375000 中国标准时间
    UTC Arrival Time: Feb 14, 2024 12:06:04.593375000 UTC
    Epoch Arrival Time: 1707912364.593375000
    [Time shift for this packet: 0.000000000 seconds]
    [Time delta from previous captured frame: 0.006990000 seconds]
    [Time delta from previous displayed frame: 0.036535000 seconds]
    [Time since reference or first frame: 96.515960000 seconds]
    Frame Number: 3568
    Frame Length: 726 bytes (5808 bits)
    Capture Length: 726 bytes (5808 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp:http:data-text-lines]
    [Coloring Rule Name: HTTP]
    [Coloring Rule String: http || tcp.port == 80 || http2]
Ethernet II, Src: de:75:30:ac:fb:5d (de:75:30:ac:fb:5d), Dst: Intel_b0:5a:45 (38:fc:98:b0:5a:45)
    Destination: Intel_b0:5a:45 (38:fc:98:b0:5a:45)
    Source: de:75:30:ac:fb:5d (de:75:30:ac:fb:5d)
    Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: 117.21.200.176, Dst: 172.16.14.21
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
    Total Length: 712
    Identification: 0x3f82 (16258)
    010. .... = Flags: 0x2, Don't fragment
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 49
    Protocol: TCP (6)
    Header Checksum: 0x0fc3 [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 117.21.200.176
    Destination Address: 172.16.14.21
Transmission Control Protocol, Src Port: 81, Dst Port: 50868, Seq: 1, Ack: 282, Len: 672
    Source Port: 81
    Destination Port: 50868
    [Stream index: 356]
    [Conversation completeness: Complete, WITH_DATA (31)]
    [TCP Segment Len: 672]
    Sequence Number: 1    (relative sequence number)
    Sequence Number (raw): 574345654
    [Next Sequence Number: 673    (relative sequence number)]
    Acknowledgment Number: 282    (relative ack number)
    Acknowledgment number (raw): 3857710515
    0101 .... = Header Length: 20 bytes (5)
    Flags: 0x018 (PSH, ACK)
    Window: 501
    [Calculated window size: 64128]
    [Window size scaling factor: 128]
    Checksum: 0xdd9b [unverified]
    [Checksum Status: Unverified]
    Urgent Pointer: 0
    [Timestamps]
    [SEQ/ACK analysis]
    TCP payload (672 bytes)
Hypertext Transfer Protocol, has 2 chunks (including last chunk)
    HTTP/1.1 200 OK\r\n
        [Expert Info (Chat/Sequence): HTTP/1.1 200 OK\r\n]
            [HTTP/1.1 200 OK\r\n]
            [Severity level: Chat]
            [Group: Sequence]
        Response Version: HTTP/1.1
        Status Code: 200
        [Status Code Description: OK]
        Response Phrase: OK
    Server: openresty\r\n
    Date: Wed, 14 Feb 2024 12:06:04 GMT\r\n
    Content-Type: text/html; charset=UTF-8\r\n
    Transfer-Encoding: chunked\r\n
    Connection: keep-alive\r\n
    Vary: Accept-Encoding\r\n
    X-Powered-By: PHP/7.3.11\r\n
    Cache-Control: no-cache\r\n
    Content-Encoding: gzip\r\n
    \r\n
    [HTTP response 1/1]
    [Time since request: 0.036535000 seconds]
    [Request in frame: 3566]
    [Request URI: http://3c97f319-92cf-4ba5-a3f2-6bd644abe921.node5.buuoj.cn:81/search.php?id=1-(ascii(substr((Select(reverse(group_concat(password)))From(F1naI1y)),6,1))%3E31)]
    HTTP chunked response
    Content-encoded entity body (gzip): 395 bytes -> 708 bytes
    File Data: 708 bytes
Line-based text data: text/html (19 lines)
    <!DOCTYPE html>\r\n
    <html>\r\n
    <head>\r\n
            <meta charset="UTF-8">\r\n
            <title>FLAG</title>\r\n
    </head>\r\n
    <body background="./image/background.jpg" style="background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;" >\r\n
    <div style="position: absolute;bottom: 0;width: 99%;"><p align="center" style="font:italic 15px Georgia,serif;color:white;"> Syclover @ cl4y</p></div>\r\n
    \r\n
    \r\n
    \t\t\t<body background='./image/background.jpg' style='background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;'>\r\n
    \t\t\t\t<br><br><br>\r\n
    \t\t\t\t<h1 style='font-family:verdana;color:red;text-align:center;font-size:40px;'>ERROR!!!</h1>\r\n
    \t\t\t\t</br>\r\n
    \t\t\t</body>\t\t\t\r\n
    \t\t\t\t\r\n
    \r\n
    </body>\r\n
    </html>

重点是里面的Request URI,因为含有注入的url【id=1-(ascii(substr((Select(reverse(group_concat(password)))From(F1naI1y)),6,1))%3E31)】,其次就是回显内容,看Line-based text data,在这里显示的差别就是ERROR!!!

利用下面这个来筛选指定length的流量

frame.len == 978
43eab3193826b3f686e2690674dab990

用tshark导出指定内容

┌──(kali㉿kali)-[~/桌面]
└─$ tshark -r blindsql.pcapng -Y "http.request" -T fields -e http.request.full_uri > data.txt

然后整理一下只保留有关flag的url

image-20240215103634340

脚本提取

错误率有点高,要不然还是一点一点自己判断吧

import urllib.parse
import requests,re
 
f = open('1.txt','r',encoding='gb18030',errors='ignore')
lines = f.readlines()


flag_ascii = {}
for line in lines:
    if len(line) > 2:
        
        request = urllib.parse.unquote(urllib.parse.unquote(line))
        matchObj = re.search(r'''(\d{0,2}),1\)\)\>(\d+)''', request)
        # print(matchObj)


        #倒数第一的value
        # if matchObj:
        #     key = int(matchObj.group(1))  # key保存字符的位置
        #     value = int(matchObj.group(2))  # value保存字符的ascii编码
        #     flag_ascii[key] = value

        #倒数第二的value
        if matchObj:
            key = int(matchObj.group(1))  # key保存字符的位置
            value = int(matchObj.group(2))  # value保存字符的ascii编码
            # 检查是否已经有一个 value 存在
            if key in flag_ascii:
                # 如果已经存在,则更新为倒数第二个
                flag_ascii[key] = [flag_ascii[key][-1], value]
            else:
                # 如果不存在,则创建一个列表,并将当前值添加到列表中
                flag_ascii[key] = [value]


# # 只保留每个 key 的最后一次出现的 value
# for key, value in flag_ascii.items():
#     flag_ascii[key] = value

# print(flag_ascii)


# 获取每个 key 对应的倒数第二个 value
for key, values in flag_ascii.items():
    if len(values) > 1:
        print(f"{values[-2]}",end=' ')
        ascii_value = values[-2]
        flag = chr(ascii_value)
        # print(str(flag),end='')

盲注流量-回显200/404解法(二分法)

当状态码是200的时候,表示正确,报错为404,判断原理为大于num错,小于num+1错,即为num,所以盲注出来的字符串应该是状态码等于200时的字符或等于404时的ascii码减去1

将流量包指定数据筛选后导出

import urllib.parse
import requests,re
 
f = open('日志里的秘密.log','r',encoding='gb18030',errors='ignore')
lines = f.readlines()
flag_ascii = {}
for line in lines:
    if len(line) > 2:
        request = urllib.parse.unquote(urllib.parse.unquote(line))
        matchObj = re.search(r'''flag_is_here ORDER BY flag LIMIT 0,1\),(.*?),1\)\)>(.*?) AND 'RCKM'='RCKM&Submit=Submit HTTP/1.1" (.*?) ''',request)
        #flag_is_here ORDER BY flag LIMIT 0,1),22,1))>96 AND 'RCKM'='RCKM&Submit=Submit HTTP/1.1
        if matchObj:
            key = int(matchObj.group(1))  # key保存字符的位置
            value = int(matchObj.group(2))  # value保存字符的ascii编码
            status= int(matchObj.group(3))
            print(matchObj.group(3),':',matchObj.group(2))
            if status==200:
                flag_ascii[key] = value+1    # 用字典保存flag
            if status==404:
                flag_ascii[key] = value     # 用字典保存flag
flag = ''
for value in flag_ascii.values():
    flag += chr(value)
print (flag)

盲注流量-布尔盲注

import re

#Request URI: http://192.168.246.1/ctf/Less-5/?id=1'%20and%20ascii(substr((select%20flag%20#from%20t),1,1))=102--+
nums = []
obj1 = re.compile(r"1\)\)=(?P<num1>.*)\b",re.S)#开启贪婪模式匹配这里一定要使用.*贪婪模式 如果用.*?可能匹配失败 \b代表结尾
def getAscii():
    with open("re.txt", "r", encoding="utf-8") as f:
        for line in f.readlines():
            line = line.strip()
            result = obj1.finditer(line)
            for it in result:
                num = it.group("num1")
                nums.append(num)


def getflag():
    flag = ""
    for i in nums:
        i = chr(int(i))
        flag = flag + i
        print(flag)

if __name__ == '__main__':
    getAscii()
    getflag()

盲注流量-时间盲注

import re


#username[1]" = "in ('-1' ))) or if(ascii(substring((select 
#flag from flag limit 0,1),1,1))=30,sleep(5),1)
asciis = []
asciis1 = []
obj = re.compile(r"limit 0,1\),(?P<num>.*),1\)\)=(?
P<asciinum>.*)\b,sleep",re.S)
#匹配正则表达式  第一个匹配lit 但是我们需要的只有ascii值  这里用.*贪婪模式  否则匹配失败


def getASCII():
    with open("time.txt","r",encoding="utf-8") as f:
        for line in f.readlines():  #readlines()读取出来为列表所以我们直接迭代 用strip()去除空格
            line = line.strip()
            result = obj.finditer(line) #正则匹配
            for it in result:
                num = it.group("num")  #lit值
                asciinum = it.group("asciinum") #ASCIi值 注意这里提取的都为str类型  所以以下都要做int强转
                asciis.append(asciinum) #将payload的全部ascii值(包括失败的)写入列表

#使用一个循环 时间盲注可知ascii正确后才会进行下一次匹配  所以我们这里直接一个一个循环
# 然后当正确的如102时  下一个又从30开始  所以会比前面小  利用这个特点筛选将正确的ASCIi写入新的列表
def getASCII2():
    a = 1
    while a < len(asciis):
        if int(asciis[a]) < int(asciis[a-1]):
            asciis1.append(int(asciis[a-1]))
        a += 1


def getFLag():  #转换ASCIi
    flag = ""
    for i in asciis1:
        i = chr(i)
        flag = flag + i
        print(flag)


if __name__ == '__main__':
    getASCII()
    getASCII2()
    getFLag()

语句为=,而非><

import re

number = []
with open("aa.txt","r",encoding="utf-8") as f:
    for i in f.readlines():
        flag_number = re.findall(r"\[Request URI: .*?=(\d+)%23\]",i,re.S)
        url_list = re.findall(r"\[Request URI: (.*?)\]",i,re.S)
        if flag_number:
            print(url_list)
            number.append(flag_number[0])

print(number)
flag = ''
for i in number:
    flag +=chr(int(i))
print(flag)

USB键盘/鼠标流量包

在kali,windows不建议,麻烦

python -m pip install poetry
poetry install
python usb-mouse-pcap-visualizer.py -i example/example.pcap

参考

【CTF_流量日志分析】二分法盲注分析_ctf 盲注log-CSDN博客

MISC杂项时间盲注及布尔盲注脚本 鹤城杯_xiaoqiuxx blog-CSDN博客

制作不易,如若感觉写的不错,欢迎打赏