Ido-Moshe-Github / CiDllDemo

Use ci.dll API for validating Authenticode signature of files
MIT License
120 stars 56 forks source link

Inconsistencies in working with Authenticode signed executables #5

Open nefarius opened 1 year ago

nefarius commented 1 year ago

First of all, thank you very much for this publication!

I couldn't resist playing around with it but I found some inconsistencies/issues/side-effects when using CiValidateFileObject against a custom executable signed with a DigiCert Authenticode certificate:

Issuer

CN = DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1
O = DigiCert, Inc.
C = US

Verification

signtool verify appears to be happy:

signtool verify /pa test.exe
File: test.exe
Index  Algorithm  Timestamp
========================================
0      sha1       Authenticode

Successfully verified: test.exe

Test results

Depending on the following OS versions and TESTSIGNING states I got the following results:

OS TESTSIGNING Result
Windows 11 22H2 ON works, can parse various certificate and publisher details
Windows 11 22H2 OFF fails with ERROR:policy info is empty
Windows 10 22H2 ON works, can parse various certificate and publisher details
Windows 10 22H2 OFF fails with STATUS_INVALID_IMAGE_HASH

Anybody seen something similar? Is this function supposed to work with any Authenticode signed file or only on those with the Microsoft "secret sauce" trusted certificate chains?

Thanks & cheers

EDIT: to clarify; I am assuming this function is supposed to work with non-Microsoft-magic files as well, if this assumption is wrong, please rectify it for me.

nefarius commented 1 year ago

@MiroKaku pardon the ping, thought this might interest you as well 😬

ByteWhite1x1 commented 2 months ago

. . . I opened a new issue. As I originally intended.

dretax commented 1 month ago

@nefarius I've seen your other project where you use the related code in some ways. Did you manage to resolve this issue? Globalsign is returning STATUS_INVALID_IMAGE_HASH without testsigning indeed for 19045

nefarius commented 1 month ago

@nefarius I've seen your other project where you use the related code in some ways. Did you manage to resolve this issue? Globalsign is returning STATUS_INVALID_IMAGE_HASH without testsigning indeed for 19045

In my particular case the issue was the certificate used. I originally had used an ECC certificate from DigiCert and after a bit of back and forth with their support (who surprisingly quite quickly figured out the issue, props there) I got a new RSA based one which worked. So it still works for purposes outside of the Microsoft certificate ecosystem, however the compatibility matrix if you will is quite narrow.

EDIT: I just realized that my initial post already mentioned testing with RSA4096 SHA384, hm... Guess I need to dig deeper in my memory what else changed 🤔

dretax commented 1 month ago

@nefarius I've seen your other project where you use the related code in some ways. Did you manage to resolve this issue? Globalsign is returning STATUS_INVALID_IMAGE_HASH without testsigning indeed for 19045

In my particular case the issue was the certificate used. I originally had used an ECC certificate from DigiCert and after a bit of back and forth with their support (who surprisingly quite quickly figured out the issue, props there) I got a new RSA based one which worked. So it still works for purposes outside of the Microsoft certificate ecosystem, however the compatibility matrix if you will is quite narrow.

EDIT: I just realized that my initial post already mentioned testing with RSA4096 SHA384, hm... Guess I need to dig deeper in my memory what else changed 🤔

Buggers, let me know, I'd really appreciate some insight on this one

nefarius commented 1 month ago

@nefarius I've seen your other project where you use the related code in some ways. Did you manage to resolve this issue? Globalsign is returning STATUS_INVALID_IMAGE_HASH without testsigning indeed for 19045

In my particular case the issue was the certificate used. I originally had used an ECC certificate from DigiCert and after a bit of back and forth with their support (who surprisingly quite quickly figured out the issue, props there) I got a new RSA based one which worked. So it still works for purposes outside of the Microsoft certificate ecosystem, however the compatibility matrix if you will is quite narrow. EDIT: I just realized that my initial post already mentioned testing with RSA4096 SHA384, hm... Guess I need to dig deeper in my memory what else changed 🤔

Buggers, let me know, I'd really appreciate some insight on this one

It definitely had something to do with the way the executable was signed, the validation code was fine, I remember that much.

nefarius commented 1 month ago

I remember now; I ended up abandoning the use of CiValidateFileObject because I couldn't figure it out 😢 So for now it will remain in the realms of Windows mysteries I'm afraid.

