Blog Post

When Developers Give Up - DeleteSecurityPackage Function

Why it pays off to look into some Win32 functions with a disassembler.

When Developers Give Up - DeleteSecurityPackage Function - Why it pays off to look into some Win32 functions with a disassembler.

Intro

While working on my Windows authentication package, I needed a way to unload and to unregister it. Registering it was quite easy, using the AddSecurityPackage function. So logically, I assumed that DeleteSecurityPackage would be the function to call to unregister it.

The function declaration was also very simple:

C++
SECURITY_STATUS SEC_ENTRY DeleteSecurityPackageW(
  [in] LPWSTR pszPackageName
);

But to my chagrin, no matter what I called that function with, it kept returning the same result, 0x80090302.

I tried everything: I attempted to provide the pszPackageName as the full path to my authentication package DLL, it didn't work. I then tried to remove file extension, it didn't work. I tried to use only file name, with the same bad result. I then even tried to add additional privileges to the process, and to adjust the security descriptor. But none of it worked.

Solution

Eventually I gave up, and decided to do what I always do when I don't understand how something works - I reverse engineered it.

And to my amazement I saw this:

gpedit.msc
Disassembler view of the sspicli!DeleteSecurityPackageW function in Ghidra.

That showed me this Assembly code:

x86-64
DeleteSecurityPackageW PROC

mov    eax, 080090302h
ret

DeleteSecurityPackageW ENDP

Which translated into the following C++ implementation:

C++
SECURITY_STATUS DeleteSecurityPackageW(LPWSTR)
{
	return SEC_E_UNSUPPORTED_FUNCTION;
}  

😂😂😊

It literally seems like someone at Microsoft had a job to implement that function and just gave up trying at the very outset.

What is also quite amazing is that they have a documentation for that function, that reads:

Deletes a security support provider from the list of providers supported by Microsoft Negotiate.
...

Return value

If the function succeeds, it returns SEC_E_OK.
If the function fails, it returns a nonzero error code.
- MSDN

I wonder at what condition can it succeed? 🤣

Conclusion

So don't be afraid to roll up your sleeves and dig inside the implementation code. You never know what you may find there. And sometimes it may even save you hours, trying to come up with fancy ways to fix something, when in reality the reasons it doesn't work are quite obvious.

Related Articles