2010-04-30 10 views
9

Tengo un problema donde necesito poder tener un exe compilado (.net 3.5 C#) que haré copias para distribuir que necesitarán cambiar una clave por ejemplo antes del exe se envía.Modificar cadena Emdeded en C# compiled exe

No puedo compilar cada vez que se necesita un nuevo exe. Este es un cliente ligero que se utilizará como parte de un proceso de registro.

Es posible agregar una entrada a un archivo de recursos con un valor en blanco y cuando llega una solicitud, haga que otra aplicación capture el cliente ligero predeterminado en blanco, cópielo, llene el valor en blanco con los datos necesarios.

Si es así ¿cómo? Si no, ¿tienes alguna idea? Me he estado rascando la cabeza durante unos días y la limitación se debe a los límites en los que se me exige que trabaje.

La otra idea que tengo es inyectar el valor en un método, que no tengo idea de cómo Incluso intentaría eso.

Gracias.

+0

¿Cuál es el propósito de esto? Sabiendo eso podría ayudarnos a ayudarlo mejor. –

+0

Hola Robert, Necesito distribuir un exe de cliente ligero a x usuarios. Sin embargo, este cliente debe poder tener una clave inyectada sobre la marcha antes de enviarla. Compilar a pedido no funcionará. Cada cliente enviado tendrá su propio identificador único asociado. No puedo usar un archivo app.config ya que el archivo debe ser independiente (otro requisito), por lo tanto, comencé a buscar en el archivo de recursos ya que la clave debe estar incrustada. Gracias. – nitefrog

+0

¿Se debe firmar el archivo? –

Respuesta

5

Convierta el conjunto a IL, haga una búsqueda textual y reemplace, vuelva a compilar la IL a un conjunto nuevamente. Use el standard tools from the .NET SDK.

+0

Dan and Amry Acabo de publicar esta pregunta: http://stackoverflow.com/questions/2749113/compile-il-code-at-runtime-using-net-3-5-and-c-from-file Voy a tomar el enfoque ildasm y ilasm, pero ¿sabes cómo automatizar esto sin tener que ordenar la línea usando process.start? – nitefrog

-1

lo que viene a la mente, pero no probado hasta ahora: crear una cadena por defecto en el programa, por ejemplo, como

static public string regGuid = "yourguidhere"; 

A continuación, busque el ejecutable compilado con cualquier editor hexadecimal decente. Si encuentra la cadena, reemplácela con otra prueba. Si todavía puede ejecutar el programa, podría tratar de automatizar este proceso y ¡listo! Aquí estás.

+2

No sé si los ensambles sin firmar tienen algún tipo de suma de comprobación, pero creo que fallarán en los ensamblados firmados, ya que la firma ya no será válida. –

+2

Sin mencionar toda la diversión si la longitud cambia ... –

+0

Ese es el problema, no se puede garantizar que la clave tenga la misma longitud cada vez. De ahí una clave de longitud variable. – nitefrog

1

Desde la capacidad del código .NET en sí, no estoy seguro de si esto es factible. Pero es posible generar dinámicamente una DLL .NET que contenga alguna clave a la que se pueda hacer referencia desde la aplicación principal. Es decir, si no te importa un segundo archivo en la distribución.

O si no le importa usar Ildasm para desmontar el .exe, cambie la clave, luego use Ilasm para volver a ensamblar, luego puede hacer algo para automatizar eso.

+0

Si convierte a il y convierte de nuevo provocará cualquier problema con la firma del exe una vez que se convierte de nuevo. El proceso, necesita ser automatizado. Por mi vida no puedo hacer que UpdateResource funcione. Modifica el archivo pero no sobrescribe el valor de Nombre ... – nitefrog

+0

Puede firmar el exe al volver a armarlo usando el argumento ilasm/key = keyfile. – Amry

+0

Acabo de probar y creé una IL, el problema es que la información del archivo de recursos no se muestra en ninguna parte. Puedo ver el nombre pero no el valor. ¿Alguien ha conseguido UpdateResource para trabajar? – nitefrog

4

En lugar de incrustar la clave en el conjunto, colóquela en el archivo app.config (u otro archivo entregado con la aplicación) y evite que su aplicación se ejecute si la clave no está presente y es válida. Para protegerlo contra la modificación por parte de los usuarios, también agregue una firma RSA al archivo de configuración.

Este código podría usarse para generar XML que contenga su clave.

public static void Main() 
{ 
    Console.WriteLine(GenerateKey()); 
} 

public static Byte[] Transform(Byte[] bytes, ICryptoTransform xform) 
{ 
    using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) 
    { 
     using (CryptoStream cstream = new CryptoStream(stream, xform, CryptoStreamMode.Write)) 
     { 
     cstream.Write(bytes, 0, bytes.Length); 
     cstream.Close(); 
     stream.Close(); 
     return stream.ToArray(); 
     } 
    } 
} 

