OllamaとLangChain、Nmapを利用して遊んでみました。
Nmapの情報を、StructuredOutputで出力しようとしました。
LLMが処理しやすいように、構造化されたXMLで、Nmapの結果を出力しましたが、すべてのポートは取得できなかったです。
まぁ、プログラムで処理できるものは、プログラムでやったほうが確実ですしね...
Nmapコマンド
nmap -A -sT -v -T 4 [IP Address] -oX nmap.xml
結果
>> python sample_code.py
name='localhost' type='loopback' vendor='Linux' family='IPv4' generation='2.6.32-71-generic' cpes=['cpe:/o:linux:linux:2.6.32-71-generic'] ports=[PortInfo(port=22, protocol='tcp', service_name='ssh'), PortInfo(port=80, protocol='tcp', service_name='http')]
全体コード
import subprocess
from typing import List
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model
class PortInfo(BaseModel):
"""Port Info
"""
port: int = Field(..., description="Open Port Number")
protocol: str = Field(..., description="Open Port Protocol")
service_name: str = Field(..., description="Open Port Service Name")
class OSInfo(BaseModel):
"""OS Info
"""
name: str = Field(..., description="OS Name")
type: str = Field(..., description="OS Type")
vendor: str = Field(..., description="OS Vendor")
family: str = Field(..., description="OS Family")
generation: str = Field(..., description="OS Generation")
cpes: List[str] = Field(..., description="OS Common Platform Enumeration")
ports: List[PortInfo] = Field(..., description="Open Ports")
def port_scan(ip_address: str) -> str:
"""Run Nmap
"""
cmd = ['nmap', '-A', '-sT', '-v', '-T', '4', ip_address, '-oX', 'nmap.xml']
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
def main(ip_address: str):
model = init_chat_model(
model="ollama:llama3.2:latest",
base_url="http://[Ollama Server IP Address]:11434",
temperature=0
)
structured_model = model.with_structured_output(OSInfo)
nmap_output = port_scan(ip_address)
prompt = f"""以下のNmap出力結果から、OSとポートの情報を抽出してください。
ポート情報は、<port>タグを全て見つけて、state="open"の全てのポートを抽出してください。
Nmap出力:
{nmap_output}
** ポートはすべてのポートを抽出してください。 **
"""
scan_result: OSInfo = structured_model.invoke(prompt)
print(scan_result)
if __name__ == "__main__":
main("[Target IP Address]")