feat: init nightly vuls for blackhat

This commit is contained in:
MaineK00n
2022-11-15 11:26:26 +09:00
parent 1d97e91341
commit 3605645ff6
234 changed files with 6172 additions and 54872 deletions

44
pkg/scan/cpe/cpe.go Normal file
View File

@@ -0,0 +1,44 @@
package cpe
import (
"context"
"fmt"
"github.com/knqyf263/go-cpe/naming"
"github.com/pkg/errors"
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
"github.com/future-architect/vuls/pkg/types"
)
type Analyzer struct {
}
func (a Analyzer) Name() string {
return "cpe analyzer"
}
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
ah.Host.Packages.CPE = map[string]types.CPE{}
for _, c := range ah.Host.Config.Scan.CPE {
if _, err := naming.UnbindFS(c.CPE); err != nil {
return errors.Wrapf(err, "unbind %s", c.CPE)
}
key := c.CPE
if c.RunningOn != "" {
if _, err := naming.UnbindFS(c.RunningOn); err != nil {
return errors.Wrapf(err, "unbind %s", c.RunningOn)
}
key = fmt.Sprintf("%s_on_%s", c.CPE, c.RunningOn)
}
ah.Host.Packages.CPE[key] = types.CPE{
CPE: c.CPE,
RunningOn: c.RunningOn,
}
}
return nil
}

93
pkg/scan/os/os.go Normal file
View File

@@ -0,0 +1,93 @@
package os
import (
"bufio"
"context"
"strings"
"github.com/pkg/errors"
"github.com/future-architect/vuls/pkg/scan/ospkg/apk"
"github.com/future-architect/vuls/pkg/scan/ospkg/dpkg"
"github.com/future-architect/vuls/pkg/scan/ospkg/rpm"
"github.com/future-architect/vuls/pkg/scan/types"
)
type Analyzer struct {
}
func (a Analyzer) Name() string {
return "os analyzer"
}
func (a Analyzer) Analyze(ctx context.Context, ah *types.AnalyzerHost) error {
status, stdout, stderr, err := ah.Host.Exec(ctx, "cat /etc/os-release", false)
if err != nil {
return errors.Wrap(err, `exec "cat /etc/os-release"`)
}
if stderr != "" {
return errors.New(stderr)
}
if status != 0 {
return errors.Errorf("exit status is %d", status)
}
ah.Host.Family, ah.Host.Release, err = ParseOSRelease(stdout)
if err != nil {
return errors.Wrap(err, "parse /etc/os-release")
}
switch ah.Host.Family {
case "debian", "ubuntu":
ah.Analyzers = append(ah.Analyzers, dpkg.Analyzer{})
case "redhat", "centos", "alma", "rocky", "fedora", "opensuse", "opensuse.tumbleweed", "opensuse.leap", "suse.linux.enterprise.server", "suse.linux.enterprise.desktop":
ah.Analyzers = append(ah.Analyzers, rpm.Analyzer{})
case "alpine":
ah.Analyzers = append(ah.Analyzers, apk.Analyzer{})
case "":
return errors.New("family is unknown")
default:
return errors.New("not supported OS")
}
return nil
}
func ParseOSRelease(stdout string) (string, string, error) {
var family, versionID string
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
ss := strings.SplitN(line, "=", 2)
if len(ss) != 2 {
continue
}
key, value := strings.TrimSpace(ss[0]), strings.TrimSpace(ss[1])
switch key {
case "ID":
switch id := strings.Trim(value, `"'`); id {
case "almalinux":
family = "alma"
case "opensuse-leap", "opensuse-tumbleweed":
family = strings.ReplaceAll(id, "-", ".")
case "sles":
family = "suse.linux.enterprise.server"
case "sled":
family = "suse.linux.enterprise.desktop"
default:
family = strings.ToLower(id)
}
case "VERSION_ID":
versionID = strings.Trim(value, `"'`)
default:
continue
}
}
if family == "" {
return "", "", errors.New("family is unknown")
}
return family, versionID, nil
}

71
pkg/scan/ospkg/apk/apk.go Normal file
View File

