工具|Golang安全开发之NMAP格式IP解析库

作者:飞天魔鬼
免责声明:本文仅供学习研究,严禁从事非法活动,任何后果由使用者本人负责。

0x00 简介

在平时使用golang写一些小工具的时候,ip地址解析是必须要使用的功能之一。很多工具解析ip只是简单的生成C段、B段、A段的全部ip地址,并不支持cidr的方式来灵活的生成ip。
比如我们要扫描10.1.1.1/22网段,这时候简单的生成C段B段就不顶事儿了。于是就有了自己实现一个可以将nmap格式的ip地址范围解析生成ip的golang类库的想法。

0x01 TODO

实现可以解析以下ip地址段,获取其包含的全部ip

192.168.0.1
192.168.0.1/24 
192.168.0.1-22 
192.168.0.* 
192.168.0.1192.168.2.1/24192.168.3.1-100192.168.4.*

0x02 实现解析cidr来生成ip

func DealCIDR(cidr string) ([]string, error) {
    
    
    ip, ipnet, err := net.ParseCIDR(cidr)
    if err != nil {
    
    
        return nil, err
    }
    var ips []string
    for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); ip_tools(ip) {
    
    
        ips = append(ips, ip.String())
    }
    return ips[1 : len(ips)-1], nil
}

func ip_tools(ip net.IP) {
    
    
    for j := len(ip) - 1; j >= 0; j-- {
    
    
        ip[j]++
        if ip[j] > 0 {
    
    
            break
        }
    }
}

1、DealCIDR函数接收一个cidr格式的IP地址范围,使用net库中的ParseCIDR()函数来获取当前cidr的ip地址和该ip地址对应的网络(例如:传入192.0.2.1/24 获得返回192.0.2.1地址和其对应的网络192.0.2.0/24)

2、使用一个for循环来循环遍历该网络地址中包含的所有ip,循环的初始值应该为该网络对应的子网掩码所包含的ip中的第一个,即为ip.Mask(ipnet.Mask)。其中ipnet.Mask为当前网络所对应的子网掩码,使用ip.Mask()即可获取当前网络对应的子网掩码所包含的ip中的第一个。

3、for循环的条件应该是当前网络是否包含当前的ip地址,即为ipnet.Contains(ip)

4、实现ip的自增就要再写一个函数ip_tools来实现。该函数需要传入一个net.IP来实现ip的自增或者自减。这里需要注意的是IP数据类型其实是一个内部为byte类型的切片,而byte类型的最大值为255,只要255再加1,byte就会变成0,所以可以利用这一点来实现ip地址的自增和移位。

0x03 实现解析「*」来批量获取C、B、A段全部ip

func DealAsterisk(s string) ([]string, error) {
    
    
    i := strings.Count(s, "*")

    switch i {
    
    
    case 1:
        return DealCIDR(strings.Replace(s, "*", "1", -1) + "/24")
    case 2:
        return DealCIDR(strings.Replace(s, "*", "1", -1) + "/16")
    case 3:
        return DealCIDR(strings.Replace(s, "*", "1", -1) + "/8")
    }

    return nil, errors.New("wrong Asterisk")
}

1、原理很简单,传入的string我们直接统计其个数,如果为1个则是C段的全部ip,如果为2个则是B段的全部ip,如果为3个则是A段的全部ip。
2、然后调用我们上面写好的DealCIDR函数来直接进行处理即可。

3、如果格式错误则会报错。

0x04 处理「-」,来获取范围内的ip

func DealHyphen(s string) ([]string, error) {
    
    
    tmp := strings.Split(s, ".")
    //TODO 异常处理
    if len(tmp) == 4 {
    
    
        iprange_tmp := strings.Split(tmp[3], "-")
        var ips []string
        tail, _ := strconv.Atoi(iprange_tmp[1])
        for head, _ := strconv.Atoi(iprange_tmp[0]); head <= tail; head++ {
    
    
            ips = append(ips, tmp[0]+"."+tmp[1]+"."+tmp[2]+"."+strconv.Itoa(head))
        }
        return ips, nil
    } else {
    
    
        return nil, errors.New("wrong Hyphen")
    }
}

原理很简单,将传入的ip范围按点分割,获取到最后的数值之后再依次添加进slice。

0x05 Handler函数

