2011-08-03 14 views
13

quiero cifrar/codificar una cadena en tiempo de compilación para que la cadena original no aparece en el ejecutable compilado.de cifrado/ofuscar una cadena literal en tiempo de compilación

He visto varios ejemplos, pero no puedo tomar una cadena literal como argumento. Consulte el siguiente ejemplo:

template<char c> struct add_three { 
    enum { value = c+3 }; 
}; 

template <char... Chars> struct EncryptCharsA { 
    static const char value[sizeof...(Chars) + 1]; 
}; 

template<char... Chars> 
char const EncryptCharsA<Chars...>::value[sizeof...(Chars) + 1] = { 
    add_three<Chars>::value... 
}; 

int main() { 
    std::cout << EncryptCharsA<'A','B','C'>::value << std::endl; 
    // prints "DEF" 
} 

No deseo proporcionar cada carácter por separado como lo hace. Mi objetivo es hacer pasar una cadena literal gustaría siguiente manera:

EncryptString<"String to encrypt">::value 

También hay algunos ejemplos como éste:

#define CRYPT8(str) { CRYPT8_(str "\0\0\0\0\0\0\0\0") } 
#define CRYPT8_(str) (str)[0] + 1, (str)[1] + 2, (str)[2] + 3, (str)[3] + 4, (str)[4] + 5, (str)[5] + 6, (str)[6] + 7, (str)[7] + 8, '\0' 

// calling it 
const char str[] = CRYPT8("ntdll"); 

pero limita el tamaño de la cadena.

¿Hay alguna manera de lograr lo que quiero?

+8

Un enfoque común para este tipo de problema es escribir una secuencia de comandos que toma su archivo de origen como una entrada y crea un archivo modificado como salida, que luego sería utilizado por su proceso de compilación. En este caso, el script buscará 'EncryptString <" String para encriptar ">' y reemplazará la cadena con la versión encriptada/codificada. – jdigital

Respuesta

1

creo que esta pregunta merece una respuesta actualizada.

Cuando hice esta pregunta hace varios años, no consideré the difference between obfuscation and encryption. Si hubiera conocido esta diferencia, habría incluido el término Ofuscación en el título anterior.

C++ y C++ 11 14 tienen características que hacen posible la implementación de en tiempo de compilación ofuscación cadena (y posiblemente cifrado, aunque no he probado todavía) de una manera eficaz y razonablemente simple, y ya está hecho.

ADVobfuscator es una biblioteca de ofuscación creada por Sebastien Andrivet que utiliza C++ 11/14 para generar código ofuscado en tiempo de compilación sin utilizar ninguna herramienta externa, solo código C++. No es necesario crear pasos de compilación adicionales, simplemente inclúyalo y úselo. No conozco una mejor implementación de encriptación/ofuscación de cadenas en tiempo de compilación que no use herramientas externas ni pasos de compilación. Si tu lo haces, por favor compártelo.

No solo obusa cadenas, sino que tiene otras funciones útiles como FSM en tiempo de compilación (Finite State Machine) que pueden ofuscar de forma aleatoria las llamadas de función y un generador de números pseudoaleatorios en tiempo de compilación, pero están fuera del alcance de esta respuesta.

Aquí es un simple ejemplo de cadena de ofuscación utilizando ADVobfuscator:

#include "MetaString.h" 

using namespace std; 
using namespace andrivet::ADVobfuscator; 

void Example() 
{ 
    /* Example 1 */ 

    // here, the string is compiled in an obfuscated form, and 
    // it's only deobfuscated at runtime, at the very moment of its use 
    cout << OBFUSCATED("Now you see me") << endl; 

    /* Example 2 */ 

    // here, we store the obfuscated string into an object to 
    // deobfuscate whenever we need to 
    auto narrator = DEF_OBFUSCATED("Tyler Durden"); 

    // note: although the function is named `decrypt()`, it's still deobfuscation 
    cout << narrator.decrypt() << endl; 
} 

Puede reemplazar las macros DEF_OBFUSCATED y OBFUSCATED con sus propias macros. Ej .:

#define _OBF(s) OBFUSCATED(s) 

... 

cout << _OBF("klapaucius"); 

¿Cómo funciona?

Si se echa un vistazo a la definición de estas dos macros en MetaString.h, verá:

#define DEF_OBFUSCATED(str) MetaString<andrivet::ADVobfuscator::MetaRandom<__COUNTER__, 3>::value, andrivet::ADVobfuscator::MetaRandomChar<__COUNTER__>::value, Make_Indexes<sizeof(str) - 1>::type>(str) 