public static string GenerateKey() 
{ 
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
    // This is the private key and should never be shared. 
    // Generate your own with RSA.Create().ToXmlString(true). 
    String rsaPrivateKey = "<RSAKeyValue><Modulus>uPCow37yEzlKQXgbqO9E3enSOXY1MCQB4TMbOZyk9eXmc7kuiCMhJRbrwild0LGO8KE3zci9ETBWVVSJEqUqwtZyfUjvWOLHrf5EmzribtSU2e2hlsNoB2Mu11M0SaGd3qZfYcs2gnEnljfvkDAbCyJhUlxmHeI+35w/nqSCjCk=</Modulus><Exponent>AQAB</Exponent><P>4SMSdNcOP0qAIoT2qzODgyl5yu9RubpIU3sSqky+85ZqJHXLUDjlgqAZvT71ROexJ4tMfMOgSWezHQwKWpz3sw==</P><Q>0krr7cmorhWgwCDG8jmzLMo2jafAy6tQout+1hU0bBKAQaPTGGogPB3hTnFIr84kHcRalCksI6jk4Xx/hiw+sw==</Q><DP>DtR9mb60zIx+xkdV7E8XYaNwx2JeUsqniwA3aYpmpasJ0N8FhoJI9ALRzzp/c4uDiuRNJIbKXyt6i/ZIFFH0qw==</DP><DQ>mGCxlBwLnhkN4ind/qbQriPYY8yqZuo8A9Ggln/G/IhrZyTOUWKU+Pqtx6lOghVdFjSxbapn0W8QalNMFGz7AQ==</DQ><InverseQ>WDYfqefukDvMhPHqS8EBFJFpls/pB1gKsEmTwbJu9fBxN4fZfUFPuTnCIJsrEsnyRfeNTAUFYl3hhlRYZo5GiQ==</InverseQ><D>qB8WvAmWFMW67EM8mdlReI7L7jK4bVf+YXOtJzVwfJ2PXtoUI+wTgH0Su0IRp9sR/0v/x9HZlluj0BR2O33snQCxYI8LIo5NoWhfhkVSv0QFQiDcG5Wnbizz7w2U6pcxEC2xfcoKG4yxFkAmHCIkgs/B9T86PUPSW4ZTXcwDmqU=</D></RSAKeyValue>"; 

    rsa.FromXmlString(rsaPrivateKey); 
    String signedData = "<SignedData><Key>Insert your key here</Key></SignedData>"; 
    Byte[] licenseData = System.Text.Encoding.UTF8.GetBytes(signedData); 
    Byte[] sigBytes = rsa.SignData(licenseData, new SHA1CryptoServiceProvider()); 
    String sigText = System.Text.Encoding.UTF8.GetString(Transform(sigBytes, new ToBase64Transform())); 
    System.Text.StringBuilder sb = new StringBuilder(); 
    using (System.Xml.XmlWriter xw = System.Xml.XmlTextWriter.Create(sb)) 
    { 
     xw.WriteStartElement("License"); 
     xw.WriteRaw(signedData); 
     xw.WriteElementString("Signature", sigText); 
     xw.WriteEndElement(); 
    } 
    return sb.ToString(); 
} 

Ejemplo de salida de este código:

<?xml version="1.0" encoding="utf-16"?> 
<License> 
    <SignedData> 
    <Key>Insert your key here</Key> 
    </SignedData> 
    <Signature>cgpmyqaDlHFetCZbm/zo14NEcBFZWaQpyHXViuDa3d99AQ5Dw5Ya8C9WCHbTiGfRvaP4nVGyI+ezAAKj287dhHi7l5fQAggUmh9xTfDZ0slRtvYD/wISCcHfYkEhofXUFQKFNItkM9PnOTExZvo75pYPORkvKBF2UpOIIFvEIU=</Signature> 
</License> 

continuación, puede utilizar código como este para verificarlo. Nunca se tiene que distribuir la clave privada:

