Page 9 of 14

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 1:45 am
by JHPJHP
I'll be glad to put this one behind us. :)

I think the new script matches the original example pretty closely... And if you give it the Ok - I can finally create a PacketInit() Procedure. :wink:

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 1:51 am
by Thunder93
Yep. this looks good. But that PacketInit() function isn't going to be easy :p

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 2:12 am
by Thunder93
Got it!... Working with the new function now perfectly.

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 2:20 am
by Thunder93
DING! DING! DING! heh

Code: Select all

#DIVERT_LAYER_NETWORK = 0
#DIVERT_PRIORITY_DEFAULT = 0
#DIVERT_FLAG_DEFAULT = 0
#MAXBUF = $FFFF
#DIVERT_DIRECTION_INBOUND = 1
#DIVERT_HELPER_NO_ICMP_CHECKSUM = 2
#DIVERT_HELPER_NO_ICMPV6_CHECKSUM = 4
#DIVERT_HELPER_NO_UDP_CHECKSUM = 16

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[0]
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(*xPACKET.PACKET)
   FillMemory(*xPACKET, SizeOf( *xPACKET ))
  PokeA(@*xPACKET\ip\HdrLength, Val("%" + RSet(Bin(4), 4, "0") + RSet(Bin(SizeOf(DIVERT_IPHDR) / 4), 4, "0")))
  PokeA(@*xPACKET\tcp\HdrLength, Val("%" + RSet(Bin(SizeOf(DIVERT_TCPHDR) / 4), 4, "0") + RSet(Bin(0), 4, "0")))
    *xPACKET\ip\Length = htons_(SizeOf(PACKET) )
    *xPACKET\ip\TTL = 64
    *xPACKET\ip\Protocol = #IPPROTO_TCP    
    
;;;; 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


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")
  HdrLength.a = Val("%" + RSet(Bin(4), 4, "0") + RSet(Bin(SizeOf(DIVERT_IPHDR) / 4), 4, "0"))
  Reserved1.a = Val("%" + RSet(Bin(SizeOf(DIVERT_TCPHDR) / 4), 4, "0") + RSet(Bin(0), 4, "0"))
  
  *reset.PACKET = AllocateMemory(SizeOf(PACKET))
  FillMemory(*reset, SizeOf(PACKET), 0)
;   PokeA(@*reset\ip\HdrLength, HdrLength)

 PacketInit(*reset)
  *reset\ip\Length = htons_(SizeOf(PACKET))
  *reset\ip\TTL = 64
  *reset\ip\Protocol = #IPPROTO_TCP
;   PokeA(@*reset\tcp\Reserved1, Reserved1)
  PokeA(@*reset\tcp\Fin, %00010100)
  blockdata.s = "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>"
  blocklength = SizeOf(DATAPACKET) + StringByteLength(blockdata)
  *blockpage.DATAPACKET = AllocateMemory(blocklength)
  FillMemory(*blockpage, blocklength, 0)
;   PokeA(@*blockpage\header\ip\HdrLength, HdrLength)
   PacketInit(*blockpage\header);

  *blockpage\header\ip\Length = htons_(blocklength)
  *blockpage\header\ip\TTL = 64
  *blockpage\header\ip\Protocol = #IPPROTO_TCP
  *blockpage\header\tcp\SrcPort = htons_(80)
