Here is where I'm at thus far...
Code: Select all
#DIVERT_LAYER_NETWORK = 0
#DIVERT_PRIORITY_DEFAULT = 0
#DIVERT_FLAG_DEFAULT = 0
#DIVERT_DIRECTION_INBOUND = 1
#DIVERT_HELPER_NO_ICMP_CHECKSUM = 2
#DIVERT_HELPER_NO_ICMPV6_CHECKSUM = 4
#DIVERT_HELPER_NO_UDP_CHECKSUM = 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#MAXBUF = $FFFF
#MAXURL = 4096
Structure DIVERT_ADDRESS
IfIdx.l
SubIfIdx.l
Direction.a
EndStructure
Structure DIVERT_IPHDR
StructureUnion
HdrLength.a
Version.a
EndStructureUnion
TOS.a
Length.u
Id.u
FragOff0.u
TTL.a
Protocol.a
Checksum.u
SrcAddr.l
DstAddr.l
EndStructure
Structure DIVERT_TCPHDR
SrcPort.u
DstPort.u
SeqNum.l
AckNum.l
StructureUnion
Reserved1.a
HdrLength.a
EndStructureUnion
StructureUnion
Fin.a
Syn.a
Rst.a
Psh.a
Ack.a
Urg.a
Reserved2.a
EndStructureUnion
Window.u
Checksum.u
UrgPtr.u
EndStructure
Structure PACKET
ip.DIVERT_IPHDR
tcp.DIVERT_TCPHDR
EndStructure
Structure DATAPACKET
header.PACKET
Data.a
EndStructure
Prototype protoDivertOpen(filter.s, layer, priority.u, flags.q)
Global DivertOpen.protoDivertOpen
Prototype.b protoDivertRecv(handle, *pPacket, packetLen, pAddr, recvLen)
Global DivertRecv.protoDivertRecv
Prototype.b protoDivertSend(handle, *pPacket, packetLen, pAddr, sendLen)
Global DivertSend.protoDivertSend
Prototype.b protoDivertHelperParsePacket(*pPacket, packetLen, *ppIpHdr, *ppIpv6Hdr, *ppIcmpHdr, *ppIcmpv6Hdr, *ppTcpHdr, *ppUdpHdr, *ppData, pDataLen)
Global DivertHelperParsePacket.protoDivertHelperParsePacket
Prototype protoDivertHelperCalcChecksums(*pPacket, packetLen, flags.q)
Global DivertHelperCalcChecksums.protoDivertHelperCalcChecksums
Prototype.b protoDivertClose(handle)
Global DivertClose.protoDivertClose
Procedure.s TestForError()
Result.s = ""
dwMessageId = GetLastError_()
*lpBuffer = AllocateMemory(255)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, #Null, dwMessageId, #Null, *lpBuffer, MemorySize(*lpBuffer), #Null)
dwDescription.s = PeekS(*lpBuffer)
Result = "Error: " + Str(dwMessageId) + " - " + Left(dwDescription, Len(dwDescription) - 1)
FreeMemory(*lpBuffer)
ProcedureReturn Result
EndProcedure
Procedure PacketInit(*PACKET.PACKET)
FillMemory(*PACKET, SizeOf( *PACKET ))
*packet\ip\Version = Val("%" +RSet(Bin(4),4,"0")+RSet(Bin((SizeOf(DIVERT_IPHDR) / #PB_Long) + 1),4,"0") )
; packet->ip.HdrLength = SizeOf(DIVERT_IPHDR) / 4 ; / SizeOf(UINT32);
*packet\ip\Length = htons_(SizeOf(PACKET) )
*packet\ip\TTL = 64
*packet\ip\Protocol = #IPPROTO_TCP
*packet\tcp\HdrLength = Val("%" + RSet(Bin(SizeOf(DIVERT_TCPHDR)+1 / #PB_Long),4,"0") + "0000")
;;;; Original
; memset(packet, 0, SizeOf(PACKET));
; packet->ip.Version = 4;
; packet->ip.HdrLength = SizeOf(DIVERT_IPHDR) / 4 ; / SizeOf(UINT32);
; packet->ip.Length = htons(SizeOf(PACKET));
; packet->ip.TTL = 64;
; packet->ip.Protocol = IPPROTO_TCP;
; packet->tcp.HdrLength = SizeOf(DIVERT_TCPHDR) / SizeOf(UINT32);
EndProcedure
#block_data = "HTTP/1.1 200 OK" + #CRLF$ +
"Connection: close" + #CRLF$ +
"Content-Type: text/html" + #CRLF$ +
#CRLF$ +
"<!doctype html>" + #LF$ +
"<html>" + #LF$ +
"<head>" + #LF$ +
"<title>BLOCKED!</title>" + #LF$ +
"</head>" + #LF$ +
"<body>" + #LF$ +
"<h1>BLOCKED!</h1>" + #LF$ +
"<hr>" + #LF$ +
"<p>This URL has been blocked!</p>" + #LF$ +
"</body>" + #LF$ +
"</html>"
WinDivert = OpenLibrary(#PB_Any, "WinDivert.dll")
If IsLibrary(WinDivert)
DivertOpen = GetFunction(WinDivert, "DivertOpen")
DivertRecv = GetFunction(WinDivert, "DivertRecv")
DivertHelperParsePacket = GetFunction(WinDivert, "DivertHelperParsePacket")
DivertHelperCalcChecksums = GetFunction(WinDivert, "DivertHelperCalcChecksums")
DivertSend = GetFunction(WinDivert, "DivertSend")
DivertClose = GetFunction(WinDivert, "DivertClose")
Packet.u = #MAXBUF
reset0.Packet : *reset.PACKET = @reset0
finish0.Packet : *finish.PACKET = @reset0
blockpage_len = SizeOf(DATAPACKET) + Len(#block_data) - 1
*blockpage.DATAPACKET = AllocateMemory(blockpage_len)
If Not *blockpage : Debug "*blockpage error: memory allocation failed" : End : EndIf
PacketInit(@*blockpage\header)
*blockpage\header\ip\Length = htons_(blockpage_len)
*blockpage\header\tcp\SrcPort = htons_(80)
*blockpage\header\tcp\Reserved2 = %00011000 ;;; <--- ACK+PSH
*blockpage\Data = AllocateMemory(Len(#block_data) - 1)
FillMemory(@*blockpage\Data, Len(#block_data) + 100)
PokeS(@*blockpage\Data, #block_data, Len(#block_data))
PacketInit(*reset)
*reset\tcp\Reserved2 = %00010100 ;<---- ACK+RST
PacketInit(*finish)
*finish\tcp\Reserved2 = %00010001 ;<---- ACK+FIN
filter.s = "outbound && ip && tcp.DstPort == 80 && tcp.PayloadLength > 0"
hWndDivert = DivertOpen(filter, #DIVERT_LAYER_NETWORK, #DIVERT_PRIORITY_DEFAULT, #DIVERT_FLAG_DEFAULT)
If hWndDivert <> #INVALID_HANDLE_VALUE
pAddr.DIVERT_ADDRESS
*ppIpHdr.DIVERT_IPHDR
*ppTcpHdr.DIVERT_TCPHDR
RunProgram("iexplore", "http://www.purebasic.com/", "")
Repeat
*pPacket = AllocateMemory(#MAXBUF)
If DivertRecv(hWndDivert, *pPacket, #MAXBUF, @pAddr, @recvLen)
DivertHelperParsePacket(*pPacket, recvLen, @*ppIpHdr, #Null, #Null, #Null, @*ppTcpHdr, #Null, @*ppData, @pDataLen)
If *ppData
If FindString(PeekS(*ppData, pDataLen), "purebasic")
; // (1) Send a TCP RST To the server; immediately closing the connection at the server's end.
; *reset\ip\HdrLength = *ppIpHdr\HdrLength ; <---- Not Needed now.
*reset\ip\Length = *ppIpHdr\Length ;<---- Needed
*reset\ip\SrcAddr = *ppIpHdr\SrcAddr
*reset\ip\DstAddr = *ppIpHdr\DstAddr
; *reset\tcp\HdrLength = *ppTcpHdr\HdrLength ;<----- Not Needed now
*reset\tcp\SrcPort = *ppTcpHdr\SrcPort
*reset\tcp\DstPort = htons_(80)
*reset\tcp\SeqNum = *ppTcpHdr\SeqNum
*reset\tcp\AckNum = *ppTcpHdr\AckNum
DivertHelperCalcChecksums(*reset, recvLen, #DIVERT_HELPER_NO_ICMP_CHECKSUM | #DIVERT_HELPER_NO_ICMPV6_CHECKSUM | #DIVERT_HELPER_NO_UDP_CHECKSUM)
If Not DivertSend(hWndDivert, *reset, recvLen, @pAddr, #Null)
Debug "*reset.DrivertSend: warning: failed To send reset packet"
Debug TestForError()
Continue
EndIf
; // (2) Send the blockpage To the browser:
; *blockpage\header\ip\HdrLength = *ppIpHdr\HdrLength ; <---- Not Needed now
*blockpage\header\ip\Length = *ppIpHdr\Length ; <---- Needed
*blockpage\header\ip\SrcAddr = *ppIpHdr\DstAddr
*blockpage\header\ip\DstAddr = *ppIpHdr\SrcAddr
; *blockpage\header\tcp\HdrLength = *ppTcpHdr\HdrLength ;<----- Not Needed now
*blockpage\header\tcp\DstPort = *ppTcpHdr\SrcPort
*blockpage\header\tcp\SeqNum = *ppTcpHdr\AckNum
*blockpage\header\tcp\AckNum = htonl_(ntohl_(*ppTcpHdr\SeqNum) + pDataLen)
pAddr\Direction ! pAddr\Direction
DivertHelperCalcChecksums(*blockpage, recvLen, 0)
If Not DivertSend(hWndDivert, *blockpage, recvLen, @pAddr, #Null)
Debug "*blockpage.DrivertSend: warning: failed To send block page packet"
Debug TestForError()
Continue
EndIf
; // (3) Send a TCP FIN To the browser; closing the connection at the browser's end.
; *finish\ip\HdrLength = *ppIpHdr\HdrLength ; <---- Not Needed now.
; *finish\ip\Length = *ppIpHdr\Length ; <---- Not Needed now.
*finish\ip\SrcAddr = *ppIpHdr\DstAddr
*finish\ip\DstAddr = *ppIpHdr\SrcAddr
; *finish\tcp\HdrLength = *ppTcpHdr\HdrLength ; <---- Not Needed now.
*finish\tcp\SrcPort = htons_(80)
*finish\tcp\DstPort = *ppTcpHdr\SrcPort
*finish\tcp\SeqNum = htonl_(ntohl_(PeekL(@*ppTcpHdr\AckNum)) + Len(#block_data) - 1)
*finish\tcp\AckNum = htonl_(ntohl_(PeekL(@*ppTcpHdr\SeqNum)) + pDataLen)
DivertHelperCalcChecksums(*finish, recvLen, #DIVERT_HELPER_NO_ICMP_CHECKSUM | #DIVERT_HELPER_NO_ICMPV6_CHECKSUM | #DIVERT_HELPER_NO_UDP_CHECKSUM)
If Not DivertSend(hWndDivert, *finish, recvLen, @pAddr, #Null)
Debug "*finish.DivertSend: warning: failed to send finish packet"
Debug TestForError() :
EndIf
Else
DivertSend(hWndDivert, *pPacket, recvLen, @pAddr, #Null)
EndIf
Else
DivertSend(hWndDivert, *pPacket, recvLen, @pAddr, #Null)
EndIf
Else
DivertSend(hWndDivert, *pPacket, recvLen, @pAddr, #Null)
EndIf
FreeMemory(*pPacket)
ForEver
DivertClose(hWndDivert)
FreeMemory(*finish)
FreeMemory(*reset)
EndIf
CloseLibrary(WinDivert)
RunProgram("sc", "stop WinDivert1.0", "", #PB_Program_Hide)
RunProgram("sc", "delete WinDivert1.0", "", #PB_Program_Hide)
EndIf