@@ -0,0 +1,71 @@
package apk
import (
"bufio"
"context"
"strings"
"github.com/pkg/errors"
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
"github.com/future-architect/vuls/pkg/types"
)
type Analyzer struct {
}
func (a Analyzer) Name() string {
return "apk analyzer"
}
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
status, stdout, stderr, err := ah.Host.Exec(ctx, "apk info -v", false)
if err != nil {
return errors.Wrap(err, `exec "apk info -v"`)
}
if stderr != "" {
return errors.New(stderr)
}
if status != 0 {
return errors.Errorf("exit status is %d", status)
}
ah.Host.Packages.OSPkg, err = ParseInstalledPackage(stdout)
if err != nil {
return errors.Wrap(err, "parse installed package")
}
return nil
}
func ParseInstalledPackage(stdout string) (map[string]types.Package, error) {
pkgs := map[string]types.Package{}
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
name, version, err := parseApkInfo(scanner.Text())
if err != nil {
return nil, errors.Wrap(err, "parse apk info line")
}
if name == "" || version == "" {
continue
}
pkgs[name] = types.Package{
Name: name,
Version: version,
}
}
return pkgs, nil
}
func parseApkInfo(line string) (string, string, error) {
ss := strings.Split(line, "-")
if len(ss) < 3 {
if strings.Contains(ss[0], "WARNING") {
return "", "", nil
}
return "", "", errors.Errorf(`unexpected package line format. accepts: "<package name>-<version>-<release>", received: "%s"`, line)
}
return strings.Join(ss[:len(ss)-2], "-"), strings.Join(ss[len(ss)-2:], "-"), nil
}

View File

@@ -0,0 +1,95 @@
package dpkg
import (
"bufio"
"context"
"strings"
"github.com/pkg/errors"
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
"github.com/future-architect/vuls/pkg/types"
)
type Analyzer struct {
}
func (a Analyzer) Name() string {
return "dpkg analyzer"
}
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
status, stdout, stderr, err := ah.Host.Exec(ctx, `dpkg-query -W -f="\${binary:Package},\${db:Status-Abbrev},\${Version},\${Architecture},\${source:Package},\${source:Version}\n"`, false)
if err != nil {
return errors.Wrap(err, `exec "dpkg-query -W -f="\${binary:Package},\${db:Status-Abbrev},\${Version},\${Architecture},\${source:Package},\${source:Version}\n"`)
}
if stderr != "" {
return errors.New(stderr)
}
if status != 0 {
return errors.Errorf("exit status is %d", status)
}
ah.Host.Packages.OSPkg, err = ParseInstalledPackage(stdout)
if err != nil {
return errors.Wrap(err, "parse installed package")
}
return nil
}
func ParseInstalledPackage(stdout string) (map[string]types.Package, error) {
pkgs := map[string]types.Package{}
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
name, status, version, arch, srcName, srcVersion, err := parseDPKGQueryLine(trimmed)
if err != nil {
return nil, errors.Wrap(err, "parse dpkq query line")
}
packageStatus := status[1]
// Package status:
// n = Not-installed
// c = Config-files
// H = Half-installed
// U = Unpacked
// F = Half-configured
// W = Triggers-awaiting
// t = Triggers-pending
// i = Installed
if packageStatus != 'i' {
continue
}
pkgs[name] = types.Package{
Name: name,
Version: version,
Arch: arch,
SrcName: srcName,
SrcVersion: srcVersion,
}
}
}
return pkgs, nil
}
func parseDPKGQueryLine(line string) (string, string, string, string, string, string, error) {
ss := strings.Split(line, ",")
if len(ss) == 6 {
// remove :amd64, i386...
name, _, _ := strings.Cut(ss[0], ":")
status := strings.TrimSpace(ss[1])
if len(status) < 2 {
return "", "", "", "", "", "", errors.Errorf(`unexpected db:Status-Abbrev format. accepts: "ii", received: "%s"`, status)
}
version := ss[2]
arch := ss[3]
srcName, _, _ := strings.Cut(ss[4], " ")
srcVersion := ss[5]
return name, status, version, arch, srcName, srcVersion, nil
}
return "", "", "", "", "", "", errors.Errorf(`unexpected package line format. accepts: "<bin name>,<status>,<bin version>,<arch>,<src name>,<src version>", received: "%s"`, line)
}

114
pkg/scan/ospkg/rpm/rpm.go Normal file
View File

