Как зашифровать или скрыть строку в Delphi EXE? - PullRequest
14 голосов
/ 23 июля 2011

В настоящее время я разрабатываю приложение в Delphi, в котором мне нужно скрыть (обфусцировать) строку в исходном коде, например str := 'Example String'.
Почему?Потому что, если я открою EXE в текстовом редакторе и найду Example String, я найду строку через секунду ...

Я попытался использовать базовую транскрипцию HEX, такую ​​как #$65#$78#$61#$6d#$70#$6c#$65, но она переписывается вочистить во время компиляции.
Я искал упаковщики, но это не лучшее решение (PECompact может быть обнаружен как ложноположительное вредоносное ПО, UPX слишком легко де-UPX, ...).Я бы предпочел идею в своем внутреннем коде ...

Кто-то поставит меня на правильный путь.

Ответы [ 2 ]

20 голосов
/ 23 июля 2011

Очень простой метод - хранить обфусцированные строки методом ROT13 .

procedure ROT13(var Str: string);
const
  OrdBigA = Ord('A');
  OrdBigZ = Ord('Z');
  OrdSmlA = Ord('a');
  OrdSmlZ = Ord('z');
var
  i, o: integer;
begin
  for i := 1 to length(Str) do
  begin
    o := Ord(Str[i]);
    if InRange(o, OrdBigA, OrdBigZ) then
      Str[i] := Chr(OrdBigA + (o - OrdBigA + 13) mod 26)
    else if InRange(o, OrdSmlA, OrdSmlZ) then
      Str[i] := Chr(OrdSmlA + (o - OrdSmlA + 13) mod 26);
  end;
end;

function ROT13fun(const Str: string): string;
begin
  result := Str;
  ROT13(result);
end;

const
  ObfuscatedString = 'Guvf vf n frperg zrffntr.';

procedure TForm4.FormCreate(Sender: TObject);
begin
  ShowMessage(ROT13fun(ObfuscatedString));
end;

Чуть сложнее было бы использовать чип Цезаря или чип Вигенера.

Чтобы получить запутанные строки для использования в исходном коде, вы можете использовать приличный текстовый редактор, такой как мой Текстовый редактор Rejbrand или Wolfram | Alpha .

Обновление

ROT13 очень легко расшифровать, но этого может быть более чем достаточно для вашей ситуации, в зависимости от того, как это выглядит! По крайней мере, будет очень трудно идентифицировать строки в двоичном файле. Это займет некоторое реальное усилие, чтобы получить строки. (В конце концов, обычный пользователь даже не смотрит на двоичные файлы в шестнадцатеричном редакторе / текстовом редакторе!) Шифр ​​Цезаря - это очень простое обобщение шифра ROT13, и его также легко расшифровать. Действительно, есть только 25 разных «паролей». Шифр Vigenère гораздо сложнее, и для его взлома требуются действительно серьезные усилия ( особенно , поскольку вы точно не знаете , где в двоичном виде - строки).

В качестве примера ниже я приведу обфусцированную строку с помощью цихпера Vigenère:

XLC tsrgcdk SJ «vrivem» MW CEI с.о. кли acirivqhfriw CW qsbsir tfmjmgw, RRH biimrk HYI pygk gilhlvc М.Ф. WS, WK Leq РПВС pvgsqc FJ agrvwtvcou mrrsiiwx мы izcfp-HEW cmji, rpxlmixl мл г piqg xigfbzgep zrrkyyuv. Mlrvih, HII QMRVVR QCTMIXW VBTPWWWW ИЛСИКК QCLVGIK KS WSQY ER SOSCHIRR KLEX HYI ILHZVI CBMMVSLAVRX MT XLI SrvXL WJ IRBOEKIVCR. Мистер Химвхстхмсл, аи уквп млйввхмеоки хфс тлквтеп зоймвт мт хли сэйвкв цргкдк.

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

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

Мое мнение о том, что я думаю, что у тебя есть все, что нужно для этого. Io puvyeq, fl cjsx xic vmovdq zappzjvz, vnjnatl frcb vy dtmd vhxkt f to babtf davf. Uuxlhqb, khk aa dbn eumsuzq, auk saed vlpnbuuo ywlemz ue pnyl ttmxv. Pa ghof, fl cjsx kmbbzk atmd wv sfjtmxcl rtfysk cb yuta md jsy. Sqf nql njsx ly vs ilusrn o gok uxwupagupaz u.

И, наконец, текст ниже обфусцируется таким же образом, но, кроме того, все строки и специальные символы были удалены из строки:

