Skip to content

Commit

Permalink
Merge pull request #13 from knownsec/dev
Browse files Browse the repository at this point in the history
v0.4
  • Loading branch information
boy-hack authored Sep 4, 2020
2 parents 4c3f6dc + ebd526d commit 64bfe82
Show file tree
Hide file tree
Showing 13 changed files with 857,545 additions and 15 deletions.
2 changes: 1 addition & 1 deletion core/banner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"ksubdomain/gologger"
)

const Version = "0.3"
const Version = "0.4"
const banner = `
_ __ _____ _ _ _
| |/ / / ____| | | | | (_)
Expand Down
46 changes: 46 additions & 0 deletions core/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package core

import (
"bufio"
"github.com/rakyll/statik/fs"
_ "ksubdomain/core/statik"
"ksubdomain/gologger"
"net"
"strconv"
"strings"
)

func GetAsnData() []AsnStruct { //[]AsnStruct
var asnData []AsnStruct = []AsnStruct{}
statikFS, err := fs.New()
if err != nil {
gologger.Fatalf(err.Error())
}
r, err := statikFS.Open("/asn.txt")
if err != nil {
gologger.Fatalf("打开资源文件失败:%s", err.Error())
}
defer r.Close()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
err := scanner.Err()
if err != nil {
break
}
line = strings.TrimSpace(line)
if line == "" {
continue
}
parts := strings.Split(line, "\t")
if len(parts) != 4 {
gologger.Fatalf("错误:%s", line)
}
asnid, _ := strconv.Atoi(parts[2])
startIP := net.ParseIP(parts[0]).To4()
endIP := net.ParseIP(parts[1]).To4()
asnData = append(asnData, AsnStruct{
ASN: asnid, Registry: parts[3], Cidr: Range2CIDR(startIP, endIP)})
}
return asnData
}
273 changes: 273 additions & 0 deletions core/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
package core

import (
"bytes"
"math/big"
"net"
"strconv"
"strings"
)

// IPv4RE is a regular expression that will match an IPv4 address.
const IPv4RE = "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"

// ReservedCIDRDescription is the description used for reserved address ranges.
const ReservedCIDRDescription = "Reserved Network Address Blocks"

// ReservedCIDRs includes all the networks that are reserved for special use.
var ReservedCIDRs = []string{
"192.168.0.0/16",
"172.16.0.0/12",
"10.0.0.0/8",
"127.0.0.0/8",
"224.0.0.0/4",
"240.0.0.0/4",
"100.64.0.0/10",
"198.18.0.0/15",
"169.254.0.0/16",
"192.88.99.0/24",
"192.0.0.0/24",
"192.0.2.0/24",
"192.94.77.0/24",
"192.94.78.0/24",
"192.52.193.0/24",
"192.12.109.0/24",
"192.31.196.0/24",
"192.0.0.0/29",
}

// The reserved network address ranges
var reservedAddrRanges []*net.IPNet

func init() {
for _, cidr := range ReservedCIDRs {
if _, ipnet, err := net.ParseCIDR(cidr); err == nil {
reservedAddrRanges = append(reservedAddrRanges, ipnet)
}
}
}

// IsIPv4 returns true when the provided net.IP address is an IPv4 address.
func IsIPv4(ip net.IP) bool {
return strings.Count(ip.String(), ":") < 2
}

// IsIPv6 returns true when the provided net.IP address is an IPv6 address.
func IsIPv6(ip net.IP) bool {
return strings.Count(ip.String(), ":") >= 2
}

// IsReservedAddress checks if the addr parameter is within one of the address ranges in the ReservedCIDRs slice.
func IsReservedAddress(addr string) (bool, string) {
ip := net.ParseIP(addr)
if ip == nil {
return false, ""
}

var cidr string
for _, block := range reservedAddrRanges {
if block.Contains(ip) {
cidr = block.String()
break
}
}

if cidr != "" {
return true, cidr
}
return false, ""
}

// FirstLast return the first and last IP address of the provided CIDR/netblock.
func FirstLast(cidr *net.IPNet) (net.IP, net.IP) {
firstIP := cidr.IP
prefixLen, bits := cidr.Mask.Size()

if prefixLen == bits {
lastIP := make([]byte, len(firstIP))
copy(lastIP, firstIP)
return firstIP, lastIP
}

firstIPInt, bits := ipToInt(firstIP)
hostLen := uint(bits) - uint(prefixLen)
lastIPInt := big.NewInt(1)

lastIPInt.Lsh(lastIPInt, hostLen)
lastIPInt.Sub(lastIPInt, big.NewInt(1))
lastIPInt.Or(lastIPInt, firstIPInt)

return firstIP, intToIP(lastIPInt, bits)
}

// Range2CIDR turns an IP range into a CIDR.
func Range2CIDR(first, last net.IP) *net.IPNet {
startip, m := ipToInt(first)
endip, _ := ipToInt(last)
newip := big.NewInt(1)
mask := big.NewInt(1)
one := big.NewInt(1)

if startip.Cmp(endip) == 1 {
return nil
}

max := uint(m)
var bits uint = 1
newip.Set(startip)
tmp := new(big.Int)
for bits < max {
tmp.Rsh(startip, bits)
tmp.Lsh(tmp, bits)

newip.Or(startip, mask)
if newip.Cmp(endip) == 1 || tmp.Cmp(startip) != 0 {
bits--
mask.Rsh(mask, 1)
break
}

bits++
tmp.Lsh(mask, 1)
mask.Add(tmp, one)
}

cidrstr := first.String() + "/" + strconv.Itoa(int(max-bits))
_, ipnet, _ := net.ParseCIDR(cidrstr)

return ipnet
}

// AllHosts returns a slice containing all the IP addresses within
// the CIDR provided by the parameter. This implementation was
// obtained/modified from the following:
// https://gist.github.com/kotakanbe/d3059af990252ba89a82
func AllHosts(cidr *net.IPNet) []net.IP {
var ips []net.IP

for ip := cidr.IP.Mask(cidr.Mask); cidr.Contains(ip); IPInc(ip) {
addr := net.ParseIP(ip.String())

ips = append(ips, addr)
}

if len(ips) > 2 {
// Remove network address and broadcast address
ips = ips[1 : len(ips)-1]
}
return ips
}

// RangeHosts returns all the IP addresses (inclusive) between
// the start and stop addresses provided by the parameters.
func RangeHosts(start, end net.IP) []net.IP {
var ips []net.IP

if start == nil || end == nil {
return ips
}

start16 := start.To16()
end16 := end.To16()
// Check that the end address is higher than the start address
if r := bytes.Compare(end16, start16); r < 0 {
return ips
} else if r == 0 {
return []net.IP{start}
}

stop := net.ParseIP(end.String())
IPInc(stop)

for ip := net.ParseIP(start.String()); !ip.Equal(stop); IPInc(ip) {
if addr := net.ParseIP(ip.String()); addr != nil {
ips = append(ips, addr)
}
}

return ips
}

// CIDRSubset returns a subset of the IP addresses contained within
// the cidr parameter with num elements around the addr element.
func CIDRSubset(cidr *net.IPNet, addr string, num int) []net.IP {
first := net.ParseIP(addr)

if !cidr.Contains(first) {
return []net.IP{first}
}

offset := num / 2
// Get the first address
for i := 0; i < offset; i++ {
IPDec(first)
// Check that it is still within the CIDR
if !cidr.Contains(first) {
IPInc(first)
break
}
}
// Get the last address
last := net.ParseIP(addr)
for i := 0; i < offset; i++ {
IPInc(last)
// Check that it is still within the CIDR
if !cidr.Contains(last) {
IPDec(last)
break
}
}
// Check that the addresses are not the same
if first.Equal(last) {
return []net.IP{first}
}
// Return the IP addresses within the range
return RangeHosts(first, last)
}

// IPInc increments the IP address provided.
func IPInc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}

// IPDec decrements the IP address provided.
func IPDec(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
if ip[j] > 0 {
ip[j]--
break
}
ip[j]--
}
}

func ipToInt(ip net.IP) (*big.Int, int) {
val := big.NewInt(1)

val.SetBytes([]byte(ip))
if IsIPv4(ip) {
return val, 32
} else if IsIPv6(ip) {
return val, 128
}

return val, 0
}

func intToIP(ipInt *big.Int, bits int) net.IP {
ipBytes := ipInt.Bytes()
ret := make([]byte, bits/8)

// Pack our IP bytes into the end of the return array,
// since big.Int.Bytes() removes front zero padding
for i := 1; i <= len(ipBytes); i++ {
ret[len(ret)-i] = ipBytes[len(ipBytes)-i]
}

return net.IP(ret)
}
4 changes: 3 additions & 1 deletion core/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Options struct {
Debug bool
DomainLevel int
SkipWildCard bool
Summary bool
}

// ParseOptions parses the command line flags provided by a user
Expand All @@ -36,11 +37,12 @@ func ParseOptions() *Options {
flag.StringVar(&options.Output, "o", "", "输出文件路径")
flag.BoolVar(&options.Test, "test", false, "测试本地最大发包数")
flag.IntVar(&options.NetworkId, "e", -1, "默认网络设备ID,默认-1,如果有多个网络设备会在命令行中选择")
flag.BoolVar(&options.Silent, "silent", false, "使用后屏幕将不会输出结果")
flag.BoolVar(&options.Silent, "silent", false, "使用后屏幕将仅输出域名")
flag.BoolVar(&options.TTL, "ttl", false, "导出格式中包含TTL选项")
flag.BoolVar(&options.Verify, "verify", false, "验证模式")
flag.IntVar(&options.DomainLevel, "l", 1, "爆破域名层级,默认爆破一级域名")
flag.BoolVar(&options.SkipWildCard, "skip-wild", false, "跳过泛解析的域名")
flag.BoolVar(&options.Summary, "summary", false, "在扫描完毕后整理域名归属asn以及IP段")
flag.Parse()
options.Stdin = hasStdin()
if options.Silent {
Expand Down
Loading

0 comments on commit 64bfe82

Please sign in to comment.