public static Boolean CheckLicenseSignature(String licXml) 
{ 
    try 
    { 
     System.Xml.XmlDocument xd = new System.Xml.XmlDocument(); 
     xd.LoadXml(licXml); 
     String licSig = xd.SelectSingleNode("/License/Signature").InnerText; 
     RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
     String rsaPublicKey = "<RSAKeyValue><Modulus>uPCow37yEzlKQXgbqO9E3enSOXY1MCQB4TMbOZyk9eXmc7kuiCMhJRbrwild0LGO8KE3zci9ETBWVVSJEqUqwtZyfUjvWOLHrf5EmzribtSU2e2hlsNoB2Mu11M0SaGd3qZfYcs2gnEnljfvkDAbCyJhUlxmHeI+35w/nqSCjCk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; 
     rsa.FromXmlString(rsaPublicKey); 
     Byte[] licenseData = System.Text.Encoding.UTF8.GetBytes(xd.SelectSingleNode("/License/SignedData").OuterXml); 
     return rsa.VerifyData(licenseData, new SHA1CryptoServiceProvider(), Transform(System.Text.Encoding.UTF8.GetBytes(licSig), new FromBase64Transform())); 
    } 
    catch (System.Xml.XmlException ex) 
    { 
     return false; 
    } 
    catch (InvalidOperationException ex) 
    { 
     return false; 
    } 
} 
+0

Una vez más, el archivo debe ser independiente. No puedo tener ningún archivo dependiente, pero esta es una solución bastante impresionante si pudiera tener otro archivo para acompañar. Además, la clave debe poder leerse ya que no se necesita cifrado. Hay otro proceso en la seguridad que bloqueará la seguridad. Solo necesito tener un identificador único asociado con el exe y debe estar integrado con cada exe que envío. – nitefrog

+0

Pensé que podría estar solucionando el problema incorrecto porque creo que en muchos casos el archivo de configuración de la aplicación se transporta automáticamente con el ejecutable. Y también hay formas de empaquetar múltiples archivos en uno si es necesario. Pero si esos problemas son más difíciles de tratar que la solución que ha aceptado, ciertamente tome el camino de menor resistencia. – BlueMonkMN

+0

Además, la clave no se cifra con este código. Todo el XML es texto plano, y solo la firma añadida al final es incomprensible. – BlueMonkMN

0

No creo que usted puede conseguir lejos sin tener que recompilar su .exe y teniendo clave incorporada en dicho .exe. El proceso de compilación se puede automatizar mediante el uso de ildasm.exe y ilasm.exe como sugirió Daniel Earwicker en su respuesta https://stackoverflow.com/a/2742902/2358659

Me gustaría ampliar eso si alguien más tropieza con este tema en el futuro.

Hace poco tuve problemas similares debido a mis pobres hábitos de control de la versión del código fuente. En resumen, tenía un ejecutable que se suponía que debía escribir algunos datos en una hoja de cálculo de Google al hacer referencia a su ID. Mucho después de que se lanzara el ejecutable surgió otra solicitud de un equipo diferente para usar la herramienta, pero tenía que escribir la misma información en una hoja de cálculo diferente para mantener los datos separados para dos equipos. En ese momento no tenía el código fuente original, por lo tanto, no pude cambiar la variable estática que contiene la ID original de la hoja de cálculo. Lo que hice fue el siguiente:

  1. Usando CMD.exe → llamada "C: \ Archivos de programa (x86) \ Microsoft SDKs \ Windows \ v8.0A \ bin \ netfx 4.0 Tools \ ildasm.exe" " MyApplication.exe "/out="myApplication.il"
  2. Usando Notepad ++ → Buscar y reemplazar ID original al nuevo ID en el interior archivo myApplication.il. Esta acción también se puede automatizar escribiendo la propia aplicación C# para hacer esto, o usando PowerShell, o usando vb/j-script o usando alguna otra herramienta de búsqueda y reemplazo disponible de fábrica, como FART (usando CMD.exe → call fart.exe myApplication.il "OldKey" "NewKey")
  3. Usando CMD.exe → llamada "C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ ilasm.exe" "myApplication.il" /res="myApplication.res "/key="myApplicationKeyFile.snk"

como se ve, todos estos pasos se pueden poner en un archivo .bat que se lleva a 'NewKey' como una entrada y pinchar uces nuevo .exe con NewKey incrustado.

Espero que ayude.

Cuestiones relacionadas