Guest User

Untitled

a guest
Jun 3rd, 2010
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.23 KB | None | 0 0
  1. #!/usr/bin/env python
  2. """
  3. Scalp! Apache log based attack analyzer
  4. by Romain Gaucher <[email protected]> - http://rgaucher.info
  5. http://code.google.com/p/apache-scalp
  6.  
  7.  
  8. Copyright (c) 2008 Romain Gaucher <[email protected]>
  9.  
  10. Licensed under the Apache License, Version 2.0 (the "License");
  11. you may not use this file except in compliance with the License.
  12. You may obtain a copy of the License at
  13.  
  14. http://www.apache.org/licenses/LICENSE-2.0
  15.  
  16. Unless required by applicable law or agreed to in writing, software
  17. distributed under the License is distributed on an "AS IS" BASIS,
  18. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. See the License for the specific language governing permissions and
  20. limitations under the License.
  21.  
  22. """
  23. from __future__ import with_statement
  24. import time, base64
  25. import os,sys,re,random
  26. from StringIO import StringIO
  27. try:
  28. from lxml import etree
  29. except ImportError:
  30. try:
  31. import xml.etree.cElementTree as etree
  32. except ImportError:
  33. try:
  34. import xml.etree.ElementTree as etree
  35. except ImportError:
  36. print "Cannot find the ElementTree in your python packages"
  37.  
  38. __application__ = "scalp"
  39. __version__ = "0.4"
  40. __release__ = __application__ + '/' + __version__
  41. __author__ = "Romain Gaucher"
  42.  
  43. names = {
  44. 'xss' : 'Cross-Site Scripting',
  45. 'sqli' : 'SQL Injection',
  46. 'csrf' : 'Cross-Site Request Forgery',
  47. 'dos' : 'Denial Of Service',
  48. 'dt' : 'Directory Traversal',
  49. 'spam' : 'Spam',
  50. 'id' : 'Information Disclosure',
  51. 'rfe' : 'Remote File Execution',
  52. 'lfi' : 'Local File Inclusion'
  53. }
  54.  
  55. c_reg = re.compile(r'^(.+)-(.*)\[(.+)[-|+](\d+)\] "([A-Z]+)?(.+) HTTP/\d.\d" (\d+)(\s[\d]+)?(\s"(.+)" )?(.*)$')
  56. table = {}
  57.  
  58. txt_header = """
  59. #
  60. # File created by Scalp! by Romain Gaucher - http://code.google.com/p/apache-scalp
  61. # Apache log attack analysis tool based on PHP-IDS filters
  62. #
  63. """
  64.  
  65. xml_header = """<!--
  66. File created by Scalp! by Romain Gaucher - http://code.google.com/p/apache-scalp
  67. Apache log attack analysis tool based on PHP-IDS filters
  68. -->
  69. <?xml version="1.0" encoding="utf-8"?>
  70. """
  71.  
  72. html_header = """<html><head><style>
  73. html, body {background-color:#ccc;color:#222;font-family:'Lucida Grande',Verdana,Arial,Sans-Serif;font-size:0.8em;line-height:1.6em;margin:0;padding:0;}
  74. body {background-color:#fff;padding:0; margin: 15px; border: 1px solid #444;}
  75. h1 { display: block; border-bottom: 2px solid #333; padding: 5px;}
  76. h2 { display: block; font-size: 1.5em; font-weight: 700; background-color: #efefef;margin:10px;padding-left: 15px;}
  77. .match { display: block; margin: 10px; border: 1px solid; padding: 5px;}
  78. .impact { float: right; background-color: #fff; border: 1px solid #ccc; padding: 5px; font-size: 1.8em;}
  79. .impact-1,.impact-2,.impact-3 { background-color: #f2ffe0; border-color: #DEF0C3;}
  80. .impact-4,.impact-5 { background-color: #ffe6bf; border-color: #ffd38f;}
  81. .impact-6,.impact-7,.impact-8,.impact-9,.impact-10,.impact-11 /*...*/ { background-color: #FFEDEF; border-color: #FFC2CA;}
  82. .block {display:block; margin:5px;}
  83. .highlight {margin: 5px;}
  84. .reason {font-weight: 700; color: #444;}
  85. .line, .regexp {border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; background-color: #fff; padding: 2px; margin: 10px;}
  86. #footer {text-align: center;}
  87. </style></head><body>"""
  88.  
  89. html_footer = "<div id='footer'>Scalp by Romain Gaucher &lt;[email protected]&gt; - <a href='http://rgaucher.info'>http://rgaucher.info</a></div></body></html>"
  90.  
  91. class object_dict(dict):
  92. def __init__(self, initd=None):
  93. if initd is None:
  94. initd = {}
  95. dict.__init__(self, initd)
  96. def __getattr__(self, item):
  97. d = self.__getitem__(item)
  98. # if value is the only key in object, you can omit it
  99. if isinstance(d, dict) and 'value' in d and len(d) == 1:
  100. return d['value']
  101. else:
  102. return d
  103. def __setattr__(self, item, value):
  104. self.__setitem__(item, value)
  105.  
  106. def __parse_node(node):
  107. tmp = object_dict()
  108. # save attrs and text, hope there will not be a child with same name
  109. if node.text:
  110. tmp['value'] = node.text
  111. for (k,v) in node.attrib.items():
  112. tmp[k] = v
  113. for ch in node.getchildren():
  114. cht = ch.tag
  115. chp = __parse_node(ch)
  116. if cht not in tmp: # the first time, so store it in dict
  117. tmp[cht] = chp
  118. continue
  119. old = tmp[cht]
  120. if not isinstance(old, list):
  121. tmp.pop(cht)
  122. tmp[cht] = [old] # multi times, so change old dict to a list
  123. tmp[cht].append(chp) # add the new one
  124. return tmp
  125.  
  126. def parse(xml_file):
  127. try:
  128. xml_handler = open(xml_file, 'r')
  129. doc = etree.parse(xml_handler).getroot()
  130. xml_handler.close()
  131. return object_dict({doc.tag: __parse_node(doc)})
  132. except IOError:
  133. print "error: problem with the filter's file"
  134. return {}
  135.  
  136. def get_value(array, default):
  137. if 'value' in array:
  138. return array['value']
  139. return default
  140.  
  141. def html_entities(str):
  142. out = ""
  143. for i in str:
  144. if i == '"': out += '&quot;'
  145. elif i == '<': out += '&lt;'
  146. elif i == '>': out += '&gt;'
  147. else:
  148. out += i
  149. return out
  150.  
  151. d_replace = {
  152. "\r":";",
  153. "\n":";",
  154. "\f":";",
  155. "\t":";",
  156. "\v":";",
  157. "'":"\"",
  158. "+ACI-":"\"",
  159. "+ADw-":"<",
  160. "+AD4-" : ">",
  161. "+AFs-" : "[",
  162. "+AF0-" : "]",
  163. "+AHs-" : "{",
  164. "+AH0-" : "}",
  165. "+AFw-" : "\\",
  166. "+ADs-" : ";",
  167. "+ACM-" : "#",
  168. "+ACY-" : "&",
  169. "+ACU-" : "%",
  170. "+ACQ-" : "$",
  171. "+AD0-" : "=",
  172. "+AGA-" : "'",
  173. "+ALQ-" : "\"",
  174. "+IBg-" : "\"",
  175. "+IBk-" : "\"",
  176. "+AHw-" : "|",
  177. "+ACo-" : "*",
  178. "+AF4-" : "^",
  179. "+ACIAPg-" : "\">",
  180. "+ACIAPgA8-" : "\">",
  181. }
  182. re_replace = None
  183.  
  184.  
  185. def fill_replace_dict():
  186. global d_replace, re_replace
  187. # very first control-chars
  188. for i in range(0,20):
  189. d_replace["%%%x" % i] = "%00"
  190. d_replace["%%%X" % i] = "%00"
  191. # javascript charcode
  192. for i in range(33,127):
  193. c = "%c" % i
  194. d_replace["\\%o" % i] = c
  195. d_replace["\\%x" % i] = c
  196. d_replace["\\%X" % i] = c
  197. d_replace["0x%x" % i] = c
  198. d_replace["&#%d;" % i] = c
  199. d_replace["&#%x;" % i] = c
  200. d_replace["&#%X;" % i] = c
  201. # SQL words?
  202. d_replace["is null"]="=0"
  203. d_replace["like null"]="=0"
  204. d_replace["utc_time"]=""
  205. d_replace["null"]=""
  206. d_replace["true"]=""
  207. d_replace["false"]=""
  208. d_replace["localtime"]=""
  209. d_replace["stamp"]=""
  210. d_replace["binary"]=""
  211. d_replace["ascii"]=""
  212. d_replace["soundex"]=""
  213. d_replace["md5"]=""
  214. d_replace["between"]="="
  215. d_replace["is"]="="
  216. d_replace["not in"]="="
  217. d_replace["xor"]="="
  218. d_replace["rlike"]="="
  219. d_replace["regexp"]="="
  220. d_replace["sounds like"]="="
  221. re_replace = re.compile("(%s)" % "|".join(map(re.escape, d_replace.keys())))
  222.  
  223.  
  224. def multiple_replace(text):
  225. return re_replace.sub(lambda mo: d_replace[mo.string[mo.start():mo.end()]], text)
  226.  
  227. # the decode engine tries to detect then decode...
  228. def decode_attempt(string):
  229. return multiple_replace(string)
  230.  
  231. def analyzer(data):
  232. exp_line, regs, array, preferences, org_line = data[0],data[1],data[2],data[3],data[4]
  233. done = []
  234. # look for the detected attacks...
  235. # either stop at the first found or not
  236. for attack_type in preferences['attack_type']:
  237. if attack_type in regs:
  238. if attack_type not in array:
  239. array[attack_type] = {}
  240. for _hash in regs[attack_type]:
  241. if _hash not in done:
  242. done.append(_hash)
  243. attack = table[_hash]
  244. cur_line = exp_line[5]
  245. if preferences['encodings']:
  246. cur_line = decode_attempt(cur_line)
  247. if attack[0].search(cur_line):
  248. if attack[1] not in array[attack_type]:
  249. array[attack_type][attack[1]] = []
  250. array[attack_type][attack[1]].append((exp_line, attack[3], attack[2], org_line))
  251. if preferences['exhaustive']:
  252. break
  253. else:
  254. return
  255.  
  256. def scalper(access, filters, preferences = [], output = "text"):
  257. global table
  258. if not os.path.isfile(access):
  259. print "error: the log file doesn't exist"
  260. return
  261. if not os.path.isfile(filters):
  262. print "error: the filters file (XML) doesn't exist"
  263. print "please download it at https://svn.php-ids.org/svn/trunk/lib/IDS/default_filter.xml"
  264. return
  265. if output not in ('html', 'text', 'xml'):
  266. print "error: the output format '%s' hasn't been recognized" % output
  267. return
  268. # load the XML file
  269. xml_filters = parse(filters)
  270. len_filters = len(xml_filters)
  271. if len_filters < 1:
  272. return
  273. # prepare to load the compiled regular expression
  274. regs = {} # type => (reg.compiled, impact, description, rule)
  275.  
  276. print "Loading XML file '%s'..." % filters
  277. for group in xml_filters:
  278. for f in xml_filters[group]:
  279. if f == 'filter':
  280. if type(xml_filters[group][f]) == type([]):
  281. for elmt in xml_filters[group][f]:
  282. rule, impact, description, tags = "",-1,"",[]
  283. if 'impact' in elmt:
  284. impact = get_value(elmt['impact'], -1)
  285. if 'rule' in elmt:
  286. rule = get_value(elmt['rule'], "")
  287. if 'description' in elmt:
  288. description = get_value(elmt['description'], "")
  289. if 'tags' in elmt and 'tag' in elmt['tags']:
  290. if type(elmt['tags']['tag']) == type([]):
  291. for tag in elmt['tags']['tag']:
  292. tags.append(get_value(tag, ""))
  293. else:
  294. tags.append(get_value(elmt['tags']['tag'], ""))
  295. # register the entry in our array
  296. for t in tags:
  297. compiled = None
  298. if t not in regs:
  299. regs[t] = []
  300. try:
  301. compiled = re.compile(rule)
  302. except Exception:
  303. print "The rule '%s' cannot be compiled properly" % rule
  304. return
  305. _hash = hash(rule)
  306. if impact > -1:
  307. table[_hash] = (compiled, impact, description, rule, _hash)
  308. regs[t].append(_hash)
  309. if len(preferences['attack_type']) < 1:
  310. preferences['attack_type'] = regs.keys()
  311. flag = {} # {type => { impact => ({log_line dict}, rule, description, org_line) }}
  312.  
  313. print "Processing the file '%s'..." % access
  314.  
  315. sample, sampled_lines = False, []
  316. if preferences['sample'] != float(100):
  317. # get the number of lines
  318. sample = True
  319. total_nb_lines = sum(1 for line in open(access))
  320. # take a random sample
  321. random.seed(time.clock())
  322. sampled_lines = random.sample(range(total_nb_lines), int(float(total_nb_lines) * preferences['sample'] / float(100)))
  323. sampled_lines.sort()
  324.  
  325. loc, lines, nb_lines = 0, 0, 0
  326. old_diff = 0
  327. start = time.time()
  328. diff = []
  329. stream = None
  330. log_file = None
  331. try:
  332. stream = open(access,'r')
  333. log_file = stream.readlines()
  334. except IOError:
  335. print "Cannot open the file", access
  336. sys.exit(0)
  337.  
  338. for line in log_file:
  339. lines += 1
  340. if sample and lines not in sampled_lines:
  341. continue
  342. if c_reg.match(line):
  343. out = c_reg.search(line)
  344. ip = out.group(1)
  345. name = out.group(2)
  346. date = out.group(3)
  347. ext = out.group(4)
  348. method = out.group(5)
  349. url = out.group(6)
  350. response = out.group(7)
  351. byte = out.group(8)
  352. referrer = out.group(9)
  353. agent = out.group(10)
  354.  
  355. if not correct_period(date, preferences['period']):
  356. continue
  357. loc += 1
  358. if len(url) > 1 and method in ('GET','POST','HEAD','PUT','PUSH','OPTIONS'):
  359. analyzer([(ip,name,date,ext,method,url,response,byte,referrer,agent),regs,flag, preferences, line])
  360. elif preferences['except']:
  361. diff.append(line)
  362.  
  363. # mainly testing purposes...
  364. if nb_lines > 0 and lines > nb_lines:
  365. break
  366.  
  367.  
  368.  
  369. tt = time.time() - start
  370. n = 0
  371. for t in flag:
  372. for i in flag[t]:
  373. n += len(flag[t][i])
  374. print "Scalp results:"
  375. print "\tProcessed %d lines over %d" % (loc,lines)
  376. print "\tFound %d attack patterns in %f s" % (n,tt)
  377.  
  378. short_name = access[access.rfind(os.sep)+1:]
  379. if n > 0:
  380. print "Generating output in %s%s%s_scalp_*" % (preferences['odir'],os.sep,short_name)
  381. if 'html' in preferences['output']:
  382. generate_html_file(flag, short_name, filters, preferences['odir'])
  383. elif 'text' in preferences['output']:
  384. generate_text_file(flag, short_name, filters, preferences['odir'])
  385. elif 'xml' in preferences['output']:
  386. generate_xml_file(flag, short_name, filters, preferences['odir'])
  387.  
  388. # generate exceptions
  389. if len(diff) > 0:
  390. o_except = open(os.path.abspath(preferences['odir'] + os.sep + "scalp_except.txt"), "w")
  391. for l in diff:
  392. o_except.write(l + '\n')
  393. o_except.close()
  394.  
  395.  
  396. def generate_text_file(flag, access, filters, odir):
  397. curtime = time.strftime("%a-%d-%b-%Y", time.localtime())
  398. fname = '%s_scalp_%s.txt' % (access, curtime)
  399. fname = os.path.abspath(odir + os.sep + fname)
  400. try:
  401. out = open(fname, 'w')
  402. out.write(txt_header)
  403. out.write("Scalped file: %s\n" % access)
  404. out.write("Creation date: %s\n\n" % curtime)
  405. for attack_type in flag:
  406. if attack_type in names:
  407. out.write("Attack %s (%s)\n" % (names[attack_type], attack_type))
  408. else:
  409. out.write("Attack type: %s\n" % attack_type)
  410. impacts = flag[attack_type].keys()
  411. impacts.sort(reverse=True)
  412.  
  413. for i in impacts:
  414. out.write("\n\t### Impact %d\n" % int(i))
  415. for e in flag[attack_type][i]:
  416. out.write("\t%s" % e[3])
  417. out.write("\tReason: \"%s\"\n\n" % e[2])
  418. out.close()
  419. except IOError:
  420. print "Cannot open the file:", fname
  421. return
  422.  
  423.  
  424. def generate_xml_file(flag, access, filters, odir):
  425. curtime = time.strftime("%a-%d-%b-%Y", time.localtime())
  426. fname = '%s_scalp_%s.xml' % (access, curtime)
  427. fname = os.path.abspath(odir + os.sep + fname)
  428. try:
  429. out = open(fname, 'w')
  430. out.write(xml_header)
  431. out.write("<scalp file=\"%s\" time=\"%s\">\n" % (access, curtime))
  432. for attack_type in flag:
  433. name = ""
  434. if attack_type in names:
  435. name = " name=\"%s\"" % names[attack_type]
  436. out.write(" <attack type=\"%s\"%s>\n" % (attack_type, name))
  437. impacts = flag[attack_type].keys()
  438. impacts.sort(reverse=True)
  439. for i in impacts:
  440. out.write(" <impact value=\"%d\">\n" % int(i))
  441. for e in flag[attack_type][i]:
  442. out.write(" <item>\n")
  443. out.write(" <reason><![CDATA[%s]]></reason>\n" % e[2])
  444. out.write(" <line><![CDATA[%s]]></line>\n" % e[3])
  445. out.write(" </item>\n")
  446. out.write(" </impact>\n")
  447. out.write(" </attack>\n")
  448. out.write("</scalp>")
  449. out.close()
  450. except IOError:
  451. print "Cannot open the file:", fname
  452. return
  453. return
  454.  
  455. def generate_html_file(flag, access, filters, odir):
  456. curtime = time.strftime("%a-%d-%b-%Y", time.localtime())
  457. fname = '%s_scalp_%s.html' % (access, curtime)
  458. fname = os.path.abspath(odir + os.sep + fname)
  459. try:
  460. out = open(fname, 'w')
  461. out.write(html_header)
  462. out.write("<h1>Scalp of %s [%s]</h1>\n" % (access, curtime))
  463. for attack_type in flag:
  464. name = ""
  465. if attack_type in names:
  466. name = "%s" % names[attack_type]
  467. if len(flag[attack_type].values()) < 1:
  468. continue
  469. out.write(" <h2>%s (%s)</h2>\n" % (attack_type, name))
  470. impacts = flag[attack_type].keys()
  471. impacts.sort(reverse=True)
  472. # order by impact
  473. for i in impacts:
  474. out.write("<div class='match impact-%d'>\n" % int(i))
  475. out.write(" <div class='impact'>Impact %d</div>\n" % int(i))
  476. # list the one of same impacts
  477. for e in flag[attack_type][i]:
  478. out.write(" <div class='block highlight'>\n")
  479. out.write(" Reason: <span class='reason'>%s</span><br />\n" % html_entities(e[2]))
  480. out.write(" <span class='line'><b>Log line:</b>%s</span><br />\n" % html_entities(e[0][5]))
  481. out.write(" <span class='regexp'><b>Matching Regexp:</b>%s</span>\n" % html_entities(e[1]))
  482. out.write(" </div>\n")
  483. out.write("</div>\n")
  484. out.write("<br />\n")
  485. out.write(html_footer)
  486. out.close()
  487. except IOError:
  488. print "Cannot open the file:", fname
  489. return
  490.  
  491. months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
  492.  
  493. def correct_period(date, period):
  494. date = date.replace(':', '/')
  495. l_date = date.split('/')
  496. for i in (2,1,0,3,4,5):
  497. if i != 1:
  498. cur = int(l_date[i])
  499. if cur < period['start'][i] or cur > period['end'][i]:
  500. return False
  501. else:
  502. cur = months.index(l_date[i])
  503. if cur == -1:
  504. return False
  505. if cur < period['start'][i] or cur > period['end'][i]:
  506. return False
  507. return True
  508.  
  509.  
  510. def analyze_date(date):
  511. """04/Apr/2008:15:45;*/May/2008"""
  512.  
  513. d_min = [01, 00, 0000, 00, 00, 00]
  514. d_max = [31, 11, 9999, 24, 59, 59]
  515.  
  516. date = date.replace(':', '/')
  517. l_date = date.split(';')
  518. l_start= l_date[0].split('/')
  519. l_end = l_date[1].split('/')
  520.  
  521. v_start = [01, 00, 0000, 00, 00, 00]
  522. v_end = [31, 11, 9999, 24, 59, 59]
  523.  
  524. for i in range(len(l_start)):
  525. if l_start[i] == '*': continue
  526. else:
  527. if i == 1:
  528. v_start[1] = months.index(l_start[1])
  529. else:
  530. cur = int(l_start[i])
  531. if cur < d_min[i]: v_start[i] = d_min[i]
  532. elif cur > d_max[i]: v_start[i] = d_max[i]
  533. else: v_start[i] = cur
  534. for i in range(len(l_end)):
  535. if l_end[i] == '*': continue
  536. else:
  537. if i == 1:
  538. v_end[1] = months.index(l_end[1])
  539. else:
  540. cur = int(l_end[i])
  541. if cur < d_min[i]: v_end[i] = d_min[i]
  542. elif cur > d_max[i]: v_end[i] = d_max[i]
  543. else: v_end[i] = cur
  544. return {'start' : v_start, 'end' : v_end}
  545.  
  546. def help():
  547. print "Scalp the apache log! by Romain Gaucher - http://rgaucher.info"
  548. print "usage: ./scalp.py [--log|-l log_file] [--filters|-f filter_file] [--period time-frame] [OPTIONS] [--attack a1,a2,..,an]"
  549. print " [--sample|-s 4.2]"
  550. print " --log |-l: the apache log file './access_log' by default"
  551. print " --filters |-f: the filter file './default_filter.xml' by default"
  552. print " --exhaustive|-e: will report all type of attacks detected and not stop"
  553. print " at the first found"
  554. print " --tough |-u: try to decode the potential attack vectors (may increase"
  555. print " the examination time)"
  556. print " --period |-p: the period must be specified in the same format as in"
  557. print " the Apache logs using * as wild-card"
  558. print " ex: 04/Apr/2008:15:45;*/Mai/2008"
  559. print " if not specified at the end, the max or min are taken"
  560. print " --html |-h: generate an HTML output"
  561. print " --xml |-x: generate an XML output"
  562. print " --text |-t: generate a simple text output (default)"
  563. print " --except |-c: generate a file that contains the non examined logs due to the"
  564. print " main regular expression; ill-formed Apache log etc."
  565. print " --attack |-a: specify the list of attacks to look for"
  566. print " list: xss, sqli, csrf, dos, dt, spam, id, ref, lfi"
  567. print " the list of attacks should not contains spaces and comma separated"
  568. print " ex: xss,sqli,lfi,ref"
  569. print " --output |-o: specifying the output directory; by default, scalp will try to write"
  570. print " in the same directory as the log file"
  571. print " --sample |-s: use a random sample of the lines, the number (float in [0,100]) is"
  572. print " the percentage, ex: --sample 0.1 for 1/1000"
  573.  
  574. def main(argc, argv):
  575. filters = "default_filter.xml"
  576. access = "access_log"
  577. output = ""
  578. preferences = {
  579. 'attack_type' : [],
  580. 'period' : {
  581. 'start' : [01, 00, 0000, 00, 00, 00],# day, month, year, hour, minute, second
  582. 'end' : [31, 11, 9999, 24, 59, 59]
  583. },
  584. 'except' : False,
  585. 'exhaustive' : False,
  586. 'encodings' : False,
  587. 'output' : "",
  588. 'odir' : os.path.abspath(os.curdir),
  589. 'sample' : float(100)
  590. }
  591.  
  592. if argc < 2 or sys.argv[1] == "--help":
  593. help()
  594. sys.exit(0)
  595. else:
  596. for i in range(argc):
  597. s = argv[i]
  598. if i < argc:
  599. if s in ("--filters","-f"):
  600. filters = argv[i+1]
  601. elif s in ("--log","-l"):
  602. access = argv[i+1]
  603. elif s in ("--output", "-o"):
  604. preferences['odir'] = argv[i+1]
  605. elif s in ("--sample", "-s"):
  606. try:
  607. preferences['sample'] = float(argv[i+1])
  608. except:
  609. preferences['sample'] = float(4.2)
  610. print "/!\ Error in the sample size, will be 4.2%"
  611. elif s in ("--period", "-p"):
  612. preferences['period'] = analyze_date(argv[i+1])
  613. elif s in ("--exhaustive", "-e"):
  614. preferences['exhaustive'] = True
  615. elif s in ("--html", "-h"):
  616. preferences['output'] += ",html"
  617. elif s in ("--xml", "-x"):
  618. preferences['output'] += ",xml"
  619. elif s in ("--text", "-t"):
  620. preferences['output'] += ",text"
  621. elif s in ("--except", "-c"):
  622. preferences['except'] = True
  623. elif s in ("--tough","-u"):
  624. fill_replace_dict()
  625. preferences['encodings'] = True
  626. elif s in ("--attack", "-a"):
  627. preferences['attack_type'] = argv[i+1].split(',')
  628. else:
  629. print "argument error, '%s' has been ignored" % s
  630. if len(preferences['output']) < 1:
  631. preferences['output'] = "text"
  632. if not os.path.isdir(preferences['odir']):
  633. print "The directory %s doesn't exist, scalp will try to create it"
  634. try:
  635. os.mkdir(preferences['odir'])
  636. except:
  637. print "/!\ scalp cannot write in",preferences['odir']
  638. print "/!\ Ising /tmp/scalp/ as new directory..."
  639. preferences['odir'] = '/tmp/scalp'
  640. os.mkdir(preferences['odir'])
  641. scalper(access, filters, preferences)
  642.  
  643. if __name__ == "__main__":
  644. main(len(sys.argv), sys.argv)
  645. """
  646. import hotshot
  647. from hotshot import stats
  648. name = "hotshot_scalp_stats"
  649. if not os.path.isfile(name):
  650. prof = hotshot.Profile(name)
  651. prof.runcall(main)
  652. prof.close()
  653. s = stats.load(name)
  654. s.sort_stats("time").print_stats()
  655. """
Advertisement
Add Comment
Please, Sign In to add comment