{"id":13650774,"url":"https://github.com/FlUxIuS/p0f3plus","last_synced_at":"2025-04-22T18:32:38.489Z","repository":{"id":42007017,"uuid":"81836994","full_name":"FlUxIuS/p0f3plus","owner":"FlUxIuS","description":"A native and unofficial implementation of p0f3 in Python with extra analysis features: It's p0f3+!","archived":false,"fork":false,"pushed_at":"2022-04-07T14:00:30.000Z","size":36,"stargazers_count":23,"open_issues_count":1,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-01-25T00:48:52.022Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlUxIuS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-13T15:01:40.000Z","updated_at":"2024-01-04T16:54:51.000Z","dependencies_parsed_at":"2022-08-12T02:10:35.415Z","dependency_job_id":null,"html_url":"https://github.com/FlUxIuS/p0f3plus","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlUxIuS%2Fp0f3plus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlUxIuS%2Fp0f3plus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlUxIuS%2Fp0f3plus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlUxIuS%2Fp0f3plus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlUxIuS","download_url":"https://codeload.github.com/FlUxIuS/p0f3plus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223903168,"owners_count":17222495,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T02:00:40.849Z","updated_at":"2024-11-10T01:31:08.056Z","avatar_url":"https://github.com/FlUxIuS.png","language":"Python","funding_links":[],"categories":["Tools"],"sub_categories":[],"readme":"# p0f3plus\nA native and unofficial implementation of p0f3 in Python with extra analysis features: It's p0f+\n\n## Dependencies\n\n- Python 2 or 3\n- Scapy (use Scapy for Python3 if you prefer Python3)\n\nUse `pip install -r requirements.txt` (or `pip3` as needed) to install dependencies.\n\n## Fingerprint a PCAP file\n\nTo fingerprint a PCAP file, the `pcaprint.py` can be used in two different ways:\n\n* the classic way that prints each frames like p0f3 do;\n* or to aggregate services in a nmap XML file like.\n\nAdditionnal information are added to p0f3 signatures if some data are\nidentified in packets. These information include HTTP or SMB headers\n(other features can be implemented).\n\n## Why I should use this tool?\n\nThis tool is slow compared to the original C implementation of p0f3, but can be\nused to identify packets, and can be extend very quickly with useful features that\nuse payloads contained in the packets.\n\nOriginally, this tool was developped because the p0f implementation in Scapy is\nobsolete with p0f3 signatures, and these signatures were needed as a backup\nway to identify an OS, or/and a service.\n\n### Quick run\n\n#### Output in XML\n\nTo p0f3 with the default script `pcaprint.py` against a PCAP to output a nmap XML (beta),\nyou can use the following command:\n\n```\npython3 ./pcaprint.py -c capture.pcapng -o test.xml\n```\n\nAs a results, you'll see a basic XML files that contains information for each IP address\nas follows:\n\n```\n$ python3 ./pcaprint.py -c capture.pcapng -o output.xml\n\u003c?xml version=\"1.0\" ?\u003e\n  \u003c?xml-stylesheet type=\"text/xsl\" href=\"file:///usr/local/bin/../share/nmap/nmap.xsl\"?\u003e\n  \u003cnmaprun scanner=\"p0fplus\" start=\"1488468846\" startstr=\"Thu Mar 2 16:34:06 2017\"\u003e\n    \u003chost\u003e\n      \u003caddress addrtype=\"ipv4\" ipaddr=\"172.XXX.XXX.XXX\"/\u003e\n      \u003chostnames/\u003e\n      \u003cports\u003e\n        \u003cport portid=\"39428\" protocol=\"tcp\"\u003e\n          \u003cstate reason=\"push-ack\" state=\"open\"/\u003e\n          \u003cservice extrainfo=\"Debian\" product=\"OpenSSH\" version=\"7.3p1\"/\u003e\n        \u003c/port\u003e\n      \u003c/ports\u003e\n      \u003cos\u003e\n        \u003cosmatch accuracy=\"100\" name=\"Linux 3.11 and newer\"\u003e\n          \u003cosclass accuracy=\"100\" osfamily=\"Linux\" osgen=\"3.11 and newer\"/\u003e\n        \u003c/osmatch\u003e\n        \u003cosmatch accuracy=\"99\" name=\"Linux 2.2\"\u003e\n          \u003cosclass accuracy=\"99\" osfamily=\"Linux\" osgen=\"2.2.x\"/\u003e\n        \u003c/osmatch\u003e\n      \u003c/os\u003e\n    \u003c/host\u003e\n    \u003chost\u003e\n      \u003caddress addrtype=\"ipv4\" ipaddr=\"XXX.XXX.XXX.12\"/\u003e\n      \u003chostnames/\u003e\n      \u003cports\u003e\n        \u003cport portid=\"443\" protocol=\"tcp\"\u003e\n          \u003cstate reason=\"ack\" state=\"open\"/\u003e\n        \u003c/port\u003e\n      \u003c/ports\u003e\n    \u003c/host\u003e\n    \u003chost\u003e\n      \u003caddress addrtype=\"ipv4\" ipaddr=\"104.16.26.235\"/\u003e\n      \u003chostnames/\u003e\n      \u003cports\u003e\n        \u003cport portid=\"443\" protocol=\"tcp\"\u003e\n          \u003cstate reason=\"syn-ack\" state=\"open\"/\u003e\n        \u003c/port\u003e\n      \u003c/ports\u003e\n      \u003cos\u003e\n        \u003cosmatch accuracy=\"94\" name=\"Linux 2.6\"\u003e\n          \u003cosclass accuracy=\"94\" osfamily=\"Linux\" osgen=\"2.6.x\"/\u003e\n        \u003c/osmatch\u003e\n        \u003cosmatch accuracy=\"94\" name=\"Linux 3\"\u003e\n          \u003cosclass accuracy=\"94\" osfamily=\"Linux\" osgen=\"3.x\"/\u003e\n        \u003c/osmatch\u003e\n      \u003c/os\u003e\n    \u003c/host\u003e\n    \u003chost\u003e\n      \u003caddress addrtype=\"ipv4\" ipaddr=\"104.16.118.182\"/\u003e\n      \u003chostnames\u003e\n        \u003chostname name=\"stackexchange.com\"/\u003e\n        \u003chostname name=\"christianity.stackexchange.com\"/\u003e\n        \u003chostname name=\"money.stackexchange.com\"/\u003e\n        \u003chostname name=\"puzzling.stackexchange.com\"/\u003e\n        \u003chostname name=\"rpg.stackexchange.com\"/\u003e\n        \u003chostname name=\"tex.stackexchange.com\"/\u003e\n        \u003chostname name=\"webapps.stackexchange.com\"/\u003e\n        \u003chostname name=\"workplace.stackexchange.com\"/\u003e\n        \u003chostname name=\"3dprinting.stackexchange.com\"/\u003e\n        \u003chostname name=\"astronomy.stackexchange.com\"/\u003e\n        \u003chostname name=\"biology.stackexchange.com\"/\u003e\n        \u003chostname name=\"blender.stackexchange.com\"/\u003e\n        \u003chostname name=\"chemistry.stackexchange.com\"/\u003e\n        \u003chostname name=\"expressionengine.stackexchange.com\"/\u003e\n      \u003c/hostnames\u003e\n    \u003c/host\u003e\n    \u003chost\u003e\n      \u003caddress addrtype=\"ipv4\" ipaddr=\"216.XXX.XXX.XXX\"/\u003e\n      \u003chostnames/\u003e\n      \u003cports\u003e\n        \u003cport portid=\"80\" protocol=\"tcp\"\u003e\n          \u003cstate reason=\"push-ack\" state=\"open\"/\u003e\n          \u003cservice extrainfo=\"\" product=\"cafe\" version=\"\"/\u003e\n        \u003c/port\u003e\n      \u003c/ports\u003e\n      \u003cos\u003e\n        \u003cosmatch accuracy=\"92\" name=\"Linux 2.6\"\u003e\n          \u003cosclass accuracy=\"92\" osfamily=\"Linux\" osgen=\"2.6.x\"/\u003e\n        \u003c/osmatch\u003e\n        \u003cosmatch accuracy=\"92\" name=\"Linux 3\"\u003e\n          \u003cosclass accuracy=\"92\" osfamily=\"Linux\" osgen=\"3.x\"/\u003e\n        \u003c/osmatch\u003e\n      \u003c/os\u003e\n    \u003c/host\u003e\n    [...]\n    \u003chost\u003e\n      \u003caddress addrtype=\"ipv4\" ipaddr=\"XXX.XXX.XXX.XXX\"/\u003e\n      \u003chostnames/\u003e\n      \u003cports\u003e\n        \u003cport portid=\"6526\" protocol=\"tcp\"\u003e\n          \u003cstate reason=\"push-ack\" state=\"open\"/\u003e\n          \u003cservice extrainfo=\"\" product=\"OpenSSH\" version=\"6.7p1\"/\u003e\n        \u003c/port\u003e\n      \u003c/ports\u003e\n      \u003cos\u003e\n        \u003cosmatch accuracy=\"99\" name=\"Linux 3\"\u003e\n          \u003cosclass accuracy=\"99\" osfamily=\"Linux\" osgen=\"3.x\"/\u003e\n        \u003c/osmatch\u003e\n      \u003c/os\u003e\n    \u003c/host\u003e\n  \u003c/nmaprun\u003e\n```\n\n#### The classic p0f way\n\nIf you're nostalgic and want to print the PCAP pretty like p0f3 do, you can run\nthe following command:\n\n```\n$ python3 ./pcaprint.py -c capture.pcapng -p\n\n.-[TCP XXX.XXX.XXX.XXX/80 -\u003e 10.11.10.136/48370 (push+ack)]-\n|---(packet payload fingerprints)\n|   os: Debian\n|   version: 2.222\n|   allow: GET,HEAD,POST,OPTIONS\n|   application: Apache\n|---(p0f signatures)\n|   label= s:!:Apache:2.x\n|   best guess sig= 1:Date,Server,?Last-Modified,?Accept-Ranges=[bytes],?Content-Length,?Connection=[close],?Transfer-Encoding=[chunked],Content-Type:Keep-Alive:Apache\n|   original sig= 1:Date,Server,Allow,Vary,Content-Length,Connection=[close],Content-Type:*:Apache\n|   sig computed= 1:Date,Server,Content-Length,Connection=[close],Content-Type:Keep-Alive:Apache\n|   distance= 11\n|   Distance too long! other guesses=\u003e\n|       Top1= sig:1:Date,Server,?Last-Modified,?Accept-Ranges=[bytes],?Content-Length,?Content-Range,Keep-Alive=[timeout],Connection=[Keep-Alive],?Transfer-Encoding=[chunked],Content-Type::Apache, label:s:!:Apache:2.x\n|       Top2= sig:1:Date,Server,?Last-Modified,?Accept-Ranges=[bytes],?Content-Length,?Connection=[close],?Transfer-Encoding=[chunked],Content-Type:Keep-Alive:Apache, label:s:!:Apache:2.x\n`----\n\nP 10.11.10.136/52244 -\u003e XXX.XXX.XXX.XXX/2013 (syn)]-\n|---(p0f signatures)\n|   label= s:!:NMap:SYN scan\n|   best guess sig= *:64-:0:1460:1024,0:mss::0\n|   original sig= 4:38:0:1460:1024:mss::0\n|   sig computed= 4:38:0:1460:1024:mss::0\n|   distance= 0\n`----\n\n.-[TCP 10.11.10.136/47220 -\u003e XXX.XXX.XXX.XXX/443 (syn)]-\n|---(p0f signatures)\n|   label= s:unix:Linux:3.11 and newer\n|   best guess sig= *:64:0:*:mss*20,10:mss,sok,ts,nop,ws:df,id+:0\n|   original sig= 4:64:0:1460:29200,10:mss,sok,ts,nop,ws:df,id+:0\n|   sig computed= 4:64:0:1460:29200,10:mss,sok,ts,nop,ws:df,id+:0\n|   distance= 0\n`----\n\n.-[TCP XXX.XXX.XXX.XXX/443 -\u003e 10.11.10.136/47220 (syn+ack)]-\n|---(p0f signatures)\n|   label= s:unix:Linux:3.x\n|   best guess sig= *:64:0:*:mss*10,*:mss,sok,ts,nop,ws:df:0\n|   original sig= 4:55:0:1448:14480,5:mss,sok,ts,nop,ws:df:0\n|   sig computed= 4:64:0:1448:14480,5:mss,sok,ts,nop,ws:df:0\n|   distance= 2\n`----\n```\n## Use the API\n\nYou can add the project in your Python library path, then p0f3plus's methods as follows to identify a packet:\n\n```python\nfrom p0f3p.core.p0f3p import *\n\na = p0f3p()\npacket = '\\x00\\xba\\xd0\\xc0\\xff\\xee@Z\\x9b\\xe8\\xdb\\x91\\x08\\x00E\\x00\\x015\\x0b @\\x007\\x06\\x99\\x07h\\x10!\\xf9BBBB\\x00P\\xb7t\\xa4\\xf0\\x1d\\x0c\\x1c{\\xcb\\x9bP\\x18\\x00 v\\xdd\\x00\\x00HTTP/1.1 204 No Content\\r\\nDate: Thu, 21 Apr 2016 11:08:56 GMT\\r\\nConnection: keep-alive\\r\\nCache-Control: private\\r\\nPragma: no-cache\\r\\nX-Frame-Options: SAMEORIGIN\\r\\nX-Request-Guid: 2f5dfddc-1d7a-45d7-a739-00584d917948\\r\\nServer: cloudflare-nginx\\r\\nCF-RAY: 29706181e6ee102b-CDG\\r\\n\\r\\n'\npktsign = a.pkt2sig(Ether(packet)) # transforms it to 'PacketSignature' object. Value of pktsign.signature = '1:Date,Connection=[keep-alive],Cache-Control,Pragma,X-Frame-Options,X-Request-Guid,Server,CF-RAY:*:cloudflare'\nmatches = a.matchsig(pktsign) # Gets matches in a 'ClassifiedSignature' object. The computed signature before the matching is '1:Date,Server,Connection=[Keep-Alive],Keep-Alive=[timeout]:Content-Type,Accept-Ranges:Apache'. The best match is '1:Date,Server,Connection=[Keep-Alive],Keep-Alive=[timeout]:Content-Type,Accept-Ranges:Apache' and you can access to the top3, label, distance, etc. to perform your analysises.\n```\n\n## Contributions\n\nA lot of work need to be done, this tool needs more features to identify packets, an IPv6 support, and so on.\nThis project is also opened for suggestions, so any contribution is welcomed :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFlUxIuS%2Fp0f3plus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFlUxIuS%2Fp0f3plus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFlUxIuS%2Fp0f3plus/lists"}