ByteWhite1x1 commented 1 month ago

I remember now; I ended up abandoning the use of CiValidateFileObject because I couldn't figure it out 😢 So for now it will remain in the realms of Windows mysteries I'm afraid.

Is your Digicert an EV one? Can you provide your test.exe that's signed with your certificate so I can test. CiValidateFileObject works for me in the kernel (Windows 11 22H3).

nefarius commented 4 weeks ago

I remember now; I ended up abandoning the use of CiValidateFileObject because I couldn't figure it out 😢 So for now it will remain in the realms of Windows mysteries I'm afraid.

Is your Digicert an EV one? Can you provide your test.exe that's signed with your certificate so I can test. CiValidateFileObject works for me in the kernel (Windows 11 22H3).

Yes, EV from DigiCert. Can provide you one later. What about Windows 10 22h2?

nefarius commented 4 weeks ago

@ByteWhite1x1 alrighty, here you go nefconc.zip this is the way it was signed:

signtool sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /n "Nefarius Software Solutions e.U." .\nefconc.exe

Same way I sign all my public releases pretty much. Sources of the binary I attached can be found here.

ByteWhite1x1 commented 3 weeks ago

[+] ComputeAuthenticodeHash \Device\HarddiskVolume3\temp3\nefconc.exe [+] ValidateCertificate \Device\HarddiskVolume3\temp3\nefconc.exe [+] CiCheckSignedFile returned 0x00000000

[+] CiValidateFileObject returned 0x00000000 \temp3\nefconc.exe

Your file validates using the both undocumented API's. The function is the same on Win10 22H2; there is no reason why it would not work.

nefarius commented 3 weeks ago

[+] ComputeAuthenticodeHash \Device\HarddiskVolume3\temp3\nefconc.exe [+] ValidateCertificate \Device\HarddiskVolume3\temp3\nefconc.exe [+] CiCheckSignedFile returned 0x00000000

[+] CiValidateFileObject returned 0x00000000 \temp3\nefconc.exe

Your file validates using the both undocumented API's. The function is the same on Win10 22H2; there is no reason why it would not work.

OK but have you tested it on 10 22H2 as well? I explicitly mentioned it because it failed my test.

It's been a while so I might just re-run it myself, maybe something wasn't done correctly in testing or in recording the results.

ByteWhite1x1 commented 3 weeks ago

Hi.

[+] Windows 10 Build: 19045 (22H2) [+] ComputeAuthenticodeHash \Device\HarddiskVolume3\temp3\nefconc.exe [+] ValidateCertificate \Device\HarddiskVolume3\temp3\nefconc.exe [+] CiCheckSignedFile returned 0x00000000 (OK)

The output is from my anti-malware driver. Is your EV certificate something that can also be used to sign a kernel driver?

nefarius commented 3 weeks ago

Thanks for confirming, maybe my testing was faulty, it's been a while. Maybe the fault was even in resolving the executable path incorrectly, I need to go back to that code and make sure.

Yes, my EV cert could in theory cross sign kernel binaries, if we were still in the past where that was a thing.

ByteWhite1x1 commented 3 weeks ago

I use the CiCheckSignedFile in my project https://hexderef.com/anti-malware-with-memory-forensics because it works also with DLL's. As soon as I find time. I'll also test Windows server 2022.

I'll also need an EV (or someone legitimate with one) to sign my kernel driver. But for now test mode does the job.

nefarius commented 3 weeks ago

Well, an EV cert no longer does you any good since cross signing certificates all have expired and the most used recent Windows 10 and 11 kernels do not load EV-signed binaries, they accept Microsoft attestation signed binaries you submitted to the Microsoft Partner Portal using your EV as a token of authenticity that the binaries you submitted actually came from the holder of the EV. The EV alone has no power anymore other than being an ID badge. This gets more complicated on older OS's ofc. but those are no longer relevant in the grand scheme of production releases.

nefarius commented 3 weeks ago

I use the CiCheckSignedFile in my project https://hexderef.com/anti-malware-with-memory-forensics because it works also with DLL's. As soon as I find time. I'll also test Windows server 2022.

I found the code associated with the original issue, if you want to have a look, maybe you see something obvious: https://gist.github.com/nefarius/eaa6a0881036cc46626b2824f12f9a00