Jump to content

p0f mangler


fugu

Recommended Posts

this is a work in progress but I figure what the heck. linux can easily change wifi mac addresses. i've always thought it should be able to easily change the syn packet fingerprint as well, but it can't (afaik). this python program can alter the syn packets before they leave the computer. it only works on linux, and needs iptables with nfqueue, python-nfqueue, and scapy.
WARNING: this will alter your current firewall and I can't guarantee that it will not break anything. If you want to add the NFQUEUE entries manually to the outgoing rules of you iptables, then I suggest that you comment out the 3 lines that contain os.system('iptables-restore '+tempfile_name).
This program will try to save the state of your firewall when it starts up, and will try to restore it when the program finishes.
This program currently will not work if there are any iptables rules that contain a --state parameter, because I think that conntrack is not properly tracking the new altered packets as the orginal connection.
So here it is, test it at your own risk:

import logging

l=logging.getLogger("scapy.runtime")
l.setLevel(49)

import os,sys,nfqueue,re,socket
from scapy.all import *

conf.verbose = 0
conf.L3socket = L3RawSocket

#Win7 syn
chars = dict();
chars["ip_frag"] = 0L;
chars["ip_ttl"] = 128;
chars["tcp_window"] = 8192;
chars["tcp_options"] =  [('MSS', 1460), ('NOP', None), ('WScale', 2), ('NOP', None), ('NOP', None), ('SAckOK', '')]

