¿Cómo ocultar cadenas en un exe o un dll?

Descubrí que es posible extraer las cadenas codificadas de un binario.
Por ejemplo, la vista de propiedades de Process Explorer muestra toda la cadena con más de 3 caracteres.

Aquí está el código de un ejecutable simple que escribí simplemente para probarlo:

#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif #include  #include  #include  int _tmain(int argc, _TCHAR* argv[]) { _TCHAR* hiddenString1 =_T("4537774B-CC80-4eda-B3E4-7A9EE77991F5"); _TCHAR* hiddenString2 =_T("hidden_password_or_whatever"); for (int i= 0; i<argc; i++) { if (0 == _tcscmp(argv[i],hiddenString1)) { _tprintf (_T("The guid argument is correct.\n")); } else if (0 == _tcscmp(argv[i],hiddenString2)) { _tprintf (_T("Do something here.\n")); } } _tprintf (_T("This is a visible string.\n")); //Keep Running Sleep(60000); return 0; } 

Las cadenas se pueden extraer claramente del ejecutable correspondiente:
texto alternativo

Creo que es un poco demasiado fácil encontrar las cuerdas.

Mis preguntas son:

  1. ¿Cómo simplemente ocultar hiddenString1 o hiddenString2 en el ejecutable?
  2. ¿Hay una manera más segura de usar el “código de trampa” que con alguna entrada oscura oculta?

Bienvenido al mundo más amplio de la progtwigción defensiva.

Hay un par de opciones, pero creo que todas dependen de alguna forma de ofuscación; que, aunque no es perfecto, es al menos algo.

  1. En lugar de un valor de cadena recta, puede almacenar el texto en alguna otra forma binaria (¿hex?).

  2. Puede encriptar las cadenas que están almacenadas en su aplicación y luego descifrarlas en tiempo de ejecución.

  3. Puede dividirlos en varios puntos de su código y reconstituirlos más tarde.

O alguna combinación de eso.

Tenga en cuenta que algunos ataques van más allá de mirar el binario real. A veces investigarán el espacio de direcciones de memoria del progtwig mientras se está ejecutando. MS ideó algo llamado SecureString en .Net 2.0 . El propósito es mantener las cadenas encriptadas mientras se ejecuta la aplicación.

Una cuarta idea es no almacenar la cadena en la aplicación en sí, sino confiar en un código de validación que se enviará a un servidor que usted controle. En el servidor puede verificar si es un “código de trampa” legítimo o no.

Hay muchas formas de ocultar datos en un ejecutable. Otros aquí han publicado buenas soluciones, algunas más fuertes que otras. No agregaré a esa lista.

Solo ten en cuenta: es todo un juego del gato y el ratón: es imposible garantizar que nadie descubra tu “secreto”.

No importa la cantidad de encriptación u otros trucos que use; no importa cuánto esfuerzo o dinero le pongas. No importa cuántos tipos de “NASA / MIT / CIA / NSA” estén involucrados en ocultarlo.

Todo se reduce a la física simple:
Si fuera imposible para cualquier usuario extraer su secreto del ejecutable y “mostrarlo”, entonces la computadora no podrá mostrarlo tampoco, y su progtwig no podrá usarlo. Cualquier desarrollador moderadamente calificado con suficiente incentivo encontrará la manera de mostrar el secreto.

En el momento en que le entrega su archivo ejecutable a un usuario, tiene todo lo que necesita para descubrir el secreto.

Lo mejor que puede esperar es hacer que sea tan difícil descubrir el secreto que los beneficios que puede obtener de conocer el secreto no valen la pena.

Por lo tanto, está bien tratar de ocultar los datos si simplemente no es “agradable” para que sea público, o si las consecuencias de su publicación serían simplemente “inconvenientes”. Pero ni siquiera pienses en esconder en tu progtwig “la contraseña de tu base de datos maestra de cliente”, una clave privada u otro secreto crítico. Usted simplemente no puede.

Si tiene información realmente críticamente secreta que su progtwig necesitará de alguna manera, pero NUNCA debe convertirse en información pública (como una clave privada), necesitará que su progtwig hable con un servidor remoto bajo su control, aplique los controles de autenticación y autorización adecuados ( es decir, asegúrese de que solo las personas o las computadoras aprobadas puedan realizar la solicitud al servidor ), y haga que ese servidor guarde el secreto y lo use.

