Search code examples
c#.netencryptioncryptographymalware-detection

Antivirus software flagging encryption code as malware


My WPF .NET 4 application has several things going against it, from a malware identification perspective:

  • It must run directly from a thumb drive
  • It must allow the user to set device security tied to the host computer
  • Once device security is set, it must never have a decrypted file on the device
  • It must decrypt files to the host computer's temp directory

As it turns out, there is "ransomware" out there now that encrypts a user's files and then demands payment for the decryption key.

Kapersky, in particular, flags the file encryption process as malware and very effectively kills the application. When encrypting, Kaspersky identifies malware, identified as PDM:Win32.Generic, and proceeds to detect, terminate and delete. A scan of an already-encrypted device comes back 100% clean - no problems.

Here is the file encrypt/decrypt code. It's adapted from a CodeProject file encryption article. Could there be something in this code that triggers suspicion in the AV software? I'm using only pure .NET, no 3rd-party libraries:

    /// <summary>
    /// Encrypt a file with a user-supplied password.
    /// WARNING: File will be lost if password is forgotton.
    /// </summary>
    /// <param name="inputFile">
    /// The name of the unencrypted file to encrypt.
    /// </param>
    /// <param name="encryptedFile">
    /// The name of the newly encrypted file to created.
    /// </param>
    /// <param name="clearTextPassword"></param>
    /// <param name="salt">
    /// You can bypass this and use the predefined salt in this class
    /// BUT IT IS NOT RECOMMENDED. Your code should provide an 8-byte
    /// array for the salt.
    /// </param>
    public static void EncryptFile( string inputFile, string encryptedFile,
        string clearTextPassword, byte[] salt = null )
    {
        salt = salt ?? FileSalt;
        byte[] key = new Rfc2898DeriveBytes( clearTextPassword, salt ).GetBytes( 16 );
        FileStream fsCrypt = new FileStream( encryptedFile, FileMode.Create );
        RijndaelManaged rmCrypto = new RijndaelManaged();
        rmCrypto.Padding = PaddingMode.PKCS7;
        CryptoStream cs = new CryptoStream( fsCrypt,
            rmCrypto.CreateEncryptor( key, key ),
            CryptoStreamMode.Write );
        FileStream fsIn = new FileStream( inputFile, FileMode.Open );
        int data;
        while( ( data = fsIn.ReadByte() ) != -1 )
            cs.WriteByte( (byte)data );
        fsIn.Close();
        cs.Close();
        fsCrypt.Close();
    }

    /// <summary>
    /// Decrypt a file with a user-supplied password.
    /// </summary>
    /// <param name="inputFile">
    /// The name of the encrypted file to decrypt.
    /// </param>
    /// <param name="unencryptedFile">
    /// The name of the unencrypted file to create.
    /// </param>
    /// <param name="clearTextPassword"></param>
    /// <param name="salt">
    /// You can bypass this and use the predefined salt in this class
    /// BUT IT IS NOT RECOMMENDED. Your code should provide an 8-byte
    /// array for the salt.
    /// </param>
    public static void DecryptFile( string inputFile, string unencryptedFile,
        string clearTextPassword, byte[] salt = null )
    {
        salt = salt ?? FileSalt;
        byte[] key = new Rfc2898DeriveBytes( clearTextPassword, salt ).GetBytes( 16 );
        FileStream fsCrypt = new FileStream( inputFile, FileMode.Open );
        RijndaelManaged rmCrypto = new RijndaelManaged();
        rmCrypto.Padding = PaddingMode.PKCS7;
        CryptoStream cs = new CryptoStream( fsCrypt,
            rmCrypto.CreateDecryptor( key, key ),
            CryptoStreamMode.Read );
        FileStream fsOut = new FileStream( unencryptedFile, FileMode.Create );
        int data;
        while( ( data = cs.ReadByte() ) != -1 )
            fsOut.WriteByte( (byte)data );
        fsOut.Close();
        cs.Close();
        fsCrypt.Close();
    }

Note that I'm not terribly interested in comments about my use of string vs. SecureString for the clear text password, etc., unless that information helps to solve the AV problem.


Solution

  • Kaspersky has concluded that this was a false positive, and they are correcting their software to handle it.