;   PokeA(@*blockpage\header\tcp\Reserved1, Reserved1)
  PokeA(@*blockpage\header\tcp\Fin, %00011000)
  
  PokeS(@*blockpage\Data[0], blockdata, StringByteLength(blockdata), #PB_UTF8)
  
  
  *finish.PACKET = AllocateMemory(SizeOf(PACKET))
  FillMemory(*finish, SizeOf(PACKET), 0)
;   PokeA(@*finish\ip\HdrLength, HdrLength)

   PacketInit(*finish)
  *finish\ip\Length = htons_(SizeOf(PACKET))
  *finish\ip\TTL = 64
  *finish\ip\Protocol = #IPPROTO_TCP
;   PokeA(@*finish\tcp\Reserved1, Reserved1)
  PokeA(@*finish\tcp\Fin, %00010001)
  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")
            *reset\ip\SrcAddr = *ppIpHdr\SrcAddr
            *reset\ip\DstAddr = *ppIpHdr\DstAddr
            *reset\tcp\SrcPort = *ppTcpHdr\SrcPort
            *reset\tcp\DstPort = htons_(80)
            *reset\tcp\SeqNum = *ppTcpHdr\SeqNum
            *reset\tcp\AckNum = *ppTcpHdr\AckNum
            DivertHelperCalcChecksums(*reset, SizeOf(PACKET), #DIVERT_HELPER_NO_ICMP_CHECKSUM | #DIVERT_HELPER_NO_ICMPV6_CHECKSUM | #DIVERT_HELPER_NO_UDP_CHECKSUM)

            If Not DivertSend(hWndDivert, *reset, SizeOf(PACKET), @pAddr, #Null)
              Debug TestForError()
              Continue
            EndIf
            *blockpage\header\ip\SrcAddr = *ppIpHdr\DstAddr
            *blockpage\header\ip\DstAddr = *ppIpHdr\SrcAddr
            *blockpage\header\tcp\DstPort = *ppTcpHdr\SrcPort
            *blockpage\header\tcp\SeqNum = *ppTcpHdr\AckNum
            *blockpage\header\tcp\AckNum = htonl_(ntohl_(PeekL(@*ppTcpHdr\SeqNum)) + pDataLen)
            pAddr\Direction = #DIVERT_DIRECTION_INBOUND
            DivertHelperCalcChecksums(*blockpage, blocklength, #DIVERT_HELPER_NO_ICMP_CHECKSUM | #DIVERT_HELPER_NO_ICMPV6_CHECKSUM | #DIVERT_HELPER_NO_UDP_CHECKSUM)

            If Not DivertSend(hWndDivert, *blockpage, blocklength, @pAddr, #Null)
              Debug TestForError()
              Continue
            EndIf
            *finish\ip\SrcAddr = *ppIpHdr\DstAddr
            *finish\ip\DstAddr = *ppIpHdr\SrcAddr
            *finish\tcp\SrcPort = htons_(80)
            *finish\tcp\DstPort = *ppTcpHdr\SrcPort
            *finish\tcp\SeqNum = htonl_(ntohl_(PeekL(@*ppTcpHdr\AckNum)) + StringByteLength(blockdata))
            *finish\tcp\AckNum = htonl_(ntohl_(PeekL(@*ppTcpHdr\SeqNum)) + pDataLen)
            DivertHelperCalcChecksums(*finish, SizeOf(PACKET), #DIVERT_HELPER_NO_ICMP_CHECKSUM | #DIVERT_HELPER_NO_ICMPV6_CHECKSUM | #DIVERT_HELPER_NO_UDP_CHECKSUM)

            If Not DivertSend(hWndDivert, *finish, SizeOf(PACKET), @pAddr, #Null) : 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

*** Updated: Rev1, read the following post for explanation.

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 2:34 am
by Thunder93
There is/was a problem when sending the browser the data. The closing bracket on the </HTML> tag gone amiss e.g: </HTML

Remove all -1 after every StringByteLength(blockdata) command

:lol:

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 2:41 am
by Thunder93
I feel a whole lot better now! Before you came up with this little project I was doing something else. Then you got me hooked and I'm somewhat of a perfectionist, and I needed to get that just right.


... that'll teach ya! :lol:

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 2:55 am
by sec
Ohah, doing Man-in-the-middle (aka MITM) for inject the iframe to web packet is proxy/hacking stuff :twisted:

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 3:13 am
by Thunder93
Get your mind out of the gutter! :lol:

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 3:28 am
by JHPJHP
Too be honest, I was cursing your name or at least your moniker, with each error you found. :twisted:

I also pride myself on being a perfectionist, so I'm very happy that you pushed... I mean motivated me to not leave that last script in its previous state.
Before you came up with this little project I was doing something else.
Lets keep things accurate - this is your project, and I'm just along for the ride. :P

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 3:40 am
by Thunder93
LOL! Yea... that is pretty bad! I only have a few hours of programming time. Heh

But I figured you might have been cursing me some lol. But it all worked out for the better.

Your here more than just along for the ride. I seen you looking at those banks that we driven by.

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 5:51 pm
by Thunder93
Here's the PB version of Divert.h.

Like you suggested way back when.... I did use Macros for the GET and SET procedures. IPv6 GET and SET isn't completed, and with REM lines. When time permits I'll complete, and update this post.

Code: Select all

; /****************************************************************************/
; /* DIVERT API                                                               */
; /****************************************************************************/

; Divert address. 
Structure DIVERT_ADDRESS
  IfIdx.l
  SubIfIdx.l
  Direction.a
EndStructure : Global pAddr.DIVERT_ADDRESS

#DIVERT_DIRECTION_OUTBOUND = 0
#DIVERT_DIRECTION_INBOUND = 1


;  * Divert layers.
#DIVERT_LAYER_NETWORK = 0                        ; /* The network layer. 0 is the default. */
#DIVERT_LAYER_NETWORK_FORWARD = 1   ; /* The network layer (forwarded packets). */

; * Divert flags.
#DIVERT_FLAG_SNIFF = 1
#DIVERT_FLAG_DROP = 2

;  * Divert parameters.
#DIVERT_PARAM_QUEUE_LEN = 0       ;  /* Packet queue length. */
#DIVERT_PARAM_QUEUE_TIME = 1     ; /* Packet queue time. */


;  * Open a divert handle.
Prototype protoDivertOpen(filter.s, layer, priority.u, flags.q)
Global DivertOpen.protoDivertOpen

;  * Receive (Read) a packet from a divert handle
Prototype.b protoDivertRecv(handle, *pPacket, packetLen, pAddr, recvLen)
Global DivertRecv.protoDivertRecv

;  * Send (write/inject) a packet To a divert handle.
Prototype.b protoDivertSend(handle, *pPacket, packetLen, pAddr, sendLen)
Global DivertSend.protoDivertSend

;  * Close a divert handle.
Prototype.b protoDivertClose(handle)
Global DivertClose.protoDivertClose

;  * Set a divert handle parameter.
Prototype.b protoDivertSetParam(handle, param, value.q)
Global DivertSetParam.protoDivertSetParam

;  * Get a divert handle parameter.
Prototype.b protoDivertGetParam(handle, param, pValue.q)
Global DivertGetParam.protoDivertGetParam

; /****************************************************************************/
; /* DIVERT HELPER API                                                        */
; /****************************************************************************/

;  * IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions.
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 : Global *pIpHdr.DIVERT_IPHDR


Macro  DIVERT_IPHDR_GET_FRAGOFF
 (*pIpHdr \FragOff0 & $FF1F)
EndMacro

Macro DIVERT_IPHDR_GET_MF
  ((*pIpHdr\FragOff0 & $0020) >> 5)
EndMacro

Macro DIVERT_IPHDR_GET_DF
   ((*pIpHdr\FragOff0 & $0040) >> 6)
 EndMacro
 
 Macro  DIVERT_IPHDR_GET_RESERVED
  ((*pIpHdr\FragOff0 & $0080) >> 7)
EndMacro


Macro DIVERT_IPHDR_SET_FRAGOFF(val)
  *pIpHdr\FragOff0 = ((*pIpHdr\FragOff0 & $00E0) | ((val) & $FF1F))
EndMacro


Macro DIVERT_IPHDR_SET_MF(val) 
  *pIpHdr\FragOff0 = (*pIpHdr\FragOff0 & $FFDF) | (((val) & $0001) << 5)
EndMacro
 

Macro DIVERT_IPHDR_SET_DF(val) 
  *pIpHdr\FragOff0 = (*pIpHdr\FragOff0 & $FFBF) | (((val) & $0001) << 6)
EndMacro


Macro DIVERT_IPHDR_SET_RESERVED(val) 
  *pIpHdr\FragOff0 = (*pIpHdr\FragOff0 & $FF7F) | (((val) & $0001) << 7)
EndMacro

Structure DIVERT_IPV6HDR
  StructureUnion
    TrafficClass0.a
    Version.a
    FlowLabel0.a
    TrafficClass1.a
  EndStructureUnion
  FlowLabel1.u
  Length.u
  NextHdr.a
  HopLimit.a
  SrcAddr.l[4]
  DstAddr.l[4]
EndStructure : Global *pIpv6Hdr.DIVERT_IPV6HDR

; ; ; Macro DIVERT_IPV6HDR_GET_TRAFFICCLASS
; ; ;   ((*pIpv6Hdr\TrafficClass0 << 4) | (*pIpv6Hdr\TrafficClass1))
; ; ; EndMacro
; ; ; 
; ; ; Macro DIVERT_IPV6HDR_GET_FLOWLABEL
; ; ;   ((*pIpv6Hdr\FlowLabel0 << 16) | (*pIpv6Hdr\FlowLabel1))
; ; ; EndMacro
; ; ; 
; ; ; Macro DIVERT_IPV6HDR_SET_TRAFFICCLASS
; ; ;   ((*pIpv6Hdr\FlowLabel0 << 16) | (*pIpv6Hdr\FlowLabel1))
; ; ; EndMacro
; ; ; 
; ; ; Procedure DIVERT_IPV6HDR_SET_TRAFFICCLASS(val)
; ; ;   *pIpv6Hdr\TrafficClass0 = val >> 4
; ; ;   *pIpv6Hdr\TrafficClass1 = val
; ; ; EndProcedure
; ; ; 
; ; ; Procedure DIVERT_IPV6HDR_SET_FLOWLABEL(val)
; ; ;   *pIpv6Hdr\FlowLabel0 = val >> 16
; ; ;   *pIpv6Hdr\FlowLabel1 = val
; ; ; EndProcedure

Structure DIVERT_ICMPHDR
  Type.a
  Code.a
  Checksum.u
  Body.l
EndStructure : Global *pIcmpHdr.DIVERT_ICMPHDR

Structure DIVERT_ICMPV6HDR
  Type.a
  Code.a
  Checksum.u
  Body.l
EndStructure : Global *pIcmpv6Hdr.DIVERT_ICMPV6HDR

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 : Global *pTcpHdr.DIVERT_TCPHDR

Structure DIVERT_UDPHDR
  SrcPort.u
  DstPort.u
  Length.u
  Checksum.u
EndStructure : Global *pUdpHdr.DIVERT_UDPHDR


;  * Flags For DivertHelperCalcChecksums()
#DIVERT_HELPER_NO_IP_CHECKSUM = 1
#DIVERT_HELPER_NO_ICMP_CHECKSUM = 2
#DIVERT_HELPER_NO_ICMPV6_CHECKSUM = 4
#DIVERT_HELPER_NO_TCP_CHECKSUM = 8
#DIVERT_HELPER_NO_UDP_CHECKSUM = 16

;  * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
Prototype.b protoDivertHelperParsePacket(*pPacket, packetLen, *pIpHdr, *pIpv6Hdr, *pIcmpHdr, *pIcmpv6Hdr, *pTcpHdr, *pUdpHdr, *pData, pDataLen)
Global DivertHelperParsePacket.protoDivertHelperParsePacket

; * Parse an IPv4 address.
Prototype.b protoDivertHelperParseIPv4Address(addrStr.s, *pAddr)
Global DivertHelperParseIPv4Address.protoDivertHelperParseIPv4Address

;  * Parse an IPv6 address.
Prototype.b protoDivertHelperParseIPv6Address(addrStr.s, *pAddr)
Global DivertHelperParseIPv6Address.protoDivertHelperParseIPv6Address

;  * Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
Prototype protoDivertHelperCalcChecksums(*pPacket, packetLen, flags.q)
Global DivertHelperCalcChecksums.protoDivertHelperCalcChecksums
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 10:40 pm
by Thunder93
Hi JHPJHP.

When I said I was working on something else, I still meant WinDivert related. I also didn't mean that I was upset or anything to that nature. I'm actually very excited to see someone else taking shared interests. Like I was thinking to myself days ago.., and I'm pretty sure you on the same boat. It is good to be covering all bases now, and knocking out any and all possible porting issues to PB.

You and I together are making big strides on this, amazing how 1 mind and a half can make a difference. :lol:

The web content filtering that you was working on and experienced problems. Addressing the lengths problem made it stable. Something else to remember, if you replacing a string with a new string and the length is different, you'll need to update the headers information.

Code: Select all

replacedata = ReplaceString(replacedata, "images/logopb.gif", "images/Xogopb.gif")
Keeping the length but making a minor change to prevent the image from loading is okay. If you going to replace it to load another image on the server and this string is different length. The other parts of the page may be affected, like the other image on the page, and it wouldn't load. But your intentions were to replace the first image and not the second one.


Here is the update, but it doesn't address string replacements with different lengths.

Code: Select all

#DIVERT_LAYER_NETWORK = 0
#DIVERT_PRIORITY_DEFAULT = 0
#DIVERT_FLAG_DEFAULT = 0
#MAXBUF = $FFFF
#DIVERT_HELPER_NO_ICMP_CHECKSUM = 2
#DIVERT_HELPER_NO_ICMPV6_CHECKSUM = 4
#DIVERT_HELPER_NO_UDP_CHECKSUM = 16

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[0]
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

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")
  
;   filter.s = "ip.SrcAddr == 88.191.144.148 or ip.DstAddr == 88.191.144.148"
  filter.s = "(ip.SrcAddr == 88.191.144.148 or ip.DstAddr == 88.191.144.148) && tcp.Ack && 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
          replacedata.s = PeekS(*ppData, pDataLen)

          If FindString(replacedata, "images/logopb.gif")       
            Debug "DAMN! A MATCH! HOW COOL IS THAT?!?!?"
            replacedata = ReplaceString(replacedata, "images/logopb.gif", "images/Xogopb.gif")
;             replacelength = SizeOf(DATAPACKET) + Len(replacedata) - 1
            replacelength = SizeOf(DATAPACKET) + StringByteLength(replacedata)
            *replace.DATAPACKET = AllocateMemory(replacelength)
            FillMemory(*replace, replacelength, 0)
            *replace\header\ip\HdrLength = *ppIpHdr\HdrLength
            *replace\header\ip\TOS = *ppIpHdr\TOS
            *replace\header\ip\Length = *ppIpHdr\Length
            *replace\header\ip\Id = *ppIpHdr\Id
            *replace\header\ip\FragOff0 = *ppIpHdr\FragOff0
            *replace\header\ip\TTL = *ppIpHdr\TTL
            *replace\header\ip\Protocol = *ppIpHdr\Protocol
            *replace\header\ip\SrcAddr = *ppIpHdr\SrcAddr
            *replace\header\ip\DstAddr = *ppIpHdr\DstAddr
            *replace\header\tcp\SrcPort = *ppTcpHdr\SrcPort
            *replace\header\tcp\DstPort = *ppTcpHdr\DstPort
            *replace\header\tcp\SeqNum = *ppTcpHdr\SeqNum
            *replace\header\tcp\AckNum = *ppTcpHdr\AckNum
            *replace\header\tcp\Reserved1 = *ppTcpHdr\Reserved1
            *replace\header\tcp\Fin = *ppTcpHdr\Fin
            *replace\header\tcp\Window = *ppTcpHdr\Window
            *replace\header\tcp\UrgPtr = *ppTcpHdr\UrgPtr
;             *replace\Data[0] = AllocateMemory(Len(replacedata) - 1)
;             FillMemory(@*replace\Data[0], Len(replacedata) - 1)
;             PokeS(@*replace\Data[0], replacedata, Len(replacedata), #PB_UTF8)

           *replace\Data[0] = AllocateMemory(StringByteLength(replacedata))
            FillMemory(@*replace\Data[0], StringByteLength(replacedata))
            PokeS(@*replace\Data[0], replacedata, StringByteLength(replacedata))
            DivertHelperCalcChecksums(*replace, recvLen, #DIVERT_HELPER_NO_ICMP_CHECKSUM | #DIVERT_HELPER_NO_ICMPV6_CHECKSUM | #DIVERT_HELPER_NO_UDP_CHECKSUM)

            If Not DivertSend(hWndDivert, *replace, recvLen, @pAddr, #Null) : Debug TestForError() : EndIf

            FreeMemory(*replace)
          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)
  EndIf
  CloseLibrary(WinDivert)
  RunProgram("sc", "stop WinDivert1.0", "", #PB_Program_Hide)
  RunProgram("sc", "delete WinDivert1.0", "", #PB_Program_Hide)
EndIf
JHPJHP wrote:Just something I'm playing with, I would like to flesh this one out... but it's very temperamental - I'm guessing based on header size, possibly others. It would be cool to get it to work with external images / text.

There is a lot more to do, such as intercepting / reassembling the data packets (payload) to something readable, and that's just a start - but it seems like the natural progression of events - what do you think?

Run the script: Can you spot what is out of place? :)

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 10:56 pm
by JHPJHP
I was just in the process of posting this, and like some other instances after I hit the Submit button the post disappeared :?:

...And now I see that you beat me to the punch, but great minds (or at least busy ones) :P think alike:

One is what I posted before, but with the string length thing partially worked out. The second is the beginning of a Packet Data assembly script, but it needs a gzip inflate / deflate routine - and that's just for a start.
- notice after the data is reordered, it makes a lot more sense
-- on my system there is a max packet size of 1460, based on the MTU setting of 1500

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 11:21 pm
by Thunder93
You have to watch your language when posting on here... Otherwise your submission is futile. :lol:

Busy minds likely... Or at least one in a half :twisted:

Downloaded and had a look at your samples. Both looks good JHP.

JHPJHP wrote:I was just in the process of posting this, and like some other instances after I hit the Submit button the post disappeared :?:

...And now I see that you beat me to the punch, but great minds (or at least busy ones) :P think alike - see the following two examples:

https://www.dropbox.com/s/fp7li05bfzivs0t/WinDivert.zip

One is what I posted before, but with the string length thing partially worked out. The second is the beginning of a Packet Data assembly script, but it needs a gzip inflate / deflate routine - and that's just for a start.
- notice after the data is reordered, it makes a lot more sense
-- on my system there is a max packet size of 1460, based on the MTU setting of 1500

Re: Windows Filtering Platform

Posted: Thu Oct 03, 2013 11:33 pm
by JHPJHP
Just a quick note: Don't have the PureBasic site (forum included) loaded prior to testing the Replace script - it can cause a browser crash - otherwise it works pretty good, providing the "replacelength" value is set correctly.