Ido-Moshe-Github / CiDllDemo

Use ci.dll API for validating Authenticode signature of files
MIT License
130 stars 57 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 7 months ago

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

dretax commented 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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 5 months 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

dretax commented 3 months 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.

Wrong, that's the whole point. Testmode is giving you delusions, the function does not work properly without testmode enabled. @nefarius and I discussed this in the past. I stumbled upon making the same mistake before, basically in test mode it worked flawless, but fails without It any time.

dretax commented 2 months ago

@ByteWhite1x1 I've contacted you through your website, let's test the CiCheckSignedFile with my cert if you have the time.

nefarius commented 2 months ago

Keep us plebs in the loop top pls 😝

ByteWhite1x1 commented 1 month ago

@ByteWhite1x1 I've contacted you through your website, let's test the CiCheckSignedFile with my cert if you have the time.

Hi. Sorry for the delay. I've been really busy and have had breaks. I've just tested your executable discussed in this post https://github.com/Ido-Moshe-Github/CiDllDemo/issues/5#issuecomment-2150424997 on bare metal with the CiCheckSignedFile and it worked just fine with your executable.

Windows 10 Pro 22H2 Build: 19045.4291

\Device\HarddiskVolume3\temp3\nefconc.exe
00000089 0.03783230 [+] CiCheckSignedFileWrapper
00000090 0.03832940 [+] CiCheckSignedFile returned 0x00000000 (the signature is valid)

"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe" verify /pa /all C:\temp3\nefconc.exe

Here is a screenshot proof: https://i.imgur.com/qZAEnhM.png

I currently have no time for more tests. CiCheckSignedFile works just fine for me also on the latest Windows 11 versions >= 22H2. Test signing was disabled. I used my DSE bypass to get the anti-malware driver loaded. Sorry for the grey hat method but it was the only way to test it.

Steps as follows:

1) GetDigestAlgorithm 2) ComputeAuthenticodeHash 3) CiCheckSignedFile

It required a great deal of effort to get all (3) steps working in a kernel driver. I can provide the source code for all (3) steps as a software work.