資安基礎惡補 - 網路篇 - 用 Python 3.5 實踐 MAC Changer

Python 3 實踐 MAC Changer 


還記得我們在 上一篇 鋪的哏嗎?

今天我們就來用 Python 實作 Mac Changer 看看!


先備知識 - Python 

基於 Python 3.5 後的版本實踐,我們會需要認識一些新版本的函式。


subprocess.run(3.5版本以後加入)


import subprocess

subprocess.run(["ls", "-l", "/dev/null"], capture_output=True)


像是上述這個例子,經過逐步拆解,大致上會是這樣:

1. 使用 subprocess.run 執行系統指令

2. ["ls", "-l", "/dev/null"] 如同在終端機執行以下指令


ls -l /dev/null


意思是列出 /dev/null 這個文件的詳細資訊, capture_output=True 代表擷取標準輸出、標準輸入,但是因為這行程式並沒有儲存輸出,所以不會顯示結果(如下圖)。



如果拿掉 capture_output=True 就會跑出結果了(如下圖),讀者們可以試試看!



除此之外,如果想要保持原有設定,並把結果儲存到文字中,可以這樣寫:


import subprocess

result = subprocess.run(["ls", "-l", "/dev/null"], capture_output=True, text=True)
print(result.stdout)


結果輸出會像是下圖:



subprocess.check_output()(3.1版本以後加入)

check_output() 「自動啟用了 check=True」,如果命令執行失敗(回傳碼 !== 0),它會拋出錯誤,而非靜默失敗。另外,有個好用的地方,就是我們可以使用這個函式來獲取輸出的結果。


argparse(3.2版本以後加入)

argparse 基本上就是一個用來解析命令列模組(CLI Arguments)的 Python 內建模組,讓我們的 Python script 可以支援不同的輸入選項,例如:


python test.py --interface eth0 --mac 00:11:22:33:44:55


我們在這邊看到了「--interface eth0」、「--mac 00:11:22:33:44:55」等參數,前者代表要帶的指定參數,後者則是要帶的參數值。


在大致了解使用情境後,我們來看一下經典範例:


import argparse

parser = argparse.ArgumentParser(
                    prog="Mac Changer",
                    description="用來改變 Mac 地址的工具",
                    epilog="Text at the bottom of help")
parser.add_argument("-i","--interface", dest="interface", help="介面")
parser.add_argument("-m","--mac", dest="new_mac", help="想換成的新mac帳號")

args = parser.parse_args()
# 此處的 args 裡面有之前寫的那些參數
print(arg.new_mac)


所以,今天假設我們下了以下指令:

python3 test.py -h


就會印出參數使用說明:







說到這,需要補充一下舊版使用 optparse 要如何更新成 argparse 的參考文件:

https://docs.python.org/zh-tw/3/howto/argparse-optparse.html#upgrading-optparse-code


先備知識 - Linux

接下來,我們來聊聊與 Mac Changer 相關的 Linux 指令:


ifconfig

可以用來看看我們目前的網路介面以及對應的 ip address、MAC address 等: 












可以看到這邊有 eth0、lo 等網卡介面,這些名稱是根據系統設定而定的。eth0 代表我們的有線網路,IP 是 172.16.108.129,而 lo 代表 本機 Loopback,IP 是 127.0.0.1。

接下來,我們進入重頭戲,修改 MAC Address!


STEP1: ifconfig eth0 down

接著,我們需要先禁用這個 interface: eth0。


STEP2: ifconfig eth0 hw ether 00:11:22:33:44:55

此處的 hw 代表 hardware; ether 代表 Ethernet(乙太網路),表示要修改 MAC 位址。


STEP3: ifconfig eth0 up

由於我們先前禁用了 eth0,所以我們現在需要做一件事:「啟用它!」


最後,再使用 ifconfig 看一下~









可以看到我們的 eth0 的 MAC Address 變成 00:11:22:33:44:55 啦!


實踐它吧!

前面我們都是在鋪哏啦!其實最主要的部分還是實踐。

在有了一些模組的使用基礎後,我們大致上就可以想一下要怎麼自動化,並且讓這個 MAC Changer 更好用啦!


給大家看一下最後完成的範例:

#!/usr/bin/env python

import argparse
import subprocess
import re

def get_args():
    parser = argparse.ArgumentParser(
        prog="Mac Changer",
        description="用來改變 Mac 地址的工具",
        epilog="Text at the bottom of help"
    )
    
    parser.add_argument("-i", "--interface", dest="interface", 
    required=True, help="介面")
    
    parser.add_argument("-m", "--mac", dest="new_mac_adr", 
    required=True, help="想換成的新 MAC Address")
    
    return parser.parse_args()

def change_MAC(interface, new_mac_adr):
    print(f"[+] 轉換 {interface} 介面的 MAC Address 成 {new_mac_adr}")
    
    subprocess.run(["ifconfig", interface, "down"], check=True)
    subprocess.run(["ifconfig", interface, "hw", "ether", new_mac_adr], check=True)
    subprocess.run(["ifconfig", interface, "up"], check=True)
    
    # 轉換後再確認一次 MAC
    return get_MAC(interface)

def get_MAC(interface):
    
    try:
        search_result = subprocess.check_output(["ifconfig", interface], 
        text=True)  # 確保是字串
        
        mac_adr_search_result = re.search(r"\w\w:\w\w:\w\w:\w\w:\w\w:\w\w", 
        search_result)

        if mac_adr_search_result:
            return mac_adr_search_result.group(0)
        else:
            print("[-] 無法讀取 MAC Address")
            return None
    except subprocess.CalledProcessError:
        print(f"[-] 無法執行 ifconfig,請確認 {interface} 是否正確")
        return None

args = get_args()

cur_MAC = get_MAC(args.interface)
if cur_MAC:
    print(f"目前的 MAC 是:{cur_MAC}")
else:
    print("[-] 無法獲取目前的 MAC Address,請確認網卡介面是否正確!")
    exit(1)

# 執行 MAC 變更
new_MAC = change_MAC(args.interface, args.new_mac_adr)

if new_MAC and new_MAC == args.new_mac_adr:
    print(f"[+] MAC Address 成功更改為:{new_MAC}")
else:
    print("[-] MAC Address 變更失敗!")


接下來,我們就可以在 Linux 上試試看這個檔案啦(參考下圖)!











參考資源


預告

終於找回學習的樂趣XD

下一篇我們將會介紹更多與 ARP  相關的內容~

留言

這個網誌中的熱門文章

資安基礎惡補 - 網路篇 - DNS

SSL/TLS 協定知多少 - 基礎篇

About Me - 關於我的一切