La idea es cifrar y/o destruir parte del contenido de las funciones para evitar el análisis estático de los binarios, esto lo tome como idea hace años del antiguo sistema de protección de Themida/WinLicense de Oreans:
Código
#include <stdio.h> #include <math.h> #include "codeencryption.h" #pragma optimize("",off) _declspec(noinline)int addOperation(int a, int b) { int iRetval; CodeEncryption cdProtection; cdProtection.dwPassWord = 0xDEADBAFF; cdProtection.biOptions = ENCRYPTION_PAGE_PROTECTIONS | ENCRYPTION_CLEAR_CODE; iRetval = a; BeginEncryption(&cdProtection); iRetval += b; EndEncryption(&cdProtection); return iRetval; } _declspec(noinline)int addAndSquareRoot(int a, int b) { int iRetval; CodeEncryption cdProtection; cdProtection.dwPassWord = 0xDEADBAFF; cdProtection.biOptions = ENCRYPTION_PAGE_PROTECTIONS | ENCRYPTION_CLEAR_CODE; iRetval = a; BeginEncryption(&cdProtection); iRetval += b; iRetval = (int)sqrt(iRetval); EndEncryption(&cdProtection); return iRetval; } #pragma optimize("",on) int main() { int a = 4, b = 21; printf("%i+%i=%i\n", a, b, addOperation(a, b)); printf("%i+%i=%i\n", a, b, addOperation(a, b)); getchar(); printf("sqrt(%i+%i)=%i\n", a, b, addAndSquareRoot(a, b)); printf("sqrt(%i+%i)=%i\n", a, b, addAndSquareRoot(a, b)); getchar(); return 0; }
Donde se puede ver el código original compilado se vé de la siguiente forma:
Sin embargo si se le pasa el mini sistema de protección que cifra y elimina las rutinas:
Como se pudo observar parte de la función que elegí queda cifrada y en ejecución si se ejecuta más de una vez esta se elimina del código asignando opcodes de NOP.
Desventaja:
Requiere deshabilitar el ASLR lo cuál no es lo usual hacerlo dado a que esto está habilitado por defecto para evitar exploits.
Cosas para terminar:
Mejorar la detección de las funciones que marcan el que código cifrar y/o eliminar.
Enlace al repositorio:
https://github.com/BloodSharp/CodeObfuscation
B#