@@ -0,0 +1,114 @@
package rpm
import (
"bufio"
"context"
"fmt"
"strings"
"github.com/hashicorp/go-version"
"github.com/pkg/errors"
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
"github.com/future-architect/vuls/pkg/types"
)
type Analyzer struct {
}
func (a Analyzer) Name() string {
return "rpm analyzer"
}
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
status, stdout, stderr, err := ah.Host.Exec(ctx, `rpm --version`, false)
if err != nil {
return errors.Wrap(err, `exec "rpm --version"`)
}
if stderr != "" {
return errors.New(stderr)
}
if status != 0 {
return errors.Errorf("exit status is %d", status)
}
cmd := `rpm -qa --queryformat "%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH} %{VENDOR}\n"`
rpmver, err := version.NewVersion(strings.TrimPrefix(strings.TrimSpace(stdout), "RPM version "))
rpmModukaritylabel, err := version.NewVersion("4.15.0")
if err != nil {
return errors.Wrap(err, "parse rpm version for modularitylabel")
}
rpmEpochNum, err := version.NewVersion("4.8.0")
if err != nil {
return errors.Wrap(err, "parse rpm version for epochnum")
}
if rpmver.GreaterThanOrEqual(rpmModukaritylabel) {
cmd = `rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH} %{VENDOR} %{MODULARITYLABEL}\n"`
} else if rpmver.GreaterThanOrEqual(rpmEpochNum) {
cmd = `rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH} %{VENDOR}\n"`
}
status, stdout, stderr, err = ah.Host.Exec(ctx, cmd, false)
if err != nil {
return errors.Wrapf(err, `exec "%s"`, cmd)
}
if stderr != "" {
return errors.New(stderr)
}
if status != 0 {
return errors.Errorf("exit status is %d", status)
}
ah.Host.Packages.OSPkg, err = ParseInstalledPackage(stdout)
if err != nil {
return errors.Wrap(err, "parse installed package")
}
return nil
}
func ParseInstalledPackage(stdout string) (map[string]types.Package, error) {
pkgs := map[string]types.Package{}
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
name, version, release, arch, vendor, modularitylabel, err := parseRpmQaLine(trimmed)
if err != nil {
return nil, errors.Wrap(err, "parse rpm -qa line")
}
pkgs[name] = types.Package{
Name: name,
Version: version,
Release: release,
Arch: arch,
Vendor: vendor,
ModularityLabel: modularitylabel,
}
}
}
return pkgs, nil
}
func parseRpmQaLine(line string) (string, string, string, string, string, string, error) {
ss := strings.Fields(line)
if len(ss) < 6 {
return "", "", "", "", "", "", errors.Errorf(`unexpected rpm -qa line format. accepts: "<name> <epoch> <version> <release> <arch> <vendor>( <modularitylabel>)", received: "%s"`, line)
}
ver := ss[2]
epoch := ss[1]
if epoch != "0" && epoch != "(none)" {
ver = fmt.Sprintf("%s:%s", epoch, ss[2])
}
var modularitylabel string
if len(ss) == 7 {
modularitylabel = ss[5]
}
return ss[0], ver, ss[3], ss[4], ss[5], modularitylabel, nil
}

54
pkg/scan/scan.go Normal file
View File

@@ -0,0 +1,54 @@
package scan
import (
"context"
"runtime"
"time"
"github.com/pkg/errors"
"github.com/future-architect/vuls/pkg/cmd/version"
"github.com/future-architect/vuls/pkg/scan/cpe"
"github.com/future-architect/vuls/pkg/scan/os"
"github.com/future-architect/vuls/pkg/scan/systeminfo"
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
"github.com/future-architect/vuls/pkg/types"
)
func Scan(ctx context.Context, host *types.Host) error {
ah := scanTypes.AnalyzerHost{Host: host}
if ah.Host.Config.Scan.OSPkg != nil {
if runtime.GOOS == "windows" {
ah.Analyzers = append(ah.Analyzers, systeminfo.Analyzer{})
} else {
ah.Analyzers = append(ah.Analyzers, os.Analyzer{})
}
}
if len(ah.Host.Config.Scan.CPE) > 0 {
ah.Analyzers = append(ah.Analyzers, cpe.Analyzer{})
}
var (
err error
)
for {
if len(ah.Analyzers) == 0 {
break
}
a := ah.Analyzers[0]
if err = a.Analyze(ctx, &ah); err != nil {
break
}
ah.Analyzers = ah.Analyzers[1:]
}
t := time.Now()
ah.Host.ScannedAt = &t
ah.Host.ScannedVersion = version.Version
ah.Host.ScannedRevision = version.Revision
if err != nil {
return errors.Wrapf(err, "analyze %s", ah.Host.Name)
}
return nil
}

