Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ require (
)

require (
bou.ke/monkey v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/saferwall/pe v1.4.4 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
golang.org/x/text v0.11.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
19 changes: 19 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI=
bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA=
github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a h1:4c0nc0krv8eh7gD809n+swLaCuFyHpxdrxwx0ZmHvBw=
github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/saferwall/pe v1.4.4 h1:Ml++7/2/Z1iKwV4zCsd1nIqTEAdUQKAetwbbcCarhOg=
github.com/saferwall/pe v1.4.4/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
Expand Down Expand Up @@ -35,3 +50,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
160 changes: 160 additions & 0 deletions internal/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package pkg_test

import (
"fmt"
pkg "loldriverscan/internal"
"net/http"
"testing"

"github.com/stretchr/testify/assert"
)

// For testing purposes
type testlolDrivers struct {
md5Map map[string]string
sha1Map map[string]string
sha256Map map[string]string

authentihashMd5Map map[string]string
authentihashSha1Map map[string]string
authentihashSha256Map map[string]string

lolDriverMap map[string]pkg.LolDriver
}

// For testing purposes
func mockfectchNormaliseData() ([]pkg.LolDriver, error) {
testdrivers := []pkg.LolDriver{
{
ID: "driver-1",
Filename: "driver1.exe",
Path: "/sample/path/to/driver",
Status: "active",
Malicious: false,
MD5: "md5-hash",
Sha1: "sha1-hash",
Sha256: "sha256-hash",
CVEs: []string{"CVE-2021-1111", "CVE-2021-2222"},
Authentihash: pkg.Authentihash{MD5: "auth-md5-1"},
},
}
return testdrivers, nil

}

// For testing purposes
func (tes *testlolDrivers) mockFindDriver(h pkg.Hashes, auth pkg.Authentihash) (pkg.LolDriver, error) {
id, ok := tes.authentihashMd5Map[auth.MD5]
if !ok {
id, ok = tes.authentihashSha1Map[auth.Sha1]
if !ok {
id, ok = tes.authentihashSha256Map[auth.Sha256]
if !ok {
// No matching driver found
return pkg.LolDriver{}, fmt.Errorf("no matching driver")
}
}
}

// Found a matching driver ID, get the corresponding LolDriver object
lolDriver := tes.lolDriverMap[id]

// Update the fields of the LolDriver object with the provided hashes
lolDriver.MD5 = h.Md5
lolDriver.Sha1 = h.Sha1
lolDriver.Sha256 = h.Sha256

// Update the fields of the Authentihash object
lolDriver.Authentihash.MD5 = auth.MD5
lolDriver.Authentihash.Sha1 = auth.Sha1
lolDriver.Authentihash.Sha256 = auth.Sha256

// Return the updated LolDriver object
return lolDriver, nil
}

func TestDrivers(t *testing.T) {
lolDriversApiUrl := `https://www.loldrivers.io/api/drivers.json`

// Check if the the response status returned is 200 OK
res, err := http.Get(lolDriversApiUrl)
if err != nil {
t.Fatalf("Unable to make driver requestd: %v", err)
}

if res.StatusCode != http.StatusOK {
t.Errorf("Expected status code to be %v but got %v", http.StatusOK, res.StatusCode)
}
}

func TestFetchApiNormaliseData(t *testing.T) {
sampledriver, err := mockfectchNormaliseData() // Mocking HTTP Get request
if err != nil {
t.Fail() // Will not occur
}

assert.NotEmpty(t, sampledriver, "Driver list must not be empty")
assert.Equal(t, sampledriver[0].ID, "driver-1")
}

func TestFindDriver(t *testing.T) {

//For test
testlolDrivers := testlolDrivers{
authentihashMd5Map: map[string]string{
"authMd5": "testdriver-1",
"authMD5hash": "testdriver-7",
},
authentihashSha1Map: map[string]string{"authSha1": "testdriver-2"},
authentihashSha256Map: map[string]string{"authSha256": "testdriver-3"},
sha1Map: map[string]string{"hashSha1": "testdriver-4"},
sha256Map: map[string]string{"hashSha256": "testdriver-5"},
md5Map: map[string]string{"hashMd5": "testdriver-6"},
lolDriverMap: map[string]pkg.LolDriver{
"testdriver-1": {ID: "testdriver-1", Authentihash: pkg.Authentihash{MD5: "authMD5hash"}},
"testdriver-2": {ID: "testdriver-2", Authentihash: pkg.Authentihash{Sha1: "authSha1hash"}},
"testdriver-3": {ID: "testdriver-3", Authentihash: pkg.Authentihash{Sha256: "authSha256"}},
"testdriver-4": {ID: "testdriver-4"},
"testdriver-5": {ID: "testdriver-5"},
"testdriver-6": {ID: "testdriver-6"},
},
}

// Case 1.1:
t.Run("No matching drivers found [INVALID HASH]", func(t *testing.T) {
_, err := testlolDrivers.mockFindDriver(pkg.Hashes{Md5: "testdriver-1"}, pkg.Authentihash{MD5: "authMD5HASH"})
if err == nil {
t.Errorf("Expected error, got nil error")
}
})

// Case 1.2:
t.Run("No matching drivers found [INVALID DRIVER]", func(t *testing.T) {
_, err := testlolDrivers.mockFindDriver(pkg.Hashes{Md5: "testdriver-2"}, pkg.Authentihash{Sha256: "hashSha256"})
if err == nil {
t.Errorf("Expected error, got nil error")
}
})

// Case 2:
t.Run("Valid drivers found", func(t *testing.T) {
foundDriver, err := testlolDrivers.mockFindDriver(pkg.Hashes{Md5: "testdriver-1"}, pkg.Authentihash{MD5: "authMd5"})
if err != nil {
t.Errorf("Expected nil error, got error")
}
assert.Equal(t, foundDriver.Authentihash.MD5, "authMd5")
assert.Equal(t, foundDriver.MD5, "testdriver-1")
})

}

func TestCreateVulnerableDriverFinder(t *testing.T) {
// Call the function
drivers, err := pkg.CreateVulnerableDriverFinder()
if err != nil {
t.Error("Expected nil error, got error")
}

assert.NotEmpty(t, drivers, "Expected drivers to have values")
assert.NotNil(t, drivers, "Expected drivers to not be nil")
}
113 changes: 113 additions & 0 deletions internal/drivers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package pkg_test

import (
"errors"
"fmt"
pkg "loldriverscan/internal"
"testing"

"bou.ke/monkey"
"github.com/stretchr/testify/assert"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc/mgr"
)

func TestConnectToServiceManager(t *testing.T) {
mockWinHandle := windows.Handle(123)

t.Run("ConnectToServiceManager without error", func(t *testing.T) {
// Monkey patching to mock implementation of windows.OpenSCmanager
patch := monkey.Patch(windows.OpenSCManager, func(host *uint16, database *uint16, access uint32) (windows.Handle, error) {
return mockWinHandle, nil
})

defer patch.Unpatch()

mgr, err := pkg.ConnectToServiceManager()
if err != nil {
t.Error("Could not connect to service manager")
}
assert.NoError(t, err, "Unexpected error")
assert.NotNil(t, mgr, "Manager is nil")
assert.Equalf(t, mockWinHandle, mgr.Handle, "Unexpected handle value: Expected %v, got %v", mockWinHandle, mgr.Handle)

})

t.Run("ConnectToServiceManager error", func(t *testing.T) {
mockwinError := windows.ERROR_ACCOUNT_RESTRICTION // Make it throws some error
patch := monkey.Patch(windows.OpenSCManager, func(host *uint16, database *uint16, access uint32) (windows.Handle, error) {
return mockWinHandle, mockwinError
})

defer patch.Unpatch()

_, err := pkg.ConnectToServiceManager()
assert.Error(t, mockwinError, err)
assert.ErrorContainsf(t, err, "Account restrictions", "Expected error message %v, got %v", "Account restrictions", err)

})
}

func TestListDriverServices(t *testing.T) {

// Case 1: passing an invalid Mgr
t.Run("Invalid Mgr", func(t *testing.T) {
_, err := pkg.ListDriverServices(&mgr.Mgr{})
assert.ErrorContains(t, err, "handle is invalid")
})

t.Run("Passing a valid service manager", func(t *testing.T) {

patchListDriverService := monkey.Patch(pkg.ListDriverServices, func(m *mgr.Mgr) ([]string, error) {
if m.Handle == 123 {
return []string{"Sample service 1"}, nil
} else if m.Handle > 400 {
return []string{"Sample service 2"}, nil
} else {
return nil, fmt.Errorf("Invalid service manager handle")
}

})
defer patchListDriverService.Unpatch()

res, err := pkg.ListDriverServices(&mgr.Mgr{Handle: 123})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}

assert.Containsf(t, res, "Sample service 1", "Expected service %v , got %v", "Sample service 1", res)

})

}

func TestOpenService(t *testing.T) {
OpenServicePatch := monkey.Patch(windows.OpenService, func(m windows.Handle, servicename *uint16, access uint32) (handle windows.Handle, err error) {
if m == 12345 {
return windows.Handle(12345), nil
} else {
return 0, fmt.Errorf("Invalid service Handle")
}

})

defer OpenServicePatch.Unpatch()

t.Run("Proper Service Openec", func(t *testing.T) {
mockOpenService, err := pkg.OpenService(&mgr.Mgr{Handle: 12345}, "Sample new service")
if err != nil {
t.Errorf("Unexpected error opening Handle %v", err)
}

assert.Equalf(t, "Sample new service", mockOpenService.Name, "Expected service name %v but got %v:", "Sample new service", mockOpenService.Name)
assert.EqualValues(t, uintptr(12345), mockOpenService.Handle)
})

t.Run("Error new opening service", func(t *testing.T) {
mockOpenService, err := pkg.OpenService(&mgr.Mgr{Handle: 121}, "Sample new service 2")
if assert.Error(t, err) {
assert.Equal(t, errors.New("Invalid service Handle"), err)
}
assert.Nil(t, mockOpenService)
})
}
Loading