Как скрыть строку в двоичном коде? - PullRequest
61 голосов
/ 31 августа 2009

Иногда полезно скрыть строку из двоичного (исполняемого) файла. Например, имеет смысл скрыть ключи шифрования от двоичных файлов.

Когда я говорю «скрыть», я имею в виду усложнение поиска строк в скомпилированном двоичном файле.

Например, этот код:

const char* encryptionKey = "My strong encryption key";
// Using the key

после компиляции создает исполняемый файл со следующим в его разделе данных:

4D 79 20 73 74 72 6F 6E-67 20 65 6E 63 72 79 70   |My strong encryp|
74 69 6F 6E 20 6B 65 79                           |tion key        |

Вы видите, что наша секретная строка может быть легко найдена и / или изменена.

Я мог бы спрятать строку ...

char encryptionKey[30];
int n = 0;
encryptionKey[n++] = 'M';
encryptionKey[n++] = 'y';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 's';
encryptionKey[n++] = 't';
encryptionKey[n++] = 'r';
encryptionKey[n++] = 'o';
encryptionKey[n++] = 'n';
encryptionKey[n++] = 'g';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 'e';
encryptionKey[n++] = 'n';
encryptionKey[n++] = 'c';
encryptionKey[n++] = 'r';
encryptionKey[n++] = 'y';
encryptionKey[n++] = 'p';
encryptionKey[n++] = 't';
encryptionKey[n++] = 'i';
encryptionKey[n++] = 'o';
encryptionKey[n++] = 'n';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 'k';
encryptionKey[n++] = 'e';
encryptionKey[n++] = 'y';

… но это не очень хороший метод. Есть идеи получше?

PS: я знаю, что простое сокрытие секретов не работает против решительного злоумышленника, но это намного лучше, чем ничего ...

Кроме того, я знаю об ассиметричном шифровании, но в данном случае это неприемлемо. Я выполняю рефакторинг существующего приложения, которое использует шифрование Blowfish и передает зашифрованные данные на сервер (сервер расшифровывает данные с помощью того же ключа).

Я не могу изменить алгоритм шифрования, потому что мне нужно обеспечить обратную совместимость. Я не могу даже изменить ключ шифрования.

Ответы [ 20 ]

2 голосов
/ 31 августа 2009

Вы можете закодировать строку с использованием некоторой тривиальной кодировки, например, xor с двоичным кодом 01010101. Без реальной защиты, конечно, но мешает использование таких инструментов, как string.

2 голосов
/ 31 августа 2009

Вот пример того, что они объяснили, но имейте в виду, что это будет просто сломано любым, кто является "хакером", но остановит детишек с помощью шестнадцатеричного редактора. Приведенный мною пример просто добавляет значение 80 и вычитает из него индекс, а затем снова создает строку. Если вы планируете хранить это в двоичном файле, есть множество способов преобразовать строку в массив byte [].

Когда у вас это работает в вашем приложении, я бы сделал "математику", которую я использовал, немного более сложной

Чтобы было понятно, для тех, кто не понимает .... Вы шифруете строку перед ее сохранением, чтобы она НЕ сохранялась в виде открытого текста. Если зашифрованный текст никогда не изменится, вы даже не включите в свой выпуск функцию шифрования, у вас есть только дешифрованная. Поэтому, когда вы хотите расшифровать строку, вы читаете файл, а затем дешифруете содержимое. Это означает, что ваша строка никогда не будет храниться в файле в текстовом формате.

Вы также можете, конечно, хранить зашифрованную строку в виде строки констант в своем приложении и дешифровать, когда вам это нужно, выбрать подходящую для вас проблему в зависимости от размера строки и частоты ее изменения.

string Encrypted = EncryptMystring("AAbbBb");
string Decrypted = DecryptMystring(Encrypted);

string DecryptMystring(string RawStr)
    {
        string DecryptedStr = "";
        for (int i = 0; i < RawStr.Length; i++)
        {
            DecryptedStr += (char)((int)RawStr[i] - 80 + i);
        }

        return DecryptedStr;
    }

    string EncryptMystring(string RawStr)
    {
        string EncryptedStr = "";
        for (int i = 0; i < RawStr.Length; i++)
        {
            EncryptedStr += (char)((int)RawStr[i] + 80 - i);
        }

        return EncryptedStr;
    }
2 голосов
/ 31 августа 2009

Если вы храните ключ шифрования в обратном порядке («yek noitpyrcne gnorts yM»), а затем переворачиваете его в своем коде (String.Reverse), это помешает простому поиску в двоичном коде текста вашего ключа шифрования.

Чтобы повторить точку зрения, высказанную каждым другим здесь, однако, это практически ничего не даст вам в плане безопасности.

1 голос
/ 23 мая 2015

