Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin for IDA 8+ #124

Open
naim94a opened this issue Dec 25, 2023 · 5 comments
Open

Plugin for IDA 8+ #124

naim94a opened this issue Dec 25, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@naim94a
Copy link
Owner

naim94a commented Dec 25, 2023

It seems that some users are having trouble connecting to unofficial lumina servers with TLS enabled. It seems that the current workarounds aren't simple enough.

We should have a plugin that securely connects to any lumen instance by approving preset certificates in addition to the builtin ones.

@naim94a naim94a added the enhancement New feature or request label Dec 25, 2023
@ElonGaties
Copy link

As of IDA 1.8 you can have private Lumina servers up, of which you can just configure a connection to in IDA Options. IDA does not allow connection to a private server without credentials (for some reason) - patching it out causes a trusted cert issue. Apparently these instances also require a trusted certificate.

@naim94a
Copy link
Owner Author

naim94a commented Jan 22, 2024

Yes, that's why I would like to create an open source plugin for this (or use this one #117 (comment)).
FYI, if TLS isn't required - you can set the LUMINA_TLS environment variable and connect without TLS.

@Hopfengetraenk
Copy link

Hopfengetraenk commented Mar 12, 2024

Okay, I guess found what is

The problem with the Lumina Servers Certificate.

So lumina.hex-rays.com:443 vs lumen.abda.nl:1235

I decompiled ida64.dll to of IDA Pro 8.3 to fix that stupid "invalid_remote_certificate" error.
And found this:
image
That is the only part where the flow of execution takes the 'wrong' path.
On lumen TrustStatus_dwErrorStatus is 0x20-CERT_TRUST_IS_UNTRUSTED_ROOT while
on lumina it is 0x10000 CERT_TRUST_IS_PARTIAL_CHAIN ) which is a requirement to be accepted by the IDA-client.

So it needs to have a broken chain:
image

Check the sites yourself:
https://sslshopper.com/ssl-checker.html#hostname=lumina.hex-rays.com:443
vs
https://sslshopper.com/ssl-checker.html#hostname=http://lumen.abda.nl:1235/

Here is the entire function:

bool IDA_CheckCert(struct_IdaCert *aCert)
{

 if ( aCert->CerErrCode =  QueryContextAttributesA(&aCert->sechandle78, 0x53u, &pBuffer) ) {
   aCert->CerErrText = "QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT)";
   return 0;
 }
 memset(&pChainPara, 0, sizeof(pChainPara));  pChainPara.cbSize = 32;
 
 
 // First time CertificateChain
 if ( !CertGetCertificateChain(0i64, pBuffer, 0i64, pBuffer->hCertStore, &pChainPara, 0, 0i64, &pChainContext) ) {
   aCert->CerErrText = "CertGetCertificateChain[1]"; aCert->CerErrCode = GetLastError();
   return 0;
 }
 TrustStatus_dwErrorStatus = pChainContext->TrustStatus.dwErrorStatus;     CertFreeCertificateChain(pChainContext);
 
 if ( (TrustStatus_dwErrorStatus & 1) != 0 ) { // =0x1 -> CERT_TRUST_IS_NOT_TIME_VALID 
   aCert->CerErrText = "expired_remote_certificate";
   return 0;
 }
 
// Problem the lumina servers certificate must have the error of an broken certificate chain to be 'genuine' 
// https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_trust_status
 if ( TrustStatus_dwErrorStatus != CERT_TRUST_IS_PARTIAL_CHAIN ) { //= 0x10000 The certificate chain is not complete.
       aCert->CerErrText = "invalid_remote_certificate";
   return 0;
 }
 if ( !CertAddEncodedCertificateToStore(pBuffer->hCertStore, 1u, aCert->pbCertEncoded, aCert->cbCertEncoded, 2u, 0i64) ) {
   aCert->CerErrText = "CertAddEncodedCertificateToStore";  aCert->CerErrCode = GetLastError();
   return 0;
 }
 

 // Second time CertificateChain  
 if ( !CertGetCertificateChain(0i64, pBuffer, 0i64, pBuffer->hCertStore, &pChainPara, 0, 0i64, &pChainContext) ) {
   aCert->CerErrText = "CertGetCertificateChain[2]";   aCert->CerErrCode = GetLastError();
   return 0;
 }
 TrustStatus_dwErrorStatus = pChainContext->TrustStatus.dwErrorStatus;  CertFreeCertificateChain(pChainContext);
 
 // lumina server cert chain must NOT end in a root certificate
 // If lumen.abda.nl Cert is in Root Trust ; TrustStatus_dwErrorStatus gets 0x0 (CERT_TRUST_NO_ERROR) 
 if ( TrustStatus_dwErrorStatus != CERT_TRUST_IS_UNTRUSTED_ROOT ) { // = 0x20 The certificate or certificate chain is based on an untrusted root.
   aCert->CerErrText = "invalid_remote_certificate";
   return 0;
 }
 if ( CertVerifyTimeValidity(0i64, pBuffer->pCertInfo) ) {
   aCert->CerErrText = "expired_remote_certificate"; CertFreeCertificateContext(pBuffer);
   return 0;
 }
 else if ( CertGetNameStringA(pBuffer, 3u, 0, "2.5.4.3", pszNameString, 0x400u) <= 1
        || !strcmp(pszNameString, "internal.hex-rays.com") )
 {
   aCert->CerErrText = "invalid_remote_certificate"; CertFreeCertificateContext(pBuffer);
   return 0;
 }
 else {
               CertFreeCertificateContext(pBuffer);
   return 1;
 }
}