func Handler(s string) ([]string, []error) {
    
    

    IPstrings := strings.Split(strings.Trim(s, ","), ",")
    var ips []string
    var err []error

    for i := 0; i < len(IPstrings); i++ {
    
    
        if strings.Contains(IPstrings[i], "*") {
    
    
            //TODO 192.168.0.*
            ips_tmp, err_tmp := DealAsterisk(IPstrings[i])
            err = append(err, err_tmp)
            ips = append(ips, ips_tmp...)
        } else if strings.Contains(IPstrings[i], "/") {
    
    
            //TODO 192.168.0.1/24
            ips_tmp, err_tmp := DealCIDR(IPstrings[i])
            err = append(err, err_tmp)
            ips = append(ips, ips_tmp...)

        } else if strings.Contains(IPstrings[i], "-") {
    
    
            //TODO 192.668.0.1-255
            ips_tmp, err_tmp := DealHyphen(IPstrings[i])
            err = append(err, err_tmp)
            ips = append(ips, ips_tmp...)
        } else {
    
    
            //TODO singel ip
            ips = append(ips, IPstrings[i])
        }
    }
    fmt.Println("hello")
    return ips, err
}

将传入的字符串按逗号进行分割,然后判断其中的元素是否含有特定的字符,再调用相应的函数处理即可。

0x06 完整代码

package nmapIPrange
import (
    "errors"
    "fmt"
    "net"
    "strconv"
    "strings"
)

func DealCIDR(cidr string) ([]string, error) {
    
    
    ip, ipnet, err := net.ParseCIDR(cidr)
    if err != nil {
    
    
        return nil, err
    }
    var ips []string
    //在循环里创建的所有函数变量共享相同的变量。
    for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); ip_tools(ip) {
    
    
        ips = append(ips, ip.String())
    }
    return ips[1 : len(ips)-1], nil
}

func ip_tools(ip net.IP) {
    
    
    for j := len(ip) - 1; j >= 0; j-- {
    
    
        ip[j]++
        if ip[j] > 0 {
    
    
            break
        }
    }
}

func DealAsterisk(s string) ([]string, error) {
    
    
    i := strings.Count(s, "*")

    switch i {
    
    
    case 1:
        return DealCIDR(strings.Replace(s, "*", "1", -1) + "/24")
    case 2:
        return DealCIDR(strings.Replace(s, "*", "1", -1) + "/16")
    case 3:
        return DealCIDR(strings.Replace(s, "*", "1", -1) + "/8")
    }

    return nil, errors.New("wrong Asterisk")
}

func DealHyphen(s string) ([]string, error) {
    
    
    tmp := strings.Split(s, ".")
    //TODO 异常处理
    if len(tmp) == 4 {
    
    
        iprange_tmp := strings.Split(tmp[3], "-")
        var ips []string
        tail, _ := strconv.Atoi(iprange_tmp[1])
        for head, _ := strconv.Atoi(iprange_tmp[0]); head <= tail; head++ {
    
    
            ips = append(ips, tmp[0]+"."+tmp[1]+"."+tmp[2]+"."+strconv.Itoa(head))
        }
        return ips, nil
    } else {
    
    
        return nil, errors.New("wrong Hyphen")
    }

}

func Handler(s string) ([]string, []error) {
    
    

    IPstrings := strings.Split(strings.Trim(s, ","), ",")
    var ips []string
    var err []error

    for i := 0; i < len(IPstrings); i++ {
    
    
        if strings.Contains(IPstrings[i], "*") {
    
    
            //TODO 192.168.0.*
            ips_tmp, err_tmp := DealAsterisk(IPstrings[i])
            err = append(err, err_tmp)
            ips = append(ips, ips_tmp...)
        } else if strings.Contains(IPstrings[i], "/") {
    
    
            //TODO 192.168.0.1/24
            ips_tmp, err_tmp := DealCIDR(IPstrings[i])
            err = append(err, err_tmp)
            ips = append(ips, ips_tmp...)

        } else if strings.Contains(IPstrings[i], "-") {
    
    
            //TODO 192.668.0.1-255
            ips_tmp, err_tmp := DealHyphen(IPstrings[i])
            err = append(err, err_tmp)
            ips = append(ips, ips_tmp...)
        } else {
    
    
            //TODO singel ip
            ips = append(ips, IPstrings[i])
        }
    }
    fmt.Println("hello")
    return ips, err
}

0x07 总结

运行效果:
在这里插入图片描述
项目地址:https://github.com/gooderbrother/nmap-IPrange
时间原因有个别异常处理没做,大佬们有时间可以提个issue,记得start。

0x08 了解更多安全知识

欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42282189/article/details/120423896