##########################
########################## MODIFING FIREWALL
##########################
#store orginal firewall
proc_str = "iptables-save"
proc = subprocess.Popen(proc_str, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
iptables_save = ''
for line in proc.stdout:
    iptables_save += line

#create modified firewall to allow packet capture of out going packets only
# FYI, by altering the outgoing packets info, the response packets will
# not completely "pair up" to the the ones iptables tried to send out,
# ipso facto we have to break connection tracking to change our fingerprint
iptables_save_nfqueue = re.sub(r"OUTPUT(.*)-j ACCEPT", "OUTPUT\g<1>-j NFQUEUE --queue-num 0", iptables_save)
iptables_save_nfqueue = re.sub("-A\s+OUTPUT\s+-o\s+lo\s+-j NFQUEUE --queue-num 0", "-A OUTPUT -o lo -j ACCEPT", iptables_save_nfqueue)

proc_str = "tempfile"
proc = subprocess.Popen(proc_str, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
tempfile_name = ''
for line in proc.stdout:
    tempfile_name += line
tempfile_name = tempfile_name[:-1]
outputFile = open(tempfile_name, "w")
outputFile.write(iptables_save_nfqueue)
outputFile.close()
os.system('iptables-restore '+tempfile_name)
os.remove(tempfile_name)
# END FIREWALL MOD

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(("eth0", 0x0800))

def send_rawsock(pkt):
    global s
    s.send(str(pkt))

def process(i, payload):
    global chars
    data = payload.get_data()
    pkt = IP(data)
    proto = pkt.proto

    #print data.encode("hex")
    # Check if it is a ICMP packet
    if proto is 0x01:
        #print "ICMP PACKET"
        payload.set_verdict(nfqueue.NF_ACCEPT)
        pass
    # Check if it is an TCP packet
    elif proto is 0x06:
        if int(pkt[TCP].flags) is 2: #SYN-only
            #print "TCP SYN PACKET"
            new_tcp_opts_len = len(chars["tcp_options"])
            current_tcp_opts_len = len(pkt[TCP].options)
            options_are_the_same = True
            if pkt[IP].frag != chars["ip_frag"]:
                options_are_the_same = False

            if pkt[IP].ttl != chars["ip_ttl"]:
                options_are_the_same = False

            if pkt[TCP].window != chars["tcp_window"]:
                options_are_the_same = False

            if current_tcp_opts_len == new_tcp_opts_len:
                for i in range(0,current_tcp_opts_len):
                    if pkt[TCP].options[i][0] != chars["tcp_options"][i][0]:
                        options_are_the_same = False
                        break
                    if pkt[TCP].options[i][1] != chars["tcp_options"][i][1]:
                        options_are_the_same = False
                        break
            if options_are_the_same:
                payload.set_verdict(nfqueue.NF_ACCEPT)
                pass
            else:
                payload.set_verdict(nfqueue.NF_DROP)

                newpkt = Ether()/IP()/TCP()
                newpkt[IP].version = pkt[IP].version
                newpkt[IP].ihl = pkt[IP].ihl
                newpkt[IP].tos = pkt[IP].tos
                #newpkt[IP].len = pkt[IP].len
                newpkt[IP].id = pkt[IP].id
                newpkt[IP].flags = pkt[IP].flags
                newpkt[IP].frag = chars["ip_frag"]
                newpkt[IP].ttl = chars["ip_ttl"]
                newpkt[IP].proto = pkt[IP].proto
                newpkt[IP].src = pkt[IP].src
                newpkt[IP].dst = pkt[IP].dst
                newpkt[IP].options = pkt[IP].options

                newpkt[TCP].sport = pkt[TCP].sport
                newpkt[TCP].dport = pkt[TCP].dport
                newpkt[TCP].seq = pkt[TCP].seq
                newpkt[TCP].ack = pkt[TCP].ack
                #newpkt[TCP].dataofs = pkt[TCP].dataofs
                newpkt[TCP].reserved = pkt[TCP].reserved
                newpkt[TCP].flags = pkt[TCP].flags
                newpkt[TCP].window = chars["tcp_window"]
                newpkt[TCP].urgptr = pkt[TCP].urgptr
                newpkt[TCP].options = chars["tcp_options"]

                send_rawsock(newpkt)
                pass
        else:
            #print "TCP NONSYN PACKET"
            payload.set_verdict(nfqueue.NF_ACCEPT)
            pass
    # Check if it is an UDP packet
    elif proto is 0x11:
        #print "UDP PACKET"
        payload.set_verdict(nfqueue.NF_ACCEPT)
        pass
    # packet is other
    else:
        #print "OTHER PACKET"
        payload.set_verdict(nfqueue.NF_ACCEPT)
        pass

def main(s):
    global iptables_save
    q = nfqueue.queue()
    q.open()
    q.set_callback(process)
    q.fast_open(0, socket.AF_INET)

    try:
        q.try_run()
    except KeyboardInterrupt:
        print "Exiting..."
        q.unbind(socket.AF_INET)
        q.close()
        s.close()

        #restore orginal firewall
        proc_str = "tempfile"
        proc = subprocess.Popen(proc_str, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
        tempfile_name = ''
        for line in proc.stdout:
            tempfile_name += line
        tempfile_name = tempfile_name[:-1]
        outputFile = open(tempfile_name, "w")
        outputFile.write(iptables_save)
        outputFile.close()
        os.system('iptables-restore '+tempfile_name)
        os.remove(tempfile_name)

try:
    main(s)
except:
        print "Error: caught main(s) exception"
        #restore orginal firewall
        proc_str = "tempfile"
        proc = subprocess.Popen(proc_str, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
        tempfile_name = ''
        for line in proc.stdout:
            tempfile_name += line
        tempfile_name = tempfile_name[:-1]
        outputFile = open(tempfile_name, "w")
        outputFile.write(iptables_save)
        outputFile.close()
        os.system('iptables-restore '+tempfile_name)
        os.remove(tempfile_name)

Edited by fugu
Link to comment
Share on other sites

  • 2 weeks later...

FYI: you can test this with

sudo p0f -i eth0 -f /etc/p0f/p0f.fp "tcp[tcpflags] & (tcp-syn) != 0 && tcp[tcpflags] & (tcp-ack) = 0"

I do have a question that maybe some one here can anwser. I've been trying to contact the people from netfilter; they don't have forums but they do have a mailing list which is not functioning as far as I can tell, and even email that I've found has not had any response. Anyone have a clue how I can get help from them, or with netfilter in general? thanks

Link to comment
Share on other sites

NETFILTER ({IP,IP6,ARP,EB,NF}TABLES)

M: Pablo Neira Ayuso <pablo@netfilter.org>

M: Patrick McHardy <kaber@trash.net>

M: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

L: netfilter-devel@vger.kernel.org

L: coreteam@netfilter.org

Edited by Cooper
Link to comment
Share on other sites

  • 2 weeks later...

From http://people.netfilter.org/pablo/docs/login.pdf : pneira@lsi.us.es is another email address for Pablo Neira.

Looking at their github the last commit was 4 days ago, so the project is still alive and kicking.

You could try talking to some of the prople from that list who provided fixes about your questions and how and where they got into contact with developers.

Link to comment
Share on other sites

  • 6 years later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...