文章目录
- 1. 错误和异常
- 1.1 基本概念
- ==1.1.1 Python 异常==
- 1.2 检测(捕获)异常
- 1.2.1 try except 语句
- 1.2.2 捕获多种异常
- 1.2.3 捕获所有异常
- 1.3 处理异常
- 1.4 特殊场景
- 1.4.1 with 语句
- 2. 内网主机存活检测程序
- 2.1 scapy 模块
- 2.1.1 主要功能
- 2.1.2 scapy 安装
- 2.1.3 进入scapy 模块
- 2.1.4 简单使用
- 2.2 主机存活检测程序
- 3. 面向对象编程
- 3.1 类
- 3.1.1 创建类
- 3.1.2 \__init__ 方法
- 3.2 方法
- 3.2.1 绑定方法
- 3.3 继承
- 3.3.1 子类继承
- 3.3.2 方法重写
- 3.3.3 多重继承
- 3.4 魔法函数
- 3.4.1 类和实例的内建函数
- 3.4.2 常用的魔法函数
- 3.5 私有化
1. 错误和异常
如果遇到了错误(异常),如何去处理?
1.1 基本概念
1.1.1 Python 异常
当程序运行时,因为遇到未知的错误而导致中止运行,便会出现Traceback 消息,打印异常。异常即是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。一般情况下,在Python 无法正常处理程序时就会发生一个异常。异常是Python 对象,表示一个错误。当Python 脚本发生异常时我们需要响应处理它,否则程序会终止执行。可以捕获异常。
异常 | 描述 |
---|---|
SyntaxError | 语法错误 |
NameError | 未声明/初始化对象 |
IndexError | 序列中没有此索引 |
KeyboardInterrupt | 用户中断执行(Ctrl+C) |
EOFError | 没有内建输入,到达EOF 标记(Ctrl+D) 不适用windows 系统 |
IOError | 输入/输出操作失败 |
ValueError | 当操作或函数接收到具有正确类型但值不适合的参数, 并且情况不能用更精确的异常,例如 IndexError来描述时将被引发。 |
TypeError | 字符串与整数相加时触发。 |
1.2 检测(捕获)异常
如果一个语句发生了错误或异常,跳过该语句的执行,执行另外的语句。
1.2.1 try except 语句
监控异常
尝试执行try 语句,如果遇到异常(行不通)则执行except 语句。两个语句执行一个。
语法规则
try:pass # 监控这里的异常
except Exception[, reason]:pass # 异常处理代码
示例:
# 01 - 异常初探.pytry: #尝试执行语句username = input("Please input your name: ")print(f"Welcome, {username}")except: #如果遇到异常执行的语句print("\nSomething Error!")
1.2.2 捕获多种异常
算命脚本:输入年龄,预测明年的年龄。
可以把多个except 语句连接在一起,处理一个try 块中可能发生的多种异常。
# 02 - 捕获多种异常.pybanner = '''
杰哥的算命脚本
1. 预测年龄
2. 预测财运
3. 预测姻缘
'''print(banner)choice = input("Please input the number: ")
choice = int(choice)def guess_age():try:age = input("Please input your age: ")print(f"The next year your name: {int(age) + 1}")except ValueError:print("\nPlease input a number!")except KeyboardInterrupt:print("\nCtrl + C.END")except:print("\nSomething Error!")
if choice != 1:print("好好学习...")exit()
eles:guess_age()
1.2.3 捕获所有异常
如果出现的异常没有出现在指定要捕获的异常列表中,程序仍然会中断。可以使用在异常继承的树结构中,BaseException 是在最顶层的,所以使用它可以捕获任意类型的异常。
except BaseException: # 捕获所有异常,相当于exceptprint("\nSomething Error!")
Pyhton 异常树
BaseException 所有异常的基类||+-- SystemExit 解释器请求退出||+-- KeyboardInterrupt 用户中断执行(通常是输入^C)||+-- GeneratorExit 生成器调用close();方法时触发的||+-- Exception 常规错误的基类,异常都是从基类Exception继承的。|+-- StopIteration 迭代器没有更多的值|+-- StandardError 所有的内建标准异常的基类| +-- BufferError 缓冲区操作不能执行| +-- ArithmeticError 所有数值计算错误的基类| | +-- FloatingPointError 浮点计算错误| | +-- OverflowError 数值运算超出最大限制| | +-- ZeroDivisionError 除(或取模)零 (所有数据类型)| +-- AssertionError 断言语句失败| +-- AttributeError 访问未知对象属性| +-- EnvironmentError 操作系统错误的基类| | +-- IOError 输入输出错误| | +-- OSError 操作系统错误| | +-- WindowsError (Windows) 系统调用失败| | +-- VMSError (VMS) 系统调用失败| +-- EOFError 没有内建输入,到达EOF 标记| +-- ImportError 导入模块/对象失败| +-- LookupError 无效数据查询的基类,键、值不存在引发的异常| | +-- IndexError 索引超出范围| | +-- KeyError 字典关键字不存在| +-- MemoryError 内存溢出错误(对于Python 解释器不是致命的)| +-- NameError 未声明/初始化对象 (没有属性)| | +-- UnboundLocalError 访问未初始化的本地变量| +-- ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象| +-- RuntimeError 一般的运行时错误| | +-- NotImplementedError 尚未实现的方法| +-- SyntaxError 语法错误| | +-- IndentationError 缩进错误| | +-- TabError Tab 和空格混用| +-- SystemError 一般的解释器系统错误| +-- TypeError 对类型无效的操作| +-- ValueError 传入无效的参数| +-- UnicodeError Unicode 相关的错误| +-- UnicodeDecodeError Unicode 解码时的错误| +-- UnicodeEncodeError Unicode 编码时错误| +-- UnicodeTranslateError Unicode 转换时错误|+-- Warning 警告的基类+-- DeprecationWarning 关于被弃用的特征的警告+-- PendingDeprecationWarning 关于特性将会被废弃的警告+-- RuntimeWarning 可疑的运行时行为(runtime behavior)的警告+-- SyntaxWarning 可疑的语法的警告+-- UserWarning 用户代码生成的警告+-- FutureWarning 关于构造将来语义会有改变的警告+-- ImportWarning 关于模块进口可能出现错误的警告的基类。+-- UnicodeWarning 有关Unicode警告的基类。+-- BytesWarning 有关字节警告相关的基类。
1.3 处理异常
try: # 尝试执行某个语句num = int(input("The number:"))
except BaseException: # 如果遇到异常,执行的语句print("something error!")
else: # 如果没有遇到异常,执行的语句print(num)
finally: # 不管是否遇到异常,都要执行的语句。print("This is finally")
-
else 子句:在try 范围中没有异常被检测到时,执行else 子句。在else 范围中的任何代码运行前,try 范围中的所有代码必须完全成功。
-
finally 子句:finally 子句是无论异常是否发生,是否捕捉都会执行的一段代码。比如获取用户的输入,写入文件,但是如果在获取数据过程中,发生了异常,就会导致整个脚本结束执行,文件也无法关闭了。为了解决这个问题,可以采用异常处理中的finally 子句,也就是说,无论语句是否正常执行,都需要关闭。
# 03 - 处理异常.pybanner = '''
杰哥的算命脚本
1. 预测年龄
2. 预测财运
3. 预测姻缘
'''print(banner)choice = input("Please input the number: ")
choice = int(choice)def guess_age():try:age = input("Please input your age: ")age = int(age) except ValueError:print("\nPlease input a number!")except KeyboardInterrupt:print("\nCtrl + C")except:print("\nSomething Error!")else:print(f"The next year your name: {age + 1}")finally:print("杰哥算命脚本执行结束,祝你好运!")
if choice != 1:print("好好学习...")exit()
else:guess_age()
1.4 特殊场景
1.4.1 with 语句
with 语句是用来简化代码的。比如在将打开文件的操作放在with 语句中,代码块结束后,文件将自动关闭。用来简化文件操作的打开和关闭,其中closed 属性是判断文件是否被关闭的
>>> with open('foo.py') as f:
2. 内网主机存活检测程序
网络模型:
应用层
表示层
会话层 应用层 应用层 http|ftp|dns|dhcp
传输层 传输层 传输层 tcp|udp
网络层 网络层 网络层 ip
数据链路层 数据链路层
物理层 物理层 网络接口层
2.1 scapy 模块
与scrapy 有非常大的区别。
scapy 是一个Python 的第三方模块,被称为“网络神器”。scapy 模块能够发送、捕获、分析和铸造网络数据包。
2.1.1 主要功能
2.1.2 scapy 安装
Windows 下安装scapy
python -m pip install scapy
依赖
Kali 中自带scapy 环境。
2.1.3 进入scapy 模块
┌──(ajest zh-CN)-[~]
└─$ sudo scapy aSPY//YASa apyyyyCY//////////YCa |sY//////YSpcs scpCY//Pp | Welcome to Scapyayp ayyyyyyySCP//Pp syY//C | Version 2.4.5AYAsAYYYYYYYY///Ps cY//S |pCCCCY//p cSSps y//Y | https://github.com/secdev/scapySPPPP///a pP///AC//Y |A//A cyP////C | Have fun!p///Ac sC///a |P////YCpc A//A | Craft packets before they craftscccccp///pSP///p p//Y | you.sY/////////y caa S//P | -- SocratecayCyayP//Ya pY/Ya |sY/PsY////YCc aC//Yp sc sccaCY//PCypaapyCP//YSs spCPY//////YPSps ccaacs using IPython 7.22.0
>>>
2.1.4 简单使用
构造数据包
>>> pkt = IP()/TCP()
>>> pkt.show()
###[ IP ]### version = 4ihl = Nonetos = 0x0len = Noneid = 1flags = frag = 0ttl = 64proto = tcpchksum = Nonesrc = 127.0.0.1dst = 127.0.0.1\options \
###[ TCP ]### sport = ftp_datadport = httpseq = 0ack = 0dataofs = Nonereserved = 0flags = Swindow = 8192chksum = Noneurgptr = 0options = ''>>> pkt = IP(src = "192.168.1.11", dst = "192.168.1.1")/TCP() #src:发送方dst:接收方
>>> pkt.show()
###[ IP ]### version = 4ihl = Nonetos = 0x0len = Noneid = 1flags = frag = 0ttl = 64proto = tcpchksum = Nonesrc = 192.168.1.11dst = 192.168.1.1\options \
###[ TCP ]### sport = ftp_datadport = httpseq = 0ack = 0dataofs = Nonereserved = 0flags = Swindow = 8192chksum = Noneurgptr = 0options = ''>>>
发送数据包
发送数据包的函数 | 说明 |
---|---|
sr(pkt) | 发送数据包,接收所有返回包 |
sr1(pkt) | 发送数据包,接收(等待)一个返回包 |
send(pkt) | 发送数据包,不等待返回包 |
srp(pkt) | 发送2 层数据包,等待回应 |
sendp(pkt) | 发送2 层数据包,不等待返回包 |
>>> res = sr1(pkt)
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>>
在发送数据包的时候,再接收返回包,网卡一直处于监听状态,接收监听的数据包,一直等待回应。直到接收到返回包。接到返回包,主机在线,接不到返回包,主机不在线。
查看返回包
>>> res.show()
###[ IP ]### version = 4ihl = 5tos = 0x0len = 44id = 13990flags = frag = 0ttl = 255proto = tcpchksum = 0x46a4src = 10.9.21.1dst = 10.9.21.111\options \
###[ TCP ]### sport = httpdport = ftp_dataseq = 1510518667ack = 1dataofs = 6reserved = 0flags = SAwindow = 65535chksum = 0x4f9curgptr = 0options = [('MSS', 1460)]
###[ Padding ]### load = '\x00\x00'>>>
2.2 主机存活检测程序
icmp的回应包:0
# 04 - 内网主机存活检测程序.pyfrom scapy.all import *
from scapy.layers.inet import *
from termcolor import coloredimport logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #屏蔽信息的模块,scapy运行期间,只有ERROR才显示即其他的都不显示。netmask = "192.168.16." #接收端的网络位
src = "192.168.16.177" #发送端for i in range(1, 255):dst = f"{netmask}{i}" #接收端pkt = IP(src = src, dst = dst)/ICMP() #创建数据包res = sr1(pkt, timeout = 1, verbose = False) #发送数据包等待回应,等待一秒,一秒后没有回应当作不在线,禁止详细输出if res and res.type == 0:print(colored(f"\n{dst} is ALIVE!","green"))else: print(f"\r{dst} is NOT LIVE!!!",end = "") #输出目的主机不存活,end=""使结果原地输出
3. 面向对象编程
编写POC平台:
goby,nuclei yaml语言pocsuite3 高仿msfpy语言yakityak语言
3.1 类
类是一类事物的统称,比如学生。对象就是类的实例化。
类有属性(变量),比如学生的姓名、性别、年龄、成绩等,也就是编程里面的变量。
类有方法(函数),比如学生的上课、下课等,也就是编程里面的函数。
3.1.1 创建类
类是一种数据结构,我们可以用它来定义对象,对象把数据值和行为特性融合在一起。Python 使用class
关键字来创建类:通常类名的第一个字母大写,推荐使用驼峰式命名法,单词首字母均大写。类有属性(变量)和方法(动作,函数)组成。
class ClassName(bases):'class documentation string' #'类文档字符串'class_suite # 类体
3.1.2 _init_ 方法
__init__()
是类的实例(对象)创建后第一个被调用的方法,通常被用来进行对象中属性(变量)的初始化。设置实例的属性可以在实例创建后任意时间进行,但是通常情况下优先在__init__()
方法中实现。
- 定义类型
- 实例化对象(创建一个对象)
- 初始化对象(第一次给对象属性赋值)
# 05 - __init__.pyclass Stu():#self:是一个特殊的参数,他对类的实例(对象)本身。在类的方法中,只用self参数可以访问该对象的属性和方法def __init__(self, name, sex, age, score):self.name = nameself.sex = sexself.age = ageself.score = scorestu1 = Stu(name = "XJ", sex = True, age = 24, score = 59.9) #在传参的时候,stu1传给类中的self,name传给类中的name...在类中相当于:stu1.name = "XJ",stu1.sex = True,stu1.age = 24...print(f"{stu1.name} 的成绩是{stu1.score}")
3.2 方法
3.2.1 绑定方法
方法仅仅是类内部定义的函数,方法只有在其所属的类拥有实例时,才能被调用;任何一个方法定义中的第一个参数都是变量self,它表示调用此方法的实例对象就是自己。
类中的方法,也就是类中定义的函数,这个函数第一个参数永远是self,表示自己。
# 06 - 绑定方法.pyimport timeclass Stu():def __init__(self, name, sex, age, score):self.name = nameself.sex = sexself.age = ageself.score = scoredef getSocre(self):print(f"{self.name} 的成绩是{self.score}")def goodGoodStudy(self):print("好好学习中...")time.sleep(10)self.score += 0.1stu1 = Stu(name = "LH", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "HMM", sex = True, age = 24, score = 89.9)stu2.getSocre()
stu2.goodGoodStudy()
stu2.getSocre()
3.3 继承
3.3.1 子类继承
继承描述了基类(祖先)的属性如何遗传给派生类(子孙),子类可以继承它的基类的任何属性,不管是数据属性还是方法。
# 34 - 子类继承.pyimport timeclass Kid():def __init__(self, name = "", sex = "", age = ""):self.name = nameself.age = ageself.sex = sexdef play(self):print("玩游戏中...")class Stu(Kid):def __init__(self,name = "", sex = "", age = "", score = ""):Kid.__init__(self, name, sex, age)self.score = scoredef get_score(self):print(f"{self.name} 的成绩是{self.score}")def good_good_study(self):print("好好学习中...")time.sleep(10)self.score += 0.1stu1 = Stu(name = "XJ", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "LL", sex = True, age = 25, score = 49.9)
stu3 = Stu(name = "HMM", sex = True, age = 23, score = 99.9)
stu4 = Stu(name = "LH", sex = True, age = 24, score = 79.9)stu1.play()
3.3.2 方法重写
如果子类中有和父类同名的方法,父类方法将被覆盖;如果需要访问父类的方法,则要调用一个未绑定的父类方法,明确给出子类的实例。
# 08 - 方法重写.pyimport timeclass Kid():def __init__(self, name, sex, age):self.name = nameself.sex = sexself.age = agedef play(self):print("玩游戏中...")class Stu(Kid):def __init__(self, name, sex, age, score):Kid.__init__(self, name, sex, age)self.score = score #Stu类继承了Kid类。在它的构造函数中,除了接受与Kid相同的三个参数外,还接受一个额外的参数score(分数)。Kid.__init__(self, name, sex, age)用于调用父类Kid的构造函数,以便初始化父类的属性。同时,Stu类还定义了一个自己的属性score,并将score的参数值赋给它。def getSocre(self):print(f"{self.name} 的成绩是{self.score}")def goodGoodStudy(self):print("好好学习中...")time.sleep(10)self.score += 0.1def play(self):print("玩王者荣耀中...")time.sleep(2)self.score -= 10stu1 = Stu(name = "AJEST", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "HMM", sex = True, age = 24, score = 89.9)stu2.getSocre()
stu2.play()
stu2.getSocre()
stu2.goodGoodStudy()
stu2.goodGoodStudy()
stu2.getSocre()
stu2.play()
stu2.getSocre()
3.3.3 多重继承
Python 允许多重继承,即一个类可以是多个父类的子类,子类可以拥有所有父类的属性。
# 09 - 多重继承.pyclass A():def a(self):print("This is function A!")class B():def b(self):print("This is function B!")class C(A, B):pass
C = C()
C.a()
C.b()
解释:
-
在Python中,pass 是一个空语句,不执行任何操作。当你在代码中遇到需要写一段代码但又暂时没有实现的情况时,可以使用 pass 来占位,使得代码结构完整而没有语法错误。
-
多重继承是指一个类可以继承自多个父类的特性和方法。在Python中,多重继承可以通过在类定义时指定多个父类来实现。
当一个类继承自多个类时,它继承了这些父类的属性和方法。这意味着子类可以使用来自所有父类的特性,并且可以在自己的定义中添加新的属性和方法。
下面是一个简单的示例,演示了多重继承的概念:
class A:def method_a(self):print("这是A类的方法")class B:def method_b(self):print("这是B类的方法")class C(A, B):def method_c(self):print("这是C类的方法")# 创建C类的对象 obj = C()# 调用来自父类A和B的方法 obj.method_a() # 输出:这是A类的方法 obj.method_b() # 输出:这是B类的方法# 调用自己的方法 obj.method_c() # 输出:这是C类的方法
在上面的代码中,类A和B分别定义了method_a和method_b两个方法。类C继承自A和B,因此它拥有这两个父类的方法。然后,通过创建C类的对象obj,我们可以调用来自父类A和B的方法,也可以调用C类自己的方法method_c。
需要注意的是,当一个类继承自多个父类时,如果不同父类中存在同名的方法或属性,Python解释器将按照特定的顺序(称为方法解析顺序)来查找和调用。方法解析顺序由C3线性化算法确定,它确保解析顺序是一种合理且一致的方式。在Python中,可以使用c3_linearize()函数来查看类的方法解析顺序。
多重继承的使用必须慎重,因为它可以引起一些复杂的问题,例如方法冲突和命名空间冲突。因此,在使用多重继承时,需要仔细考虑类与类之间的关系,以及方法和属性的命名以避免冲突。
3.4 魔法函数
3.4.1 类和实例的内建函数
函数 | 作用 |
---|---|
issubclass() | 判断一个类是另一个类的子类或子孙类 |
isinstance() | 判定一个对象是否是另一个给定类(可以是一个父类的子孙类,也可以是一个子类的父类)的实例 |
hasattr() | 判断一个对象是否有一个特定的属性 |
getattr() | 获得一个对象的属性值 |
setattr() | 设置一个对象的属性 |
delattr() | 删除一个对象的属性 |
3.4.2 常用的魔法函数
魔法函数是系统自带的,会在“恰当”的时候自动调用。
# 10 - 魔术方法.pyclass Test():def __init__(self):print("Function __init__ is called!")def __str__(self):return "Why print(self)?"def __call__(self):print("Why call me like Function?")t = Test()print(t)t()
解释:
在Python中,魔法函数(Magic methods)是一类特殊的函数,以双下划线(__)开头和结尾的方法。它们也被称为特殊方法或双下方法。
魔法函数在Python中用于定义自定义类的行为,使其具有类似内置类型的行为。当某些特定的操作发生时(例如实例创建、对象调用、属性访问等),魔法函数会被自动调用。
下面是一些常见的魔法函数的详细解释和示例:
-
__init__
: 这是一个构造函数,用于创建对象实例。它在对象被创建时自动调用,常用于初始化对象的属性。class Person:def __init__(self, name, age):self.name = nameself.age = ageperson = Person("John", 30) print(person.name) # 输出: John print(person.age) # 输出: 30
-
__str__
和__repr__
:__str__
用于定义对象的字符串表示形式,对于用户的友好输出有很大作用;而__repr__
则用于定义对象的技术细节表示形式,主要用于调试和开发。class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"Person(name={self.name}, age={self.age})"def __repr__(self):return f"Person(name='{self.name}', age={self.age})"person = Person("John", 30) print(str(person)) # 输出: Person(name=John, age=30) print(repr(person)) # 输出: Person(name='John', age=30)
-
__len__
: 该方法定义了对象的长度。使用内建函数len()
调用对象时,实际上是调用了对象的__len__
方法。class MyList:def __init__(self, elements):self.elements = elementsdef __len__(self):return len(self.elements)my_list = MyList([1, 2, 3, 4, 5]) print(len(my_list)) # 输出: 5
-
__getitem__
和__setitem__
: 这些方法定义了对象的索引操作行为。可以通过方括号 [] 访问对象中的元素,而实际上是调用了对应的魔法函数。class MyList:def __init__(self, elements):self.elements = elementsdef __getitem__(self, index):return self.elements[index]def __setitem__(self, index, value):self.elements[index] = valuemy_list = MyList([1, 2, 3, 4, 5]) print(my_list[2]) # 输出: 3 my_list[2] = 10 print(my_list[2]) # 输出: 10
-
__call__
: 使得对象可以像函数一样被调用。在对象后面加括号时,会自动调用该对象的__call__
方法。class Calculator:def __call__(self, a, b):return a + bcalculator = Calculator() result = calculator(3, 5) print(result) # 输出: 8
还有很多其他的魔法函数,例如 __add__
(用于定义对象相加操作)、__sub__
(用于定义对象相减操作)、__eq__
(用于定义对象相等比较操作)等等。通过定义这些魔法函数,可以使得自定义类的实例表现得更加像内置类型,提供更多的灵活性和可定制性。
3.5 私有化
Python 为类元素(属性和方法)的私有性提供初步的形式,由双下划线开始的属性在运行时被“混淆”,所以直接访问是不允许的。
# 11 - 私有化.py# 06 - 绑定方法.pyimport timeclass Stu():def __init__(self, name, sex, age, score):self.name = nameself.sex = sexself.age = ageself.__score = scoredef getSocre(self):print(f"{self.name} 的成绩是{self.__score}") #允许访问成绩def goodGoodStudy(self):print("好好学习中...")time.sleep(10)self.__score += 0.1stu1 = Stu(name = "AJEST", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "HMM", sex = True, age = 24, score = 89.9)stu2.getSocre()
ator()result = calculator(3, 5)print(result) # 输出: 8
还有很多其他的魔法函数,例如 __add__
(用于定义对象相加操作)、__sub__
(用于定义对象相减操作)、__eq__
(用于定义对象相等比较操作)等等。通过定义这些魔法函数,可以使得自定义类的实例表现得更加像内置类型,提供更多的灵活性和可定制性。