So until you somehow get it done to craft a certificate with a broken chain for the lumina server on lumen.abda.nl.
We need to patch ida64.dll.

Fileoffset: 000B00E8 32 C0 -> B0 01
Will turn all that above return 0; into return 1;

You are using a different Version of IDA?

->So that is how to find the file offset

Having ida64.dll loaded press Shift+F4 to open "Strings"
ctrl+f and enter invalid_remote_certificate. Enter to follow that entry. Ctrl+x to show xrefs. There should be 2. Press Enter to follow the last xrefs.
Now you are inside the right function. Some lines down there should be call cs:CertFreeCertificateContext.
A little more down xor al, al . That's what needs the patch.
Scroll to that line.

Edit\Patch program\Patch Bytes
32 C0 .... change it to B0 01 ....
Edit\Patch program\Apply patch to input file.
Ok to save and ya done.

Well file is probably in use and save not possible.
But hey you smart, you'll get this done, don't ya. ;^)

@tomrus88
Copy link

tomrus88 commented Mar 15, 2024

@naim94a you wanted open source? Here you go https://github.com/tomrus88/OpenLumina. But you will have to create new server certificate because your old certificate doesn't use certificate chains as intended by IDA and official Lumina servers (both public and private). Scripts to generate new compatible certificates can be found in plugin repo. Certificates generated by provided scripts use exact same settings that are used to generate official Lumina server certificates, the only difference is that we create our own private keys (because we don't have original ones). The idea is so that this plugin works with both your server as well as official private Lumina servers (but pirated).

In the feature, once you update your server certificate, I think it should be possible to include that new certificate within the plugin as preset certificate (hardcode it just like IDA does) so that users don't have to copy both certificate file and plugin to theirs IDA's.

There's also performance benefit from using new generated TLS certificates because they are ECC based certificates instead of RSA. ECC certificates use much shorter keys (256 bits instead of 4096 bits) and that means it's much easier for both server and client to deal with encryption.

Elliptic Curve Cryptography (ECC) is emerging as an attractive public-key cryptosystem for mobile/wireless environments. Compared to traditional cryptosystems like RSA, ECC offers equivalent security with smaller key sizes, which results in faster computations, lower power consumption, as well as memory and bandwidth savings.

This is completely new plugin that was created from scratch today and uses different method (compared to method used in old plugin I shared previously) to fix certificate issues in newer IDA versions.

Edit: there's appears to be a bug that prevents this method from working correctly if Lumen server is running on Windows OS, server doesn't send whole certificate chain from certificate file to client as intended for some reason, only first certificate from the chain is being sent and that causes validation on client to fail... Bug is probably somewhere in Windows schannel (less likely) or in rust-native-tls library and it's dependencies (most likely)...

Edit2: found a workaround for that bug where when hosting Lumen server on Windows OS it's not sending full certificate chain, if you manually install your generated intermediate certificate to "Current User" certificate store under "Intermediate Certificate Authorities" -> "Certificates" category, server will send certificate chain correctly and validation will succeed as intended.

Plugin is Windows only because:

  • I don't use any other OS but Windows personally
  • I don't know how to do hooking on other OS's nor I want to spend time figuring this out

Edit3: there's now experimental versions of plugin for Linux and MacOS.

If someone knows how to add Linux/MacOS support to the plugin, feel free to submit PR.

@tomrus88
Copy link

tomrus88 commented Mar 31, 2024

I've also created plugins for Linux and MacOS, they seems to work fine during my limited testing on local server. I had to add support for Linux/MacOS to my closed source plugin that brings Lumina functionality to IDA Freeware to be able to test it, but for version 8.4 only, because those OS's are pain to work with and there's some differences in IDA internals between versions making it even more pain.

But we still need server certificate update for it to be useful.

At least people who run theirs own Lumina server can use plugin now as long as they generate new compatible certificate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants