-- class1.py --
# 1. 클래스 정의
class Student:
age = 100
def sayHello():
print('Hello')
def printName():
print('홍길동')
# 2. 클래스 사용
Student.sayHello() # Hello
Student.printName() # 홍길동
print(Student.age) # 100
-- class1.py --
-- class2.py --
# 1. 클래스 정의
class Student:
age = 25
def printAge(self):
print(f'나이: {self.age}')
# 2. 객체(인스턴스) 생성
s1 = Student()
# 3. 객체(인스턴스) 사용
s1.printAge()
-- class2.py --
-- class3.py --
# 1. 클래스 정의
class Student:
age = 25
def printAge(self):
print(f'나이: {self.age}')
print(id(self)) # 주소 출력
# 2. 객체(인스턴스) 생성
s1 = Student()
# 3. 객체(인스턴스) 사용
s1.printAge()
print(id(s1)) # 주소 출력
print('프로그램 종료')
-- class3.py --
-- class4.py --
# 1. 클래스 정의
class Student:
def setAge(self, age):
self.age = age # 인스턴스에 저장
def printAge(self):
print(f'나이: {self.age}') # 인스턴스에 저장된 값 출력
# 2. 객체(인스턴스) 생성
s1 = Student()
s2 = Student()
# 3. 객체(인스턴스) 사용
s1.setAge(10)
s1.printAge() # 10
s2.setAge(20)
s2.printAge() # 20
print('프로그램 종료')
-- class4.py --
-- class5.py --
# 1. 클래스 정의
class Student:
def __init__(self):
print("생성자 실행!!!")
# 2. 객체(인스턴스) 생성
s1 = Student()
print('프로그램 종료')
-- class5.py --
-- class6.py --
# 1. 클래스 정의
class Student:
def __init__(self,age):
self.age = age
print("생성자 실행!!!")
def printAge(self):
print(f'나이: {self.age}') # 인스턴스에 저장된 값 출력
# 2. 객체(인스턴스) 생성
s1 = Student(10)
# 3. 객체(인스턴스) 실행
s1.printAge()
print('프로그램 종료')
-- class6.py --
실습> TV 만들기
TV를 객체로 만들어서 사용한다.
파일명 : tvclass.py
클래스명 : MyTV
속성(변수) :
- 모델명 : modelName
- 색상 : modelColor
- 채널 : channel (1 ~ 100)
- 볼륨 : volume (1 ~ 30)
- 전원상태 : True(On), False(Off)
메소드(함수) :
- TV On/Off 한다. : tvOnOff
- 채널을 UP 시킨다. : channelUp
- 채널을 DOWN 시킨다. : channelDown
- 채널을 직접 변경한다. : channelChange
- 볼륨을 UP 시킨다. : volumeUp
- 볼륨을 DOWN 시킨다. : volumeDown
- 현재 볼륨을 가져온다. : getVolume
- 현재 채널을 가져온다. : getChannel
-- tvclass.py --
"""
파일명 : tvclass.py
프로그램 설명 : TV 클래스 만들기
제작자 : 리눅스마스터
버전 : 2023031501
클래스명 : MyTV
속성(인스턴스 변수) :
- 모델명 : modelName
- 색상 : modelColor
- 채널 : channel (1 ~ 100)
- 볼륨 : volume (1 ~ 30)
- 전원상태 : onOff
메소드(함수) :
- TV On/Off 한다. : tvOnOff
- 채널을 UP 시킨다. : channelUp
- 채널을 DOWN 시킨다. : channelDown
- 채널을 직접 변경한다. : channelChange
- 볼륨을 UP 시킨다. : volumeUp
- 볼륨을 DOWN 시킨다. : volumeDown
- 현재 볼륨을 가져온다. : getVolume
- 현재 채널을 가져온다. : getChannel
"""
import os
# 1. 클래스 정의
class MyTV:
"""MyTV 클래스"""
def __init__(self):
"""생성자"""
# 인스턴스 변수를 생성한다.
self.modelName = "MyTV" # 모델명
self.modelColor = "Green" # 색상
self.channel = 1 # 채널 1 ~ 100
self.volume = 1 # 볼륨 1 ~ 30
self.onOff = False # On/Off 상태 True : On, False : Off
self.tvOffMessage = 'TV의 전원이 꺼졌습니다.'
self.tvOnMessage = 'TV의 전원이 켜졌습니다.'
# TV 전원 On/Off 메소드
def tvOnOff(self):
"""
TV On/Off 한다.
매개 변수 : X
리턴값 : X
"""
# print('tvOnOff() 메소드 실행')
self.onOff = not self.onOff # 전원 상태를 변경한다.
if self.onOff: # 전원 On
print(self.tvOnMessage)
else: # 전원 Off
print(self.tvOffMessage)
# 채널 UP 메소드
def channelUp(self):
"""
채널을 UP 시킨다.
매개 변수 : X
리턴값 : X
"""
#print('channelUp() 메소드 실행')
# TV의 전원이 켜졌는지 체크하는 부분
if self.onOff: # TV의 전원이 켜졌는가 ?
if self.channel == 100 : # 채널이 100이면
self.channel = 1 # 채널을 1로 설정한다.
print(f'채널을 1로 설정합니다. ({self.channel})')
else:
self.channel += 1 # 채널을 증가한다.
print(f'채널을 1증가했습니다. ({self.channel})')
else:
print(self.tvOffMessage)
# 채널 DOWN 메소드
def channelDown(self):
"""
채널을 DOWN 시킨다.
매개 변수 : X
리턴값 : X
"""
# print('channelDown() 메소드 실행')
# TV의 전원이 켜졌는지 체크하는 부분
if self.onOff: # TV의 전원이 켜졌는가 ?
if self.channel == 1 : # 채널이 1이면
self.channel = 100 # 채널을 100으로 설정한다.
print(f'채널을 100로 설정합니다. ({self.channel})')
else:
self.channel -= 1 # 채널을 감소한다.
print(f'채널을 1감소했습니다. ({self.channel})')
else:
print(self.tvOffMessage)
# 채널 직접 변경 메소드
def channelChange(self, channel):
"""
채널을 직접 변경한다.
매개 변수 : O
- channel : 변경할 채널 번호
리턴값 : X
"""
# print('channelChange() 메소드 실행')
if self.onOff: # TV의 전원이 켜졌는가 ?
if channel >= 1 and channel <= 100: # 채널범위 1 ~ 100
self.channel = channel
print(f'채널을 직접 설정했습니다. ({self.channel})')
else:
print('채널은 1 ~ 100까지 입력해야 합니다.')
else:
print(self.tvOffMessage)
# 볼륨 UP 메소드
def volumeUp(self):
"""
볼륨을 UP 시킨다.
매개 변수 : X
리턴값 : X
볼륨의 범위 : 1 ~ 30
30까지 갔는데 volumeUp() 메소드를 호출하면 더이상 올라가지 않고
현재 최대 볼륨입니다. 라는 메세지를 출력한다.
"""
# print('volumeUp() 메소드 실행')
if self.onOff: # TV의 전원이 켜졌는가 ?
if self.volume == 30: # 볼륨이 30이면
print(f'현재 최대 볼륨입니다. ({self.volume})')
else: # 볼륨이 30보다 작으면
self.volume += 1
print(f'볼륨을 1증가했습니다. ({self.volume})')
else:
print(self.tvOffMessage)
# 볼륨 DOWN 메소드
def volumeDown(self):
"""
볼륨을 DOWN 시킨다.
매개 변수 : X
리턴값 : X
볼륨의 범위 : 1 ~ 30
1까지 갔는데 volumeDown() 메소드를 호출하면 더이상 내려가지 않고
현재 최소 볼륨입니다. 라는 메세지를 출력한다.
"""
# TV의 전원이 켜졌는지 ???
if self.onOff:
if self.volume == 1: # 볼륨이 1이면
print(f'현재 최소 볼륨입니다. ({self.volume})')
else: # 볼륨이 1보다 크면
self.volume -= 1
print(f'볼륨을 1감소했습니다. ({self.volume})')
else:
print(self.tvOffMessage)
# 채널을 가져오는 메소드
def getChannel(self):
"""
현재 채널을 가져온다.
매개 변수 : X
리턴값 : X
"""
# print('getChannel() 메소드 실행')
if self.onOff: # TV의 전원이 켜졌는가 ?
print(f'현재 채널 : {self.channel}')
else:
print(self.tvOffMessage)
# 볼륨을 가져오는 메소드
def getVolume(self):
"""
현재 볼륨을 가져온다.
매개 변수 : X
리턴값 : X
"""
# print('getVolume() 메소드 실행')
if self.onOff: # TV의 전원이 켜졌는가 ?
print(f'현재 볼륨 : {self.volume}')
else:
print(self.tvOffMessage)
# TV 메뉴 메소드
def tvmenu(self):
"""
TV 프로그램 메뉴
매개 변수 : X
리턴값 : O
- menu : 메뉴가 저장된 문자열
"""
menu = f'>>> TV 프로그램 ({self.modelName}) <<<\n'
menu += f'전원: { "On" if self.onOff == True else "Off" } '
menu += f'채널: {self.channel} '
menu += f'볼륨: {self.volume}\n'
menu += '1. TV On/Off\n'
menu += '2. 채널 증가 ▲\n'
menu += '3. 채널 감소 ▼\n'
menu += '4. 채널 직접 변경\n'
menu += '5. 볼륨 증가 △\n'
menu += '6. 볼륨 감소 ▽\n'
menu += '7. 현재 볼륨 확인 ★\n'
menu += '8. 현재 채널 확인 ☆\n'
menu += '9. 프로그램 정보\n'
menu += 'q. 프로그램 종료\n'
return menu
# 프로그램 정보
def tvAbout(self):
"""프로그램 정보"""
print(">>> TV 프로그램 정보 <<<")
aboutMsg = "TV 프로그램\n"
aboutMsg += "버전 : 0.1\n"
aboutMsg += "프로그램 제작 : 홍길동(hong@naver.com)\n"
print(aboutMsg)
# main 함수
def main(self):
"""main"""
while True:
os.system('cls') # 화면 지우기
print(self.tvmenu()) # 메뉴 출력
x = input('선택 >>> ') # 메뉴 입력
# 메뉴 체크
if x == '1' : # TV On/Off
self.tvOnOff()
elif x == '2' : # 채널 증가
self.channelUp()
elif x == '3' : # 채널 감소
self.channelDown()
elif x == '4' : # 채널 직접 변경
channel = input('변경할 채널 : ')
channel = int(channel) if channel.isdigit() else ''
if channel :
if channel >= 1 and channel <= 100:
self.channelChange(channel)
else:
print('채널 번호는 1 ~ 100까지 입니다.')
else:
print('채널 번호를 잘못 입력했습니다.')
elif x == '5' : # 볼륨 증가
self.volumeUp()
elif x == '6' : # 볼륨 감소
self.volumeDown()
elif x == '7' : # 현재 볼륨 확인
self.getVolume()
elif x == '8' : # 현재 채널 확인
self.getChannel()
elif x == '9' : # 프로그램 정보
self.tvAbout()
elif x == 'q' : # 프로그램 종료
print("MyTV 프로그램을 종료합니다...")
break
else: # 그외의 모든 값
print('1 ~ 9 or q중에서 입력해야 합니다.')
input()
# 2. 객체(인스턴스) 생성
mytv = MyTV()
# 3. 객체(인스턴스) 실행
mytv.main()
-- tvclass.py --
실습> 함수형 프로그램을 클래스 형태로 변환하기
파일명: 점수관리프로그램.py
클래스명 : Jumsu
인스턴스명 : jumsu
1. class Jumsu 를 생성한다.
2. 모든 함수들을 Jumsu class 안에 넣는다.
3. 모든 메소드(함수) 정의 부분에 self를 추가한다.
4. 각 메소드(함수)에서 변수를 참조하거나 메소드(함수)호출 앞에 self 를 붙인다.
5. 인스턴스 jumsu를 생성한다.
6. jumsu 인스턴스 안에 있는 main() 메소드를 실행한다.
-- 점수관리프로그램.py --
"""
파일명 : 점수관리프로그램.py
프로그램 설명 : 점수 관리 프로그램
작성자 : 리눅스마스터
작성일 : 2023.3.15
"""
import os
def jumsuAdd():
"""점수 추가"""
global kor, eng, math, total, average
# 1. 점수 입력
print("점수를 입력하세요.")
kor = input("국어 점수 : ")
eng = input("영어 점수 : ")
math = input("수학 점수 : ")
# 2. 점수 체크
kor = int(kor) # if kor.isdigit() else 0
eng = int(eng) # if eng.isdigit() else 0
math = int(math) # if math.isdigit() else 0
# 3. 점수 계산
total = kor + eng + math # 총점
#total = sum([kor, eng, math]) # 총점
average = total / 3 # 평균
# 4. 점수 출력
print("\n===== 점수의 결과 =====\n"
f"국어 점수 : {kor}\n"
f"영어 점수 : {eng}\n"
f"수학 점수 : {math}\n"
f"총점 : {total}\n"
f"평균 : {average:.2f}\n"
"===== 점수의 결과 =====")
print('엔터키를 누르세요...')
input()
def jumsuView():
"""점수 확인"""
# 점수 출력
print("\n===== 점수의 결과 =====\n"
f"국어 점수 : {kor}\n"
f"영어 점수 : {eng}\n"
f"수학 점수 : {math}\n"
f"총점 : {total}\n"
f"평균 : {average:.2f}\n"
"===== 점수의 결과 =====")
print('엔터키를 누르세요...')
input()
def jumsuMenu():
"""메뉴"""
menu = '>>> 점수 관리 프로그램 <<<\n'
menu += '1. 점수 추가\n'
menu += '2. 점수 확인\n'
menu += 'q. 프로그램 종료'
print(menu)
def main():
"""main 함수"""
while True:
os.system('cls') # 화면 지우기
jumsuMenu()
x = input('선택 >>> ') # 메뉴 입력
# 메뉴 체크
if x == '1' :
jumsuAdd()
elif x == '2' :
jumsuView()
elif x == 'q' :
break
else:
print('1, 2, q 중에서 입력하세요.')
main()
print('점수 관리 프로그램을 종료합니다.')
-- 점수관리프로그램.py --
-- 점수관리프로그램.py --
"""
파일명 : 점수관리프로그램.py
프로그램 설명 : 점수 관리 프로그램
작성자 : 리눅스마스터
작성일 : 2023.3.15
"""
import os
class Jumsu:
def jumsuAdd(self):
"""점수 추가"""
# 1. 점수 입력
print("점수를 입력하세요.")
self.kor = input("국어 점수 : ")
self.eng = input("영어 점수 : ")
self.math = input("수학 점수 : ")
# 2. 점수 체크
self.kor = int(self.kor) # if self.kor.isdigit() else 0
self.eng = int(self.eng) # if self.eng.isdigit() else 0
self.math = int(self.math) # if self.math.isdigit() else 0
# 3. 점수 계산
self.total = self.kor + self.eng + self.math # 총점
#self.total = sum([self.kor, self.eng, self.math]) # 총점
self.average = self.total / 3 # 평균
# 4. 점수 출력
print("\n===== 점수의 결과 =====\n"
f"국어 점수 : {self.kor}\n"
f"영어 점수 : {self.eng}\n"
f"수학 점수 : {self.math}\n"
f"총점 : {self.total}\n"
f"평균 : {self.average:.2f}\n"
"===== 점수의 결과 =====")
print('엔터키를 누르세요...')
input()
def jumsuView(self):
"""점수 확인"""
# 점수 출력
print("\n===== 점수의 결과 =====\n"
f"국어 점수 : {self.kor}\n"
f"영어 점수 : {self.eng}\n"
f"수학 점수 : {self.math}\n"
f"총점 : {self.total}\n"
f"평균 : {self.average:.2f}\n"
"===== 점수의 결과 =====")
print('엔터키를 누르세요...')
input()
def jumsuMenu(self):
"""메뉴"""
menu = '>>> 점수 관리 프로그램 <<<\n'
menu += '1. 점수 추가\n'
menu += '2. 점수 확인\n'
menu += 'q. 프로그램 종료'
print(menu)
def main(self):
"""main 함수"""
while True:
os.system('cls') # 화면 지우기
self.jumsuMenu()
x = input('선택 >>> ') # 메뉴 입력
# 메뉴 체크
if x == '1' :
self.jumsuAdd()
elif x == '2' :
self.jumsuView()
elif x == 'q' :
break
else:
print('1, 2, q 중에서 입력하세요.')
jumsu = Jumsu()
jumsu.main()
print('점수 관리 프로그램을 종료합니다.')
-- 점수관리프로그램.py --
패킷 조작 툴: scapy
패킷 구조를 공부할 수 있는 장점이 있다.
https://scapy.readthedocs.io/en/latest/
실습> 윈도우에서 scapy 설치하기
가상환경으로 사용한다.
가상환경 :
파이썬을 가상으로 환경을 프로젝트별로 구축해서 사용하는 환경이다.
실무에서 많이 사용하는 것이므로 잘 알아두어야 한다.
가상환경을 이용해서 프로젝트를 생성하는 방법
- bash, CMD/PS(Power Shell) 에서 생성하는 방법
- VScode, Pycharm에서 생성하는 방법
가상환경을 사용하지 않은 환경
Python 3.x
+-----+
| |
| |
+-----+
가상환경을 사용한 환경
Python 3.x 복제된 가상환경 Python 3.x
+-----+ +-----+
| | ----> | |
| | | |
+-----+ +-----+
:
:(여러 개 만들 수 있다.)
각자 자신의 워크스페이스에서 작업한다.
자신의 워크스페이스는 모두 다를 수 있다.
1. 가상환경 생성
현재 설치된 파이썬을 복제한다.
워크스페이스 폴더: D:\pythonWorkspace (각자 다르다.)
가상환경 폴더: scapyTest
형식: python -m venv <가상환경이름>
D:\pythonWorkspace>python -m venv scapyTest
2. 가상환경 변경
가상환경이 생성되면 가상환경으로 변경한다.
형식: <가상환경이름>\Scripts\activate
D:\pythonWorkspace>cd scapyTest\Scripts
D:\pythonWorkspace\scapyTest\Scripts>dir
복제된 환경으로 사용한다.
D:\pythonWorkspace\scapyTest\Scripts> activate
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>
VSCode 에서도 가상환경으로 변경한다.
오른쪽 하단에 3.11.2 64bit를 클릭해서 가상환경의 경로를 선택한다.
[3.11.2 64bit] > [3.11.2('scapyTest':venv)
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>
3. pip 업그레이드
가상환경으로 변경하면 반드시 pip 명령어를 업그레이드해야 한다.
형식 1: python -m pip install --upgrade pip
형식 2: pip install --upgrade pip
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>python -m pip install --upgrade pip
4. 패키지 설치
yum 처럼 pip 명령어를 이용해서 파이썬에서 제공되는 패키지를 설치한다.
형식 1: python -m pip install <패키지명>
형식 2: pip install pymysql
패키지가 설치되는 경로: <워크스페이스>\<가상환경이름>\Lib\site-packages
pymysql 패키지를 설치한다.
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>python -m pip install pymysql
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>python -m pip list
Package Version
---------- -------
pip 23.0.1
PyMySQL 1.0.2
setuptools 65.5.0
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>pip list
Package Version
---------- -------
pip 23.0.1
PyMySQL 1.0.2
setuptools 65.5.0
패키지가 설치되는 경로: <워크스페이스>\<가상환경이름>\Lib\site-packages
PyMySQL 패키지가 <워크스페이스>\<가상환경이름>\Lib\site-packages에 저장된다.
D:\pythonWorkspace\scapyTest\Lib\site-packages
<워크스페이스><가상환경명>
5. 가상환경 종료
형식: <워크스페이스>\<가상환경이름>\Scripts deactivate.bat
가상환경을 종료한다.
(scapyTest) D:\pythonWorkspace\scapyTest\Scripts>deactivate.bat
D:\pythonWorkspace\scapyTest\Scripts>python
Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymysql
>>> exit()
실습> scapy 설치하기
가상환경 scapyTest를 생성해서 scapy를 설치한다.
1. 패키지 설치
VSCode에서 cmd창을 열어서 작성한다.
(scapyTest) D:\pythonWorkspace>pip install scapy
(scapyTest) D:\pythonWorkspace>pip list
Package Version
---------- -------
pip 23.0.1
PyMySQL 1.0.2
scapy 2.5.0 <-- 설치된 scapy (<워크스페이스>\<가상환경이름>\Lib\site-packages)
setuptools 65.5.0
2. scapy 실행
(scapyTest) D:\pythonWorkspace>scapy
:
:(생략)
>>> a = IP(ttl=10)
>>> a.src
'127.0.0.1'
>>> a
<IP ttl=10 |>
>>>
실습> Kali Linux에서 scapy 사용하기
[root@kali ~]# scapy
>>> a = IP()
>>> a
<IP |>
>>> a = IP(ttl=10)
>>> a
<IP ttl=10 |>
>>> a.src
'127.0.0.1'
>>> a.dst
'127.0.0.1'
>>> a.src = '200.200.200.4'
>>> a.src
'200.200.200.4'
>>> a.dst = '200.200.200.3'
>>> a
<IP ttl=10 src=200.200.200.4 dst=200.200.200.3 |>
>>> quit
실습> 리눅스에서 가상환경 사용하기
1. 파이썬 설치
# yum -y install python3
2. 가상환경 프로젝트 생성
가상환경 프로젝트 2개를 생성한다.
venv(Virtual ENvirenment)
가상환경 생성 형식:
리눅스: python3 -m venv 가상환경이름(프로젝트명)
# python3 -m venv scapyTest
3. 가상환경 활성화
첫 번째 가상환경 project1 bin/activate 를 실행해서 가상환경을 활성화 한다.
!!! 여기서는 테스트이므로 root 사용자로 실행하지만 실제로는 일반유저에서 사용해야 한다. !!!
[root@victim3 ~]# . scapyTest/bin/activate
(scapyTest) [root@victim3 ~]#
가상환경을 해제할 때는 deactivate를 실행한다.
(scapyTest) [root@victim3 ~]# deactivate
4. pip 업그레이드
가상환경으로 변경되면 반드시 pip 업그레이드를 한번 실행해서 최신버전으로 유지해야 한다.
[root@victim3 ~]# . scapyTest/bin/activate
(scapyTest) [root@victim3 ~]# python -m pip install --upgrade pip
5. 패키지 확인
(scapyTest) [root@victim3 ~]# pip list
Package Version
---------- -------
php 1.2.1
pip 21.3.1
setuptools 39.2.0
6. 패키지 설치
(scapyTest) [root@victim3 ~]# pip install pymysql
(scapyTest) [root@victim3 ~]# pip list
Package Version
---------- -------
php 1.2.1
pip 21.3.1
PyMySQL 1.0.2
setuptools 39.2.0
(scapyTest) [root@victim3 ~]# pip install scapy
(scapyTest) [root@victim3 ~]# scapy
>>>
>>> 정리 <<<
가상환경을 일반 유저에서도 사용이 가능하다.
[root@victim3 ~]# yum -y install python3 <-- root 권한이 필요
[root@victim3 ~]# su - user1
나머지는 모두 일반 사용자에서 사용이 가능하다.
[user1@victim3 ~]$ python3 -m venv projectTest
[user1@victim3 ~]$ . projectTest/bin/activate
(scapyTest) [user1@victim3 ~]$ python -m pip install --upgrade pip
(scapyTest) [user1@victim3 ~]$ pip install pymysql
(scapyTest) [user1@victim3 ~]$ pip list
Package Version
---------- -------
pip 21.3.1
PyMySQL 1.0.2
setuptools 39.2.0
(scapyTest) [user1@victim3 ~]$ deactivate
[user1@victim3 ~]$ rm -rf projectTest
[user1@victim3 ~]$ exit
scapy 는 패킷을 조작해야 하므로 root권한이 필요하다.
[root@victim3 ~]# python3 -m venv scapyTest
[root@victim3 ~]# . scapyTest/bin/activate
(scapyTest) [root@victim3 ~]# python -m pip install --upgrade pip
(scapyTest) [root@victim3 ~]# python -m pip install scapy
(scapyTest) [root@victim3 ~]# python -m pip list
Package Version
---------- -------
pip 21.3.1
scapy 2.5.0 <-- /root/scapyTest/lib/python3.6/site-packages/
setuptools 39.2.0
(scapyTest) [root@victim3 ~]# scapy
:
:(생략)
>>>
Ether 헤더를 생성한다.
>>> packet = Ether()
>>> packet.show()
WARNING: Mac address to reach destination not found. Using broadcast.
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 00:0c:29:3d:bf:69 <-- 자신의 MAC 주소
type = LOOP
ARP 헤더를 생성한다.
>>> packet = ARP()
>>> packet.show()
###[ ARP ]###
hwtype = Ethernet (10Mb)
ptype = IPv4
hwlen = None
plen = None
op = who-has
hwsrc = 00:0c:29:3d:bf:69
psrc = 200.200.200.6
hwdst = 00:00:00:00:00:00
pdst = 0.0.0.0
IP 헤더를 생성한다.
>>> packet = IP()
>>> packet.show()
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = hopopt
chksum = None
src = 127.0.0.1
dst = 127.0.0.1
\options \
>>> del packet
ICMP 헤더를 생성한다.
>>> packet = ICMP()
>>> packet.show()
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
unused = ''
UDP 패킷을 생성한다.
>>> packet = UDP() <-- s1 = Student()
>>> packet <-- s1
<UDP |>
>>> packet.show() <-- s1.printAge()
###[ UDP ]###
sport = domain
dport = domain
len = None
chksum = None
[Attacker]3000 --------------> 53[DNS]
>>> packet.sport = 3000
>>> packet.dport = 53
>>> packet.show()
###[ UDP ]###
sport = hbci
dport = domain
len = None
chksum = None
[root@victim3 ~]# grep ^hbci /etc/services
hbci 3000/tcp # HBCI
hbci 3000/udp # HBCI
[root@victim3 ~]# grep ^domain /etc/services
domain 53/tcp # name-domain server
TCP 헤더를 생성한다.
>>> packet = TCP()
>>> packet
<TCP |>
>>> packet.show()
###[ TCP ]###
sport = ftp_data
dport = http
seq = 0
ack = 0
dataofs = None
reserved = 0
flags = S
window = 8192
chksum = None
urgptr = 0
options = ''
>>> del packet
s1 = Student()
s1.setAge(10) # 10살 세팅
s1.printAge() # 10살 출력
s1 = Student(10)
s1.printAge() # 10살 출력
>>> packet = IP(src='1.1.1.1',dst='200.200.200.6')
>>> packet.show()
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = hopopt
chksum = None
src = 1.1.1.1
dst = 200.200.200.6
\options \
참고: https://cafe.naver.com/linuxmasternet/1592
>>> packet = IP(dst='2.2.2.2', ttl=128, src='1.2.3.4')
>>> packet.show()
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 128
proto = hopopt
chksum = None
src = 1.2.3.4
dst = 2.2.2.2
\options \
>>> a = Ether(src="11:22:33:44:55:66")
>>> a.show()
WARNING: Mac address to reach destination not found. Using broadcast.
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 11:22:33:44:55:66
type = LOOP
>>> a.show()
WARNING: Mac address to reach destination not found. Using broadcast.
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 00:0c:29:3d:bf:69
type = LOOP
-- scapy1.py --
class Ether:
def __init__(self,
src='00:0c:29:3d:bf:69',
dst='ff:ff:ff:ff:ff:ff',
type='LOOP'):
self.src = src
self.dst = dst
self.type = type
def show(self):
print('###[ Ethernet ]###')
print(f'dst = {self.dst}')
print(f'src = {self.src}')
print(f'type = {self.type}')
a = Ether()
a.show()
-- scapy1.py --
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 00:0c:29:3d:bf:69
type = LOOP
실습> Ether 클래스 만들기
실제 이렇게 작성되었는지 실제 소스를 봐야하고 가상으로 작성한 것이다.
-- scapy1.py --
class Ether:
# 생성자
def __init__(self,
src='00:0c:29:3d:bf:69',
dst='ff:ff:ff:ff:ff:ff',
type='LOOP'):
self.src = src
self.dst = dst
self.type = type
def show(self):
""" 메소드 """
print('###[ Ethernet ]###')
print(f'dst = {self.dst}')
print(f'src = {self.src}')
print(f'type = {self.type}')
# 1. 객체 생성
a = Ether(src="11:22:33:44:55:66")
# 2. 메소드 호출
a.show()
-- scapy1.py --
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 11:22:33:44:55:66
type = LOOP
실습> 순서대로 자세히 출력
>>> a = Ether()
>>> ls(a)
>>> b = ARP()
>>> ls(b)
>>> c = IP()
>>> ls(c)
>>> d = ICMP()
>>> ls(d)
>>> e = UDP()
>>> ls(e)
>>> f = TCP()
>>> ls(f)
>>> g = DNS()
>>> ls(g)
>>> packet = Ether()/IP()/TCP()
>>> packet
<Ether type=IPv4 |<IP frag=0 proto=tcp |<TCP |>>>
>>> ls(packet)
dst : DestMACField = 'ff:ff:ff:ff:ff:ff' ('None')
src : SourceMACField = '00:00:00:00:00:00' ('None')
type : XShortEnumField = 2048 ('36864')
--
version : BitField (4 bits) = 4 ('4')
ihl : BitField (4 bits) = None ('None')
tos : XByteField = 0 ('0')
len : ShortField = None ('None')
id : ShortField = 1 ('1')
flags : FlagsField = <Flag 0 ()> ('<Flag 0 ()>')
frag : BitField (13 bits) = 0 ('0')
ttl : ByteField = 64 ('64')
proto : ByteEnumField = 6 ('0')
chksum : XShortField = None ('None')
src : SourceIPField = '127.0.0.1' ('None')
dst : DestIPField = '127.0.0.1' ('None')
options : PacketListField = [] ('[]')
--
sport : ShortEnumField = 20 ('20')
dport : ShortEnumField = 80 ('80')
seq : IntField = 0 ('0')
ack : IntField = 0 ('0')
dataofs : BitField (4 bits) = None ('None')
reserved : BitField (3 bits) = 0 ('0')
flags : FlagsField = <Flag 2 (S)> ('<Flag 2 (S)>')
window : ShortField = 8192 ('8192')
chksum : XShortField = None ('None')
urgptr : ShortField = 0 ('0')
options : TCPOptionsField = [] ("b''")
실습> scapy를 이용한 패킷 전송
Attacker(Kali) : 200.200.200.3 00:0c:29:28:37:34
Victim3(CentOS7): 200.200.200.6 00:0c:29:3d:bf:69
1. 방화벽 중지
[root@victim3 ~]# systemctl stop firewalld
[root@victim3 ~]# iptables -F
2. 웹서버 실행
[root@victim3 ~]# systemctl start httpd
3. 패킷 모니터링
[root@victim3 ~]# tcpdump -nn -i ens33 not port 22 and host 200.200.200.3 and tcp -vv
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
4. scapy 실행
[root@kali ~]# scapy
IPv4 패킷 생성
형식: 변수 = Ether(옵션)/IP(옵션)/TCP(옵션)
>>> packet = Ether(dst='00:0c:29:3d:bf:69')/IP(ttl=2,dst='200.200.200.6')/TCP(dport=80)
>>> ls(packet)
dst : DestMACField = '00:0c:29:3d:bf:69' ('None') <--
src : SourceMACField = '00:0c:29:28:37:34' ('None')
type : XShortEnumField = 2048 ('36864')
--
version : BitField (4 bits) = 4 ('4')
ihl : BitField (4 bits) = None ('None')
tos : XByteField = 0 ('0')
len : ShortField = None ('None')
id : ShortField = 1 ('1')
flags : FlagsField = <Flag 0 ()> ('<Flag 0 ()>')
frag : BitField (13 bits) = 0 ('0')
ttl : ByteField = 2 ('64') <--
proto : ByteEnumField = 6 ('0')
chksum : XShortField = None ('None')
src : SourceIPField = '200.200.200.3' ('None')
dst : DestIPField = '200.200.200.6' ('None')
options : PacketListField = [] ('[]')
--
sport : ShortEnumField = 20 ('20')
dport : ShortEnumField = 80 ('80') <--
seq : IntField = 0 ('0')
ack : IntField = 0 ('0')
dataofs : BitField (4 bits) = None ('None')
reserved : BitField (3 bits) = 0 ('0')
flags : FlagsField = <Flag 2 (S)> ('<Flag 2 (S)>')
window : ShortField = 8192 ('8192')
chksum : XShortField = None ('None')
urgptr : ShortField = 0 ('0')
options : TCPOptionsField = [] ("b''")
[root@victim3 ~]# tcpdump -nn -i ens33 not port 22 and host 200.200.200.3 and tcp -vv
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
패킷 1개 보내기
형식: sendp(packet)
count 인수가 없으면 default 매개변수의 값이 1로 설정되므로 패킷이 1개가 전송된다.
sendp(packet) == sendp(packet, count=1) == sendp(packet, count=1, loop=0)
>>> sendp(packet)
패킷 1000개 전송
count 인수가 1000으로 설정되므로 패킷이 10,000개가 전송된다.
- count변수에 패킷 개수를 설정하고 전송한다.
>>> sendp(packet, count=10000)
패킷 무한루프 전송
- loop변수에 1을 설정하고 전송한다.
- 종료는 Ctrl + C를 누른다.
형식: sendp(packet, loop=1)
>>> sendp(packet, loop=1)
실습> 패킷 전송 프로그램 제작하기
scapy 가 내부적으로 socket 을 이용한다.
1. 패킷 모니터링
[root@victim3 ~]# tcpdump -nn -i ens33 not port 22 and host 200.200.200.3 and port 80
2. 소스코드 작성
[root@kali ~]# vi sendPacket.py
#!/usr/bin/python3
from scapy.all import *
import sys
# Victim3(CentOS7): 200.200.200.6 00:0c:29:3d:bf:69
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <packet count>")
sys.exit(1)
packetCount = int(sys.argv[1])
packet = Ether(dst='00:0c:29:3d:bf:69')/IP(dst='200.200.200.6')/TCP(dport=80)
sendp(packet, count=packetCount)
3. 프로그램 실행
[root@kali ~]# chmod 755 sendPacket.py
[root@kali ~]# ./sendPacket.py
Usage: ./sendPacket.py <packet count>
[root@kali ~]# ./sendPacket.py 1
[root@kali ~]# ./sendPacket.py 100000