首页
社区
课程
招聘
[原创]数据包伪造替换、会话劫持、https劫持之探索和测试
发表于: 2023-5-27 16:57 19925

[原创]数据包伪造替换、会话劫持、https劫持之探索和测试

2023-5-27 16:57
19925

该攻击过程如下:伪造服务器响应客户端的数据包。监听客户端的数据包,用预先伪造的数据包,伪装成服务器返回的数据发送给客户端。

因为攻击者跟目标在同一个局域网,所以攻击者发送的数据包肯定比服务器的响应数据要快很多,只要数据包构造正确,就一定可以被客户端按正常的数据处理。

这部分的重点和难点在于,要构造正确的数据包,需要根据攻击者的目的,修改数据包中的数据、MAC、IP、TCP(UDP)层的长度、校验值等多个字段的值,还要兼容多种网络协议,另外还需要高效的处理数据包。

这部分内容对于熟悉tcp/ip协议栈的程序员来讲非常容易,唯一需要注意的坑就是,udp和tcp封包中的checksum字段的计算,其格式不是简单的tcp和udp包头字节的crc校验,而是:

计算tcp和udp中校验和的代码大体如下所示:

该模块基于winpcap开发。

各层封包的包头处理有很多细节需要注意。在实际场景中,抓到的数据包并不是mac层,而是大多是pppoe或者wlan格式,其包头格式如下:

具体处理流程更多是包头协议格式的解析,在此按下不表。

本程序支持tcp和udp数据包的伪造、欺骗攻击,其代码主要位于ReplacePacket.cpp中。其中,dns劫持就是一种较为简单的数据包替换攻击,其代码位于 PacketProc.cpp中,要实现攻击需要了解dns数据包的格式,读者请自行百度。其主要数据结构如下:

如下以下视频中,当dns欺骗未开启时,在nslookup中查询到的www.baidu.com的IP地址是182.61.200.7,而当dns攻击开启时,www.baiducom的ip地址被替换为192.168.101.122,这个地址正好是本机的ip地址,本机上有一个服务器程序,监听443或者80端口的数据,这样就可以当作下一步https攻击的服务器。

从wireshark可以清晰看到网卡发出的dns伪造数据包。

图片描述

图片描述

https劫持有多种方式可以实现,比如dns劫持方式和数据包转发。

数据包转发方式较为复杂,各有各的实现方法。一般原理是:

另一种方式较为简单,其过程如下:

本程序采用第二种方法,主要的https中间人代码在sslEntry.cpp,sslProxyListener.cpp,sslProxy.cpp,makeCert.cpp,sslPublic.cpp等几个文件中,搬砖的工作暂且不表:)。

在https劫持中一个重要问题就是证书问题。这里采取的方式是,将生成次级证书的根证书导入到本机的根证书授信中心,接下来利用此证书签名的二级证书和三级证书在chrome和edge中的访问都是没问题的,但是firefox有单独的证书认证体系,windows等操作系统认可的证书、包括我们我们导入的证书不在其认可范围之内。

程序中实现了域名证书证书自动生成功能,可以根据客户端的clienthello数据包中的域名,动态生成域名证书。另外还支持自动检测和生成、导入根证书。

程序运行需要预先安装openssl。

在实际测试中,国内大厂包括阿里系,腾讯系的软件大都采用了https传输方式,但是也有极个别软件的服务器域名的ssl流量可以劫持成功,特别是某些Android移动端软件,ios端也发现过此种情况。当然,现在的趋势是验证机制越来越严格,难度越来越大。

本实例程序运行时,会将ssl数据存放在output目录下的ssl.dat文件中,如下截图所示,当未开启ssl攻击时,浏览器访问正常;当开启ssl劫持后,浏览器依然正常,此时ouput目录下的ssl.dat中存放着https中的明文数据。从host或者域名可以验证我们刚才点击访问的网址,证明ssl劫持成功。

图片描述

本次测试的具体代码下载地址:点击此处下载