Вы можете использовать библиотеку c ++ , которую я разработал для этой цели. Еще одна статья , которую гораздо проще реализовать, выиграла как лучшая статья c ++ за сентябрь 2017 года.

0 голосов
/ 28 марта 2016

Вот скрипт на perl для генерации запутанного c-кода, чтобы скрыть незашифрованный пароль от программы «strings».

  obfuscate_password("myPassword123");

  sub obfuscate_password($) {

  my $string = shift;
  my @c = split(//, $string);
  push(@c, "skip"); # Skip Null Terminator
                    # using memset to clear this byte
  # Add Decoy Characters
  for($i=0; $i < 100; $i++) {
    $ch = rand(255);
    next if ($ch == 0);
    push(@c, chr($ch));
  }                     
  my $count1 = @c;
  print "  int x1, x2, x3, x4;\n";
  print "  char password[$count1];\n";
  print "  memset(password, 0, $count1);\n";
  my $count2 = 0;
  my %dict  = ();
  while(1) {
    my $x = int(rand($count1));
    $y = obfuscate_expr($count1, $x);
    next if (defined($dict{$x}));
    $dict{$x} = 1;
    last if ($count2+1 == $count1);
    if ($c[$x] ne "skip") {
      #print "  $y\n";
      print "  $y password[x4] = (char)" . ord($c[$x]) . ";\n";
    }
    $count2++;
  }
  }

  sub obfuscate_expr($$) {
    my $count  = shift;
    my $target = shift;
    #return $target;

    while(1) {

       my $a = int(rand($count*2));
       my $b = int(rand($count*2));
       my $c = int(rand($count*2));
       next if (($a == 0) || ($b == 0) || ($c == 0));
       my $y = $a - $b;
       #print "$target: $y : $a - $b\n";
       if ($y == $target) {
          #return "$a - $b + $c";
          return "x1=$a; x2=$b; x3=$c; x4=x1-x2+x3; x5= +=x4;";
       }
    } 
  }
0 голосов
/ 28 марта 2016

создайте функцию, которая присваивает ваш пароль статическому массиву символов и возвращает указатель на эту функцию. Затем запустите эту функцию через программу запутывания.

Если программа хорошо работает. должно быть невозможно прочитать ваш простой текстовый пароль с помощью шестнадцатеричного редактора, чтобы проверить двоичный файл программы. (по крайней мере, не без обратного инжиниринга языка ассемблера. Это должно остановить всех детей сценариев, вооруженных «строками» или шестнадцатеричными редакторами, за исключением преступно-безумного хакера, которому нечем потратить свое время.)

0 голосов
/ 10 декабря 2015

Я предлагаю m4 .

  1. Храните строку с макросами вроде const string sPassword = _ENCRYPT("real password");

  2. Перед сборкой разверните макросы до зашифрованной строки с помощью m4 , чтобы ваш код выглядел как const string sPassword = "encrypted string";

  3. Расшифровка в среде выполнения.

0 голосов
/ 29 сентября 2015

Зашифруйте ключ шифрования другим кодом. Покажите изображение другого кода пользователю. Теперь пользователь должен ввести ключ, который он видит (как капчу, но всегда один и тот же код). Это также делает невозможным предсказание кода другими программами. При желании вы можете сохранить (соленый) хеш-код для проверки ввода пользователя.

0 голосов
/ 23 октября 2012

Интересно, если после того, как вы сначала скрыли это, как уже упоминали другие, вы могли бы встроить вашу строку в блок сборки, чтобы она выглядела как инструкция. Тогда вы могли бы иметь «if 0» или «goto just_past_string_assembly», чтобы перепрыгнуть через «код», который действительно скрывает вашу строку. Вероятно, для извлечения строки из кода потребуется немного больше работы (единовременная стоимость кодирования), но это может оказаться немного более неясным.

0 голосов
/ 01 сентября 2009

Я думаю, вы хотите, чтобы это выглядело как инструкция, ваш пример

х [у ++] = 'М'; х [у ++] = 'у'; ...

Сделал бы именно это, длинная последовательность повторяющихся инструкций с небольшим изменением может выделиться, и это было бы плохо, рассматриваемый байт может быть закодирован в инструкции как есть, и это было бы плохо, так что, возможно, метод xor и, возможно, некоторые другие приемы, чтобы сделать этот длинный фрагмент кода не выделяющимся, возможно, некоторые фиктивные вызовы функций. Зависит также от вашего процессора, например, ARM очень легко смотреть на двоичные данные и выбирать инструкции из данных и оттуда (если вы ищете ключ по умолчанию), чтобы, возможно, выбрать то, что может быть ключом, потому что это данные, но это не так, и напасть на это. Аналогично, блок похожих инструкций с изменяющимся непосредственным полем, даже если у вас есть компилятор или данные с константой.

...