Подтвердить что ты не робот

Как склеить или скрыть строку в Delphi EXE?

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

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

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

4b9b3361

Ответ 1

Очень простой способ - хранить строки, запутанные методом 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;

Немного сложнее было бы использовать шифр Цезаря или Шифер Vigenère.

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

Обновление

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

В качестве примера ниже я даю строку, запутанную с помощью Vienère cihper:

Xlc tsrgcdk sj 'vrivem mw cei sd kli acirivqhfriw cw qsbsir tfmjmgw, rrh biimrk hyi pygk gilhlvc mf ws, wk leq rpws pvgsqc fj agrvwtvcou mrrsiiwx we izcfp-hew cmji, rpxlmixl ml r piqg xigfbzgep zrrkyyuv. Mlrvih, hyi qmrvvr qctmixw vbtpmwkw ilsikc qclvgiq ks wsqy er soxirr klex hyi ilhzvi cbmmvslavrx mt xli Srvxl wj irboekivcr. Г-н hymw qstxmsl, ai uwcp mljvwxmeoki xfs tlcqwtep zojmw mt xli seivkw tsrgcdk.

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

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

Взаимопомощь m vjsy-tombox zguol ap ahqovz d uwk sbze w conz pe biusvth pagh h njsx. Io puvyeq, fl cjsx xic vmovdq zappzjvz, vnjnatl frcb vy dtmd vhxkt fto 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 SEK (100 шведских крон)!

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

Обновление

Как просил Уоррен П, я использую следующий код для шифрования/дешифрования 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;

Ответ 2

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

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

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