View File

@@ -0,0 +1,480 @@
package systeminfo
import (
"bufio"
"context"
"fmt"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/future-architect/vuls/pkg/scan/types"
)
type Analyzer struct {
}
func (a Analyzer) Name() string {
return "systeminfo analyzer"
}
func (a Analyzer) Analyze(ctx context.Context, ah *types.AnalyzerHost) error {
status, stdout, stderr, err := ah.Host.Exec(ctx, "systeminfo", false)
if err != nil {
return errors.Wrap(err, `exec "systeminfo"`)
}
if stderr != "" {
return errors.New(stderr)
}
if status != 0 {
return errors.Errorf("exit status is %d", status)
}
ah.Host.Family, ah.Host.Release, ah.Host.Packages.KB, err = ParseSysteminfo(stdout)
if err != nil {
return errors.Wrap(err, "parse systeminfo")
}
if ah.Host.Family == "" {
return errors.New("family is unknown")
}
if ah.Host.Release == "" {
return errors.New("release is unknown")
}
return nil
}
func ParseSysteminfo(stdout string) (string, string, []string, error) {
var (
o osInfo
kbs []string
)
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
switch {
case strings.HasPrefix(line, "OS Name:"):
o.productName = strings.TrimSpace(strings.TrimPrefix(line, "OS Name:"))
case strings.HasPrefix(line, "OS Version:"):
s := strings.TrimSpace(strings.TrimPrefix(line, "OS Version:"))
lhs, build, _ := strings.Cut(s, " Build ")
vb, sp, _ := strings.Cut(lhs, " ")
o.version = strings.TrimSuffix(vb, fmt.Sprintf(".%s", build))
o.build = build
if sp != "N/A" {
o.servicePack = sp
}
case strings.HasPrefix(line, "System Type:"):
o.arch = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "System Type:"), "PC"))
case strings.HasPrefix(line, "OS Configuration:"):
switch {
case strings.Contains(line, "Server"):
o.installationType = "Server"
case strings.Contains(line, "Workstation"):
o.installationType = "Client"
default:
return "", "", nil, errors.Errorf(`installation type not found from "%s"`, line)
}
case strings.HasPrefix(line, "Hotfix(s):"):
nKB, err := strconv.Atoi(strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "Hotfix(s):"), " Hotfix(s) Installed.")))
if err != nil {
return "", "", nil, errors.Errorf(`number of installed hotfix from "%s"`, line)
}
for i := 0; i < nKB; i++ {
scanner.Scan()
line := scanner.Text()
_, rhs, found := strings.Cut(line, ":")
if !found {
continue
}
s := strings.TrimSpace(rhs)
if strings.HasPrefix(s, "KB") {
kbs = append(kbs, strings.TrimPrefix(s, "KB"))
}
}
default:
}
}
release, err := detectOSName(o)
if err != nil {
return "", "", nil, errors.Wrap(err, "detect os name")
}
return "windows", release, kbs, nil
}
type osInfo struct {
productName string
version string
build string
edition string
servicePack string
arch string
installationType string
}
func detectOSName(osInfo osInfo) (string, error) {
osName, err := detectOSNameFromOSInfo(osInfo)
if err != nil {
return "", errors.Wrapf(err, "detect OS Name from OSInfo: %#v", osInfo)
}
return osName, nil
}
func detectOSNameFromOSInfo(osInfo osInfo) (string, error) {
switch osInfo.version {
case "5.0":
switch osInfo.installationType {
case "Client":
if osInfo.servicePack != "" {
return fmt.Sprintf("Microsoft Windows 2000 %s", osInfo.servicePack), nil
}
return "Microsoft Windows 2000", nil
case "Server":
if osInfo.servicePack != "" {
return fmt.Sprintf("Microsoft Windows 2000 Server %s", osInfo.servicePack), nil
}
return "Microsoft Windows 2000 Server", nil
}
case "5.1":
switch osInfo.installationType {
case "Client":
var n string
switch osInfo.edition {
case "Professional":
n = "Microsoft Windows XP Professional"
case "Media Center":
n = "Microsoft Windows XP Media Center Edition 2005"
case "Tablet PC":
n = "Microsoft Windows XP Tablet PC Edition 2005"
default:
n = "Microsoft Windows XP"
}
switch osInfo.arch {
case "x64":
n = fmt.Sprintf("%s x64 Edition", n)
}
if osInfo.servicePack != "" {
return fmt.Sprintf("%s %s", n, osInfo.servicePack), nil
}
return n, nil
}
case "5.2":
switch osInfo.installationType {
case "Client":
var n string
switch osInfo.edition {
case "Professional":
n = "Microsoft Windows XP Professional"
case "Media Center":
n = "Microsoft Windows XP Media Center Edition 2005"
case "Tablet PC":
n = "Microsoft Windows XP Tablet PC Edition 2005"
default:
n = "Microsoft Windows XP"
}
switch osInfo.arch {
case "x64":
n = fmt.Sprintf("%s x64 Edition", n)
}
if osInfo.servicePack != "" {
return fmt.Sprintf("%s %s", n, osInfo.servicePack), nil
}
return n, nil
case "Server":
n := "Microsoft Windows Server 2003"
if strings.Contains(osInfo.productName, "R2") {
n = "Microsoft Windows Server 2003 R2"
}
switch osInfo.arch {
case "x64":
n = fmt.Sprintf("%s x64 Edition", n)
case "IA64":
if osInfo.edition == "Enterprise" {
n = fmt.Sprintf("%s, Enterprise Edition for Itanium-based Systems", n)
} else {
n = fmt.Sprintf("%s for Itanium-based Systems", n)
}
}
if osInfo.servicePack != "" {
return fmt.Sprintf("%s %s", n, osInfo.servicePack), nil
}
return n, nil
}
case "6.0":
switch osInfo.installationType {
case "Client":
var n string
switch osInfo.arch {
case "x64":
n = "Windows Vista x64 Editions"
default:
n = "Windows Vista"
}
if osInfo.servicePack != "" {
return fmt.Sprintf("%s %s", n, osInfo.servicePack), nil
}
return n, nil
case "Server":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
if osInfo.servicePack != "" {
return fmt.Sprintf("Windows Server 2008 for %s Systems %s", arch, osInfo.servicePack), nil
}
return fmt.Sprintf("Windows Server 2008 for %s Systems", arch), nil
case "Server Core":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
if osInfo.servicePack != "" {
return fmt.Sprintf("Windows Server 2008 for %s Systems %s (Server Core installation)", arch, osInfo.servicePack), nil
}
return fmt.Sprintf("Windows Server 2008 for %s Systems (Server Core installation)", arch), nil
}
case "6.1":
switch osInfo.installationType {
case "Client":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
if osInfo.servicePack != "" {
return fmt.Sprintf("Windows 7 for %s Systems %s", arch, osInfo.servicePack), nil
}
return fmt.Sprintf("Windows 7 for %s Systems", arch), nil
case "Server":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
if osInfo.servicePack != "" {
return fmt.Sprintf("Windows Server 2008 R2 for %s Systems %s", arch, osInfo.servicePack), nil
}
return fmt.Sprintf("Windows Server 2008 R2 for %s Systems", arch), nil
case "Server Core":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
if osInfo.servicePack != "" {
return fmt.Sprintf("Windows Server 2008 R2 for %s Systems %s (Server Core installation)", arch, osInfo.servicePack), nil
}
return fmt.Sprintf("Windows Server 2008 R2 for %s Systems (Server Core installation)", arch), nil
}
case "6.2":
switch osInfo.installationType {
case "Client":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
return fmt.Sprintf("Windows 8 for %s Systems", arch), nil
case "Server":
return "Windows Server 2012", nil
case "Server Core":
return "Windows Server 2012 (Server Core installation)", nil
}
case "6.3":
switch osInfo.installationType {
case "Client":
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
return fmt.Sprintf("Windows 8.1 for %s Systems", arch), nil
case "Server":
return "Windows Server 2012 R2", nil
case "Server Core":
return "Windows Server 2012 R2 (Server Core installation)", nil
}
case "10.0":
switch osInfo.installationType {
case "Client":
if strings.Contains(osInfo.productName, "Windows 10") {
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
name, err := formatNamebyBuild("10", osInfo.build)
if err != nil {
return "", err
}
return fmt.Sprintf("%s for %s Systems", name, arch), nil
}
if strings.Contains(osInfo.productName, "Windows 11") {
arch, err := formatArch(osInfo.arch)
if err != nil {
return "", err
}
name, err := formatNamebyBuild("11", osInfo.build)
if err != nil {
return "", err
}
return fmt.Sprintf("%s for %s Systems", name, arch), nil
}
case "Server":
return formatNamebyBuild("Server", osInfo.build)
case "Server Core":
name, err := formatNamebyBuild("Server", osInfo.build)
if err != nil {
return "", err
}
return fmt.Sprintf("%s (Server Core installation)", name), nil
}
}
return "", errors.New("OS Name not found")
}
func formatArch(arch string) (string, error) {
switch arch {
case "x64-based":
return "x64-based", nil
case "ARM64-based":
return "ARM64-based", nil
case "Itanium-based":
return "Itanium-based", nil
case "X86-based":
return "32-bit", nil
default:
return "", errors.New("CPU Architecture not found")
}
}
type buildNumber struct {
build string
name string
}
var (
winBuilds = map[string][]buildNumber{
"10": {
{
build: "10240",
name: "Windows 10", // not "Windows 10 Version 1507"
},
{
build: "10586",
name: "Windows 10 Version 1511",
},
{
build: "14393",
name: "Windows 10 Version 1607",
},
{
build: "15063",
name: "Windows 10 Version 1703",
},
{
build: "16299",
name: "Windows 10 Version 1709",
},
{
build: "17134",
name: "Windows 10 Version 1803",
},
{
build: "17763",
name: "Windows 10 Version 1809",
},
{
build: "18362",
name: "Windows 10 Version 1903",
},
{
build: "18363",
name: "Windows 10 Version 1909",
},
{
build: "19041",
name: "Windows 10 Version 2004",
},
{
build: "19042",
name: "Windows 10 Version 20H2",
},
{
build: "19043",
name: "Windows 10 Version 21H1",
},
{
build: "19044",
name: "Windows 10 Version 21H2",
},
// It seems that there are cases where the Product Name is Windows 10 even though it is Windows 11
// ref: https://docs.microsoft.com/en-us/answers/questions/586548/in-the-official-version-of-windows-11-why-the-key.html
{
build: "22000",
name: "Windows 11",
},
},
"11": {
{
build: "22000",
name: "Windows 11", // not "Windows 11 Version 21H2"
},
},
"Server": {
{
build: "14393",
name: "Windows Server 2016",
},
{
build: "16299",
name: "Windows Server, Version 1709",
},
{
build: "17134",
name: "Windows Server, Version 1809",
},
{
build: "17763",
name: "Windows Server 2019",
},
{
build: "18362",
name: "Windows Server, Version 1903",
},
{
build: "18363",
name: "Windows Server, Version 1909",
},
{
build: "19041",
name: "Windows Server, Version 2004",
},
{
build: "19042",
name: "Windows Server, Version 20H2",
},
{
build: "20348",
name: "Windows Server 2022",
},
},
}
)
func formatNamebyBuild(osType string, mybuild string) (string, error) {
builds, ok := winBuilds[osType]
if !ok {
return "", errors.New("OS Type not found")
}
v := builds[0].name
for _, b := range builds {
if mybuild == b.build {
return b.name, nil
}
if mybuild < b.build {
break
}
v = b.name
}
return v, nil
}

17
pkg/scan/types/types.go Normal file
View File

@@ -0,0 +1,17 @@
package types
import (
"context"
"github.com/future-architect/vuls/pkg/types"
)
type Analyzer interface {
Name() string
Analyze(context.Context, *AnalyzerHost) error
}
type AnalyzerHost struct {
Host *types.Host
Analyzers []Analyzer
}