该项目具有tcp和udp数据包伪造替换、dns欺骗劫持、https中间人(mid in man)劫持攻击等多种功能。

 
 
 
typedef struct
{
    unsigned char SrcIP[IPV6_IP_SIZE];
    unsigned char DstIP[IPV6_IP_SIZE];
    unsigned short Protocol;
    unsigned short PackLen;
}IPV6FAKEHEADER, *LPIPV6FAKEHEADER;
typedef struct
{
    unsigned char SrcIP[IPV6_IP_SIZE];
    unsigned char DstIP[IPV6_IP_SIZE];
    unsigned short Protocol;
    unsigned short PackLen;
}IPV6FAKEHEADER, *LPIPV6FAKEHEADER;
WORD Checksum::checksum(WORD *buffer,int size)
{
    unsigned long cksum = 0;
    while(1<size)
    {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }
    if(0<size)
        cksum += *(UCHAR*)buffer;
    cksum = (cksum>>16) + (cksum&0xffff);
    cksum += (cksum>>16);
    return(unsigned short)(~cksum);
}
 
 
USHORT Checksum::subPackChecksum(char * lpCheckSumData,WORD wCheckSumSize,DWORD dwSrcIP,DWORD dwDstIP,unsigned int wProtocol)
{
    char szCheckSumBuf[MAX_SINGLE_PACKET_SIZE];
    LPCHECKSUMFAKEHEADER lpFakeHdr = (LPCHECKSUMFAKEHEADER)szCheckSumBuf;
    lpFakeHdr->dwSrcIP = dwSrcIP;
    lpFakeHdr->dwDstIP = dwDstIP;
    lpFakeHdr->Protocol = ntohs(wProtocol);
    lpFakeHdr->usLen = ntohs(wCheckSumSize);
 
    memcpy(szCheckSumBuf + sizeof(CHECKSUMFAKEHEADER),(char*)lpCheckSumData,wCheckSumSize);
 
    *(DWORD*)(szCheckSumBuf + sizeof(CHECKSUMFAKEHEADER) + wCheckSumSize) = 0;
 
    unsigned short nCheckSum = checksum((WORD*)szCheckSumBuf,wCheckSumSize + sizeof(CHECKSUMFAKEHEADER));
    return nCheckSum;
}
WORD Checksum::checksum(WORD *buffer,int size)
{
    unsigned long cksum = 0;
    while(1<size)
    {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }
    if(0<size)
        cksum += *(UCHAR*)buffer;
    cksum = (cksum>>16) + (cksum&0xffff);
    cksum += (cksum>>16);
    return(unsigned short)(~cksum);
}
 
 
USHORT Checksum::subPackChecksum(char * lpCheckSumData,WORD wCheckSumSize,DWORD dwSrcIP,DWORD dwDstIP,unsigned int wProtocol)
{
    char szCheckSumBuf[MAX_SINGLE_PACKET_SIZE];
    LPCHECKSUMFAKEHEADER lpFakeHdr = (LPCHECKSUMFAKEHEADER)szCheckSumBuf;
    lpFakeHdr->dwSrcIP = dwSrcIP;
    lpFakeHdr->dwDstIP = dwDstIP;
    lpFakeHdr->Protocol = ntohs(wProtocol);
    lpFakeHdr->usLen = ntohs(wCheckSumSize);
 
    memcpy(szCheckSumBuf + sizeof(CHECKSUMFAKEHEADER),(char*)lpCheckSumData,wCheckSumSize);
 
    *(DWORD*)(szCheckSumBuf + sizeof(CHECKSUMFAKEHEADER) + wCheckSumSize) = 0;
 
    unsigned short nCheckSum = checksum((WORD*)szCheckSumBuf,wCheckSumSize + sizeof(CHECKSUMFAKEHEADER));
    return nCheckSum;
}
 
typedef struct {
    char version : 4;
    char type : 4;
    unsigned char code;
    unsigned short sessionid;
    unsigned short len;
    unsigned short protocol;
}PPPOEHEADER, *LPPPPOEHEADER;
 
 
typedef struct
{
 
    unsigned char idhigh : 4;
    unsigned char canonical : 1;
    unsigned char priority : 3;
    unsigned char id : 8;
 
    unsigned short type;
}HEADER8021Q, *LPHEADER8021Q;
typedef struct {
    char version : 4;
    char type : 4;
    unsigned char code;
    unsigned short sessionid;
    unsigned short len;
    unsigned short protocol;
}PPPOEHEADER, *LPPPPOEHEADER;
 
 
typedef struct
{
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-5-27 21:58 被satadrover编辑 ,原因:
收藏
免费 6
支持
分享
最新回复 (3)
雪    币: 3004
活跃值: (30861)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-5-27 19:02
1
雪    币: 1669
活跃值: (3202)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
秋狝 感谢分享
比较简单,主要是动手
2023-6-15 14:07
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2023-8-5 21:31
0
游客
登录 | 注册 方可回帖
返回
//