【问题标题】:How to crypt or hide a string in Delphi EXE?如何在 Delphi EXE 中加密或隐藏字符串?
【发布时间】:2011-07-23 12:23:33
【问题描述】:

我目前正在用 Delphi 开发一个应用程序,其中我必须在源代码中隐藏(混淆)一个字符串,例如 str := 'Example String'
为什么 ?因为如果我在文本编辑器中打开 EXE 并搜索 Example String 我会在第二个找到字符串...

我尝试使用 #$65#$78#$61#$6d#$70#$6c#$65 之类的基本 HEX 转录,但它在编译时以清晰的形式重新转录。
我寻找了打包程序,但这不是最好的解决方案(PECompact 可以被检测为误报恶意软件,UPX 太容易反UPX,...)。我希望在我的内部代码中有一个想法......

有人会让我走上正确的道路。

【问题讨论】:

标签: string delphi obfuscation


【解决方案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;

稍微复杂一点的是使用 Caesar Chipher 或 Vigenère Chipher。

要获得要在源代码中使用的混淆字符串,您可以使用像我自己的Rejbrand Text EditorWolfram|Alpha 这样的体面的文本编辑器。

更新

ROT13 很容易破译,但对于您的情况,它可能绰绰有余,具体取决于它的外观!至少在二进制文件中识别字符串会变得非常困难。获得这些字符串需要付出一些真正的努力。 (毕竟,日常用户甚至不会在十六进制编辑器/文本编辑器中查看二进制文件!)凯撒密码是 ROT13 密码的一个非常简单的概括,也很容易破译。事实上,只有 25 个不同的“密码”。 Vigenère 密码要复杂得多,并且需要付出非常认真的努力才能破解(尤其是,因为您不知道字符串在二进制文件中的确切位置)。

作为一个例子,下面我给出了一个使用 Vigenère 密码混淆的字符串:

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, rpxlmixzgep ml r yuvqg. zigf 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。

当然可以扩展密码来处理数字和特殊字符,包括空格。它也可以混合大写和小写字母。那么破译将非常困难(尽管可能)。如果密码是已知单词,则可能更容易破译,该单词可以在字典中找到。如果是不是一个词,那就更安全了。

上面的文字是用一个你可以在足够大的字典中找到的词来混淆的。下面的文本使用无意义的字符串作为密码进行了混淆:

Miwzvjfy 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 P>

我挑战你破译这三个文本。如果有人能成功破译最后一个,我保证给这个人 100 SEK(100 瑞典克朗)!

但是,Warren P 仍然是对的:如果您真的需要高安全性,即使专家也无法破译,那么您应该选择一些 真正 > 加密。

更新

应 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;

【讨论】:

  • 嗯,真的很有趣!我现在就试试。谢谢 !这个问题我一直保持联系。
  • 完美运行!非常感谢你。目前我会留在ROT13,但我会了解凯撒。你的文本编辑器会很有帮助:)
  • +1 用于将法语 è 重音符号放入 Delphi 函数名称中。请在 Delphi 7 中尝试一下。 :-)
  • @Warren P:然后你还没有看到我的Möbius 函数!
  • 真的很好!正如你上面所说,ROT13 对我的情况来说已经足够了;但我会尽量让自己熟悉 Vigenère,以便将来更有效率。感谢您的时间和解释:)
【解决方案2】:

您可以使用真正的加密库,例如 this question。一个小的外部实用程序可以获取您的原始字符串并将其转换为静态字节数组,该数组将编译到您的应用程序中,并作为字符串在内存中解密和恢复。这将具有额外的好处,它看起来仍然不像 ascii(范围 32..127),并且对于使用十六进制编辑器的临时检查员来说不会那么明显。

此外,真正的加密(即使是 3DES 或 Blowfish)也不会像 ROT13 或单级凯撒密码那样,在不需要查看源代码或对二进制文件进行逆向工程的情况下被轻易删除,但是,如果您的密钥(用于解密/加密)本身没有受到保护,它也没有您希望的那么安全。我很容易将调试器附加到您的代码,甚至是发布版本,并在运行时恢复和记录字符串堆中的所有字符串,甚至无需费心破解您的加密,即使您使用真正的库作为多于。我同意 Andreas 的观点,即 Vigenere 似乎为您的目的提供了合理的保护和努力,我认为 ROT13 和单级凯撒密码本身就是可笑的。更新:不过,Andreas 发布的 vignere 非常棒,在你的情况下,我更喜欢它而不是一个庞大的外部库。

对于您将某些内容存储在文本文件中的特殊情况,我会编写一个小实用程序,可以将您的秘密加密并编码到您的源代码中,并至少将密钥存储在其他地方。这就像把你的弹药放在一个密码箱里,把它的钥匙放在别的地方。即使这样也不完美,但它可能比 ROT13 更好,这是所有玩具加密风格中最“玩具”的一种。

【讨论】:

  • 维吉尼亚密码比凯撒密码更难破译(ROT13 是凯撒密码的一个特例)。 (而且 ROT13 也是讨论的函数的唯一对合。)
  • 有任何 Vigenère 的代码示例吗?应该只是凯撒技法的组合吗?这是一个很酷的历史参考。来自 1553 的算法!如果生成的文本仍然是 ASCII 可读的,那么当十六进制编辑器查看生成的目标可执行文件时,它会像拇指一样突出。
  • 嗯,这是一个 Èpîc Hàck! Wày tø gò Àndrèàs!
  • 感谢沃伦的想法。另外,我不知道加密库,我会找到的。
猜你喜欢
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 2010-10-10
  • 2018-10-31
  • 2018-01-23
  • 2014-11-05
  • 2013-12-28
相关资源
最近更新 更多