arping
- 通过
sendARP
函数发送ARP
广播查询实时监测目标MAC
地址,若有变动立即输出警告。
为应对复杂环境并实现快速判断,推荐结合Wireshark
进行ARP
报文分析或使用Linux版本
C:\Users\admin>certutil -hashfile D:\arping.exe sha256
SHA256 的 D:\arping.exe 哈希:
c8ec7f443b7e4d614c4a279fe30f4a2570ddf27da55ff1ab5080a3a752149d56
C:\Users\admin>certutil -hashfile D:\arping.exe sha1
SHA1 的 D:\arping.exe 哈希:
d7273f5532ffae64a98d79369bc19b53dc4b49d4
C:\Users\admin>certutil -hashfile D:\arping.exe md5
MD5 的 D:\arping.exe 哈希:
6a71419144bd84e0ae460afbec6c0dd3
检测到冲突会提示信息
- 直接双击
arping.exe
根据提示输入检测目标IP
- 然后按
Enter(回车)
键
- 将
arping.exe
放入C:\Windows
目录 - 打开
CMD(终端)
输入arping <检测目标IP>
- 然后按
Enter(回车)
键
set HTTP_PROXY=http://192.168.123.2:10809
set HTTPS_PROXY=http://192.168.123.2:10809
go get golang.org/x/text/encoding/simplifiedchinese
go build
module arping
go 1.21.4
require golang.org/x/sys v0.5.0
require golang.org/x/text v0.14.0 // indirect
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
package main
import (
"bufio"
"encoding/binary"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"time"
"unsafe"
)
const redColor = "\033[31m"
func colorizeRed(text string) string {
return fmt.Sprintf("%s%s\033[0m", redColor, text)
}
var lastSeenMac = make(map[string]string)
func main() {
fmt.Println("arping 版本: V1.0.5 由 https://osed.cn 提供")
targetIP := ""
if len(os.Args) > 1 {
targetIP = os.Args[1]
}
for {
if targetIP == "" {
fmt.Print("请输入IP: ")
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
targetIP = scanner.Text()
}
if targetIP == "" {
fmt.Println("IP不能为空")
continue
}
}
// 创建一个通道用于通知goroutines立即退出
exitSignalCh := make(chan struct{})
// 创建一个新的goroutine来监听Ctrl+C
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
close(exitSignalCh) // 关闭通道,通知所有goroutine立即退出
signal.Stop(c) // 停止监听信号,这样可以重新开始监听
}()
arpCheckLoop(targetIP, exitSignalCh)
// 重置targetIP以允许输入新的IP地址
targetIP = ""
}
}
func arpCheckLoop(targetIP string, exitSignalCh chan struct{}) {
for {
select {
case <-exitSignalCh:
return
default:
performArpCheck(targetIP)
time.Sleep(500 * time.Millisecond) // 每500毫秒执行一次ARP查询
}
}
}
func performArpCheck(targetIP string) {
macAddr, err := sendARP(targetIP)
if err != nil {
// 不再输出详细的错误信息,仅简单提示没有MAC地址
fmt.Printf("%s 没有响应\n", targetIP)
return
}
fmt.Printf("IP %s - MAC %s\n", targetIP, macAddr)
previousMac, exists := lastSeenMac[targetIP]
if exists && macAddr != previousMac {
fmt.Printf(colorizeRed("发现IP冲突!IP:%s\n原MAC: %s\n现MAC: %s\n"), targetIP, previousMac, macAddr)
}
lastSeenMac[targetIP] = macAddr // 更新历史MAC地址
}
func sendARP(destIP string) (string, error) {
dst := net.ParseIP(destIP).To4()
if dst == nil {
return "", fmt.Errorf("无效的IP地址")
}
src := make([]byte, 4) // 本机IP地址,0.0.0.0表示任意
mac := make([]byte, 6) // 目标MAC地址
maclen := uint32(len(mac))
dll := syscall.MustLoadDLL("iphlpapi.dll")
proc := dll.MustFindProc("SendARP")
ret, _, callErr := proc.Call(
uintptr(binary.LittleEndian.Uint32(dst)),
uintptr(binary.LittleEndian.Uint32(src)),
uintptr(unsafe.Pointer(&mac[0])),
uintptr(unsafe.Pointer(&maclen)),
)
if ret != 0 {
return "", fmt.Errorf("SendARP调用失败: %v", callErr)
}
return net.HardwareAddr(mac).String(), nil
}