#define OBFUSCATED(str) (DEF_OBFUSCATED(str).decrypt()) 

Básicamente, hay tres variantes diferentes del MetaString clase (el núcleo de la ofuscación de cadena) . Cada uno tiene su propio algoritmo de ofuscación. Una de estas tres variantes se elige aleatoriamente en tiempo de compilación, utilizando el generador de números pseudoaleatorios de la biblioteca (MetaRandom), junto con un char aleatorio que es utilizado por el algoritmo elegido para xor los caracteres de cadena.

"Oye, pero si hacemos los cálculos, algoritmos 3 * 255 claves posibles char (0 no se utiliza) = 765 variantes de la cadena ofuscado"

Tienes razón. La misma cadena solo puede ofuscarse en 765 formas diferentes. Si tiene una razón para necesitar algo más seguro (es paranoico/su aplicación exige mayor seguridad) puede ampliar la biblioteca e implementar sus propios algoritmos, utilizando una ofuscación más fuerte o incluso cifrado (White-Box cryptography se encuentra en el mapa de ruta de la lib).


Dónde/cómo se almacenan las cadenas ofuscado?

Una cosa que me parece interesante sobre esta implementación es que no almacena la cadena ofuscada en la sección de datos del ejecutable. En su lugar, está almacenado estáticamente en el objeto MetaString (en la pila) y el algoritmo lo decodifica en su lugar en tiempo de ejecución. Este enfoque hace que sea mucho más difícil encontrar las cadenas ofuscadas, estáticamente o en tiempo de ejecución.

Puede profundizar en la implementación por su cuenta. Esa es una solución de ofuscación básica muy buena y puede ser un punto de partida para una más compleja.

+0

Si bien su respuesta agrega detalles sobre cómo usar la herramienta a la que se ha vinculado, sería genial si pudiera agregar aquí (al menos algunos) detalles de la implementación también. De lo contrario, en caso de que su enlace se agote, los lectores del futuro solo podrán ver cómo usar una implementación de un ofuscador al que no tienen acceso, lo que sería ligeramente exasperante. –

+0

Gracias por su sugerencia. Publicaré los detalles de la implementación. – karliwson

3

La razón por la cual los ejemplos que encontró no pueden tomar literales de cadena como argumento de plantilla es porque no está permitido por el estándar ISO C++. Eso es porque, aunque C++ tiene una clase de cadena, un literal de cadena sigue siendo un const char *. Por lo tanto, no puede, o no debe, alterarlo (conduce a un comportamiento indefinido), incluso si puede acceder a los caracteres de dicho literal de cadena en tiempo de compilación.

La única manera que veo está usando define, ya que son manejados por el preprocesador antes de que el compilador. Tal vez impulsar le dará una mano en ese caso.

2

Una macro solución basada sería tomar un argumento variadic y pasar en cada parte de la cadena como un único token. A continuación, escriba el token y encripte y concatene todos los tokens. El resultado final sería algo como esto

CRYPT(m y _ s t r i n g) 

Dónde _ algún marcador de posición para un carácter de espacio en blanco literal. Horriblemente desordenado y preferiría cualquier otra solución sobre esto.

Algo como esto podría hacerlo aunque la secuencia Boost.PP no lo esté haciendo más bonito.

#include <iostream> 
#include <boost/preprocessor/stringize.hpp> 
#include <boost/preprocessor/seq/for_each.hpp> 

#define GARBLE(x) GARBLE_ ## x 
#define GARBLE_a x 
#define GARBLE_b y 
#define GARBLE_c z 

#define SEQ (a)(b)(c) 
#define MACRO(r, data, elem) BOOST_PP_STRINGIZE(GARBLE(elem)) 

int main() { 
    const char* foo = BOOST_PP_SEQ_FOR_EACH(MACRO, _, SEQ); 
    std::cout << foo << std::endl; 
} 
7

ahorrarse un montón de problemas en la línea con metaprogramming plantilla y acaba de escribir un programa independiente que cifra la cadena y produce un archivo de origen cpp que se compila a continuación. Este programa se ejecute antes de compilar y produciría un archivo cpp y/o encabezado que contendría la cadena encriptada para que usted pueda usar.

Así que aquí es lo que usted comienza con:

  1. encrypted_string.cpp y encrypted_string.h (que están en blanco)
  2. Un guión o aplicación independiente que toma un archivo de texto como entrada y escribe sobre encrypted_string .cpp y encrypted_string.h

Si la secuencia de comandos falla, su compilación fallará porque habrá referencias en su código a una variable que no existe. Podría ser más inteligente, pero eso es suficiente para comenzar.

Cuestiones relacionadas