Search code examples
gowinapi

How to get Windows Security Information?


I'm trying to get the information about the windows security like farewall,antispyware with Golang. Here is an example how it's done with cpp from microsoft. I'm trying to do the same with Golang. using go-ole package or just plain syscalls. I've had no luck with syscalls. with go-ole I have the following code

func main() {
    if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED); err != nil {
        log.Fatal("CoInitialize failed:", err)
    }
    defer ole.CoUninitialize()

    wscProductListID := ole.NewGUID("{17072F7B-9ABE-4A74-A261-1EB76B55107A}")
    iwscProductListID := ole.NewGUID("{722A338C-6E8E-4E72-AC27-1417FB0C81C2}")
    unknown, err := ole.CreateInstance(wscProductListID, iwscProductListID)
    if err != nil {
        log.Fatal("CreateInstance failed:", err)
    }
    defer unknown.Release()

    wscProductList, err := unknown.QueryInterface(ole.NewGUID("{722A338C-6E8E-4E72-AC27-1417FB0C81C2}"))
    if err != nil {
        log.Fatal("QueryInterface failed:", err)
    }
    defer wscProductList.Release()
    
    _, err = wscProductList.CallMethod("Initialize", 1)
    if err != nil { // getting error here - library not found
        fmt.Println(err)
    }
}

library not found error is very strange because running the cpp code works fine.

Any ideas what goes wrong? How to retrieve the information that is retrieved in the cpp code?


Solution

  • I've confirmed that I can produce this result code (0x8002801d, or TYPE_E_LIBNOTREGISTERED) in C++ by calling GetIDsOfNames directly on a WSCProductList, so it doesn't seem like it's an issue inherent to go-ole.

    Calling GetIDsOfNames ends up in wscapi!ATL::CComTypeInfoHolder::GetIDsOfNames, which calls wscapi!ATL::CComTypeInfoHolder::GetTI, which calls oleaut32!LoadRegTypeLib, looking for type library {B52A4496-7753-4F74-BE64-C2072E308122} with a version of 2.0. In my registry (Win11 24H2), however, the type library only offers version 1.0.

    I initially thought that Microsoft may have updated the type library against which wscapi.dll was built to version 2.0 and neglected to register it, but extracting the type library from the .rsrc section of wscapi.dll appears to result in the exact same type library as the one registered in the registry, so that theory doesn't appear to hold water. I am still unsure of why version 2.0 of the type library is requested.

    For fun, I used WinDbg to dork the call to oleaut32!LoadRegTypeLib, manually setting the major and minor versions (rdx and r8, respectively) to 0xFFFF, which, as suggested here, should force the type library inside the .dll to be used instead of the registry. And what do you know, it worked!

    Moral of the story: I'm fairly comfortable concluding that this appears to be a bug in wscapi.dll. Whether the core bug is that it's requesting entirely the wrong type library version or that there is a version 2.0 that remains unpublished, I am not sure.