La forma más simple es encriptarlos con algo trivial como xor o rot-13, y luego descifrarlos sobre la marcha cuando se usan. Eso eliminará la visión casual de ellos, pero no detendrá a nadie con mucha experiencia para revertir.

Además de esos métodos, Chris menciona que también podría usar un algoritmo hash. Si todo lo que quiere hacer es verificar si se especificó la ID correcta, no es necesario que almacene la ID completa en su progtwig.

  • Cree un hash (MD5, SHA, etc.) de la cadena / contraseña / ID con la que desea comparar, tal vez agregue un valor ‘sal’. Almacene esto en su progtwig
  • Cuando se ejecuta el progtwig, haga el mismo algoritmo en la cadena de entrada / contraseña / identificación y compare los dos hashes para ver si coinciden.

De esta forma, el texto real nunca se almacena en su progtwig y no pueden realizar una ingeniería inversa de su progtwig para averiguar cuál era el texto original, ya que los algoritmos hash son unidireccionales.

También hay URL para las solicitudes http que me gustaría ocultar.

Si su aplicación está haciendo la solicitud, no tiene sentido ocultar esto. Al ejecutar una aplicación como el violinista, el analizador http o uno de los muchos métodos gratuitos y fácilmente disponibles, se mostrará todo el tráfico que crea su aplicación.

¿Todos sus códigos secretos serán GUID o solo fue un ejemplo?

Quizás guarde su secreto como una guía binaria:

 const GUID SecretGuid = { 0x4537774B, 0xCC80, 0x4eda, { 0x7A, 0x9E, 0xE7, 0x79, 0x91, 0xF5 } }; 

A continuación, convierta el guid suministrado de cadena a formato binario y compare las dos guías binarias.

Si hay una cadena específica que no desea que la gente pueda ver, encripte y descifre en tiempo de ejecución.

Si no desea que las personas vean su GUID, entonces hágalo desde bytes, en lugar de construirlo a partir de una cadena:

 const GUID SecretGuid = { 0x4537774B, 0xCC80, 0x4eda, { 0x7A, 0x9E, 0xE7, 0x79, 0x91, 0xF5 } }; 

Lo mejor que puede hacer es codificar su contraseña u otra cadena que desee ocultar como matriz de caracteres. Por ejemplo:

 std::string s1 = "Hello"; // This will show up in exe in hex editor char* s2 = "World"; // this will show up in exe in hex editor char s3[] = {'G', 'O', 'D'}; // this will not show up in exe in hex editor. 

Este es el método que uso para este propósito. Primero, utilizo la herramienta Cadenas de Sysinternals para mostrar las cadenas en un EXE o DLL. A continuación, utilizo la siguiente pequeña herramienta (ver artículo ) para reemplazar estas cadenas con una matriz codificada de caracteres almacenados como una expresión aritmética: por ejemplo: en lugar de la cadena: “esto es una prueba” , colocaré el siguiente código: (que es generado automáticamente por esta herramienta )

 WCHAR T1[28]; T1[22] = 69; T1[15] = 121 - 17; T1[9] = L':' + -26; T1[12] = L't' - 1; T1[6] = 116 - 1; T1[17] = 117 - 12; T1[3] = 116 - 1; T1[14] = L'' - 3; T1[13] = L'w' - 3; T1[23] = 69; T1[26] = L'Y' + 3; T1[19] = 111 + 0; T1[21] = L'k' - 34; T1[27] = L'\\' - 8; T1[20] = L'B' + 32; T1[4] = 42 + -10; T1[25] = L'm' - 17; T1[16] = L'H' + 18; T1[18] = L'A' + 56; T1[24] = 68; T1[1] = 105 - 1; T1[11] = L'k' - 6; T1[10] = 66 + 50; T1[2] = 105; T1[0] = 117 - 1; T1[5] = L'k' - 2; T1[8] = 89 + 8; T1[7] = 32; 

Hay muchas soluciones a este problema y ninguna de ellas (incluida la mía) es perfecta, sin embargo, hay formas de codificar, disfrazar y ocultar las cadenas sensibles. Por supuesto, puede encriptarlos y descifrarlos durante el tiempo de ejecución (consulte este artículo), pero me parece más importante hacer que estas cadenas desaparezcan entre los bits y bytes del archivo ejecutable y funciona. Después de ejecutar mi herramienta, no encontrará “esto es una prueba” en el archivo ejecutable.