cishkclruervutzgnyarkgzjsaqgsrzvmmrzweolpcnvbkxrvdnqrlurhpmhfaxsuoqncxgzqegnqmngaryfbgozpcgrkgzrrybybmouyzbbkoucbnrnsxkmcbywpllxhkoobmzoydrfvrkhpvsavmzocwjflouboymlotjcnqrirgucdrftllladcwtmnkqehjpmnafoobyvkvdaancbzeokdnsotkkawvanjkryculluyaoklpnojfnqrlatypznpalzocjunuxzdbnzntpqulplekxhrshpttjqyculkkjyxhxgxdozruwlbtkyrsuumkgslbyunabbkryfupvnafobhuoyyvqjlzgzpomc

Я призываю вас расшифровать эти три текста. Если кому-то удастся расшифровать последний, я обещаю дать этому человеку 100 шведских крон (100 шведских крон)!

Но, тем не менее, Уоррен П прав: если вам действительно требуется высокий уровень безопасности, который даже эксперты не смогут расшифровать, то вам следует использовать шифрование real .

Update

По просьбе Уоррена П, я использую следующий код для шифрования / дешифрования Vigenère:

const
  OrdBigA = Ord('A');
  OrdBigZ = Ord('Z');
  OrdSmlA = Ord('a');
  OrdSmlZ = Ord('z');

function imod(const x: integer; const y: integer): integer;
begin
  if x >= 0 then
    imod := x - floor(x/y) * y
  else
    imod := x + ceil(-x/y) * y;
end;

procedure Vigenère(var Str: string; const Key: string);
var
  n, i, o: integer;
  KeyChrs: TBytes;
begin

  n := length(Key);
  SetLength(KeyChrs, n);
  for i := 1 to n do
    if InRange(ord(Key[i]), OrdBigA, OrdBigZ) then
      KeyChrs[i - 1] := Ord(Key[i]) - OrdBigA
    else
      raise Exception.Create('Invalid character in Vigenère key.');

  for i := 1 to length(Str) do
  begin
    o := Ord(Str[i]);
    if InRange(o, OrdBigA, OrdBigZ) then
      Str[i] := Chr(OrdBigA + imod((o - OrdBigA + KeyChrs[(i-1) mod n]), 26))
    else if InRange(o, OrdSmlA, OrdSmlZ) then
      Str[i] := Chr(OrdSmlA + imod((o - OrdSmlA + KeyChrs[(i-1) mod n]), 26));
  end;

end;

function Vigenèref(const Str: string; const Key: string): string;
begin
  result := Str;
  Vigenère(result, Key);
end;

procedure VigenèreD(var Str: string; const Key: string);
var
  n, i, o: integer;
  KeyChrs: TBytes;
begin

  n := length(Key);
  SetLength(KeyChrs, n);
  for i := 1 to n do
    if InRange(ord(Key[i]), OrdBigA, OrdBigZ) then
      KeyChrs[i - 1] := Ord(Key[i]) - OrdBigA
    else
      raise Exception.Create('Invalid character in Vigenère key.');

  for i := 1 to length(Str) do
  begin
    o := Ord(Str[i]);
    if InRange(o, OrdBigA, OrdBigZ) then
      Str[i] := Chr(OrdBigA + imod((o - OrdBigA - KeyChrs[(i-1) mod n]), 26))
    else if InRange(o, OrdSmlA, OrdSmlZ) then
      Str[i] := Chr(OrdSmlA + imod((o - OrdSmlA - KeyChrs[(i-1) mod n]), 26));
  end;

end;

function VigenèreDf(const Str: string; const Key: string): string;
begin
  result := Str;
  VigenèreD(result, Key);
end;
0 голосов
/ 23 июля 2011

Вы можете использовать настоящую библиотеку шифрования, как в этот вопрос .Небольшая внешняя утилита может взять вашу исходную строку и преобразовать ее в статический массив байтов, который будет скомпилирован в ваше приложение, и будет расшифрован и восстановлен в памяти как строка.Это даст дополнительное преимущество, заключающееся в том, что он не будет выглядеть как ascii (диапазон 32..127) и не будет столь очевидным для случайных инспекторов, использующих шестнадцатеричный редактор.

Кроме того, реальное шифрование (даже 3DES илиBlowfish) было бы не так легко удалить, даже не посмотрев на ваш исходный код или перепроектировать ваши двоичные файлы, как это было бы с ROT13 или одним уровнем цезаря, но если ваш ключ (используемый для дешифрования / шифрования) сам по себене защищен, он не так безопасен, как вы могли бы надеяться.Мне было бы довольно легко подключить отладчик к вашему коду, даже к выпускной версии, а также восстановить и записать все строки в кучу строк во время выполнения, даже не потрудившись взломать ваше шифрование, даже когда вы используете настоящую библиотеку каквыше.Я согласен с Андреасом в том, что Vigenere кажется разумным количеством защиты и усилий для ваших целей, и я думаю, что ROT13 и одноуровневый Цезарь шифр являются своего рода смехотворными сами по себе.Обновление: Vignere, опубликованный Андреасом, блестящий, хотя, и я предпочитаю это большой толстой внешней библиотеке, в вашем случае.

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

...