String 如何在Delphi EXE中加密或隐藏字符串?

String 如何在Delphi EXE中加密或隐藏字符串?,string,delphi,obfuscation,String,Delphi,Obfuscation,我目前正在用Delphi开发一个应用程序,其中我必须在源代码中隐藏(模糊)一个字符串,如str:=“示例字符串” 为什么?因为如果我在文本编辑器中打开EXE并搜索示例字符串,我会在第二秒内找到该字符串 我试着使用基本的十六进制转录,比如#$65#$78#$61#$6d#$70#$6c#$65,但它在编译时被清晰地重新转录。 我寻找包装商,但这不是最好的解决方案(PECompact可以被检测为假阳性恶意软件,UPX太容易反UPX,…)。我希望在我的内部代码中有一个想法 有人会让我走上正确的道路。一

我目前正在用Delphi开发一个应用程序,其中我必须在源代码中隐藏(模糊)一个字符串,如
str:=“示例字符串”

为什么?因为如果我在文本编辑器中打开EXE并搜索
示例字符串
,我会在第二秒内找到该字符串

我试着使用基本的十六进制转录,比如
#$65#$78#$61#$6d#$70#$6c#$65
,但它在编译时被清晰地重新转录。
我寻找包装商,但这不是最好的解决方案(PECompact可以被检测为假阳性恶意软件,UPX太容易反UPX,…)。我希望在我的内部代码中有一个想法


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

一个非常简单的方法是存储被该方法混淆的字符串

稍微复杂一点的是雇佣凯撒·奇珀或维根埃·奇珀

要获得在源代码中使用的模糊字符串,可以使用像样的文本编辑器,如my own或

更新

ROT13很容易破译,但它可能对您的情况来说已经足够了,这取决于它的外观!至少在二进制文件中识别字符串会变得非常困难。要获得字符串需要一些实际的努力。(毕竟,每天的用户甚至不用在十六进制编辑器/文本编辑器中查看二进制文件!)凯撒密码是ROT13密码的一个非常简单的推广,也很容易破译。事实上,只有25种不同的“密码”。Vigenère密码要复杂得多,并且需要花费一些非常认真的努力才能破解(特别是因为您不知道字符串在二进制文件中的确切位置)

作为一个示例,下面我给出了一个使用Vigenère cihper进行模糊处理的字符串:

Xlc tsrgcdk sj‘vrivem’mw cei sd kli acirivqhfriw cw qsbsir tfmjmgw,rrh biimrk hyi pygk GILLVC mf ws,wk leq rpws pvgsqc fj agrvwtvcou mrrsiiwx我们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

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

上面的文字使用一个你可以在足够大的字典中找到的单词进行模糊处理。以下文本使用无意义字符串作为密码进行模糊处理:

Miwzvjfy m vjsy tombox zguol ap ahqovz d uwk sbze与njsx合作。佛罗里达州普维耶克市希克斯西区vmovdq zappzjvz,vnjnatl frcb vy dtmd vhxkt fto babtf davf。Uuxlhqb、khk aa dbn eumsuzq、auk saed VLPNBUO ywlemz和pnyl ttmxv。佛罗里达州帕戈夫市cjsx kmbbzk atmd wv sfjtmxcl rtfysk cb yuta md jsy。Sqf nql njsx ly vs ilusrn o gok Uxwupagaz u

最后,下面的文本以同样的方式进行模糊处理,但是-此外-所有空格和特殊字符都已从字符串中删除:

CISHKCLRUERVUTZGNYARKGZJSAQGSRZVMMRZWEOLPCNVBKKRvDnqLurhPmHfFaxSuoqNcxGzGzGzGzGzGzGzGzGzGzRyBYZBYBYBYBYBYBYBYBYBKKKKKKKKKKKKKYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYBYKKKK霍伊夫QJLZGZPOMC

我要求你破译这三段文字。如果有人能成功破解最后一个,我保证给这个人100瑞典克朗(100瑞典克朗)

但是,沃伦·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;

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

此外,真正的加密(即使是3DES或Blowfish)也不会像ROT13或单一级别的caesar cypher那样,在不需要查看源代码或对二进制文件进行反向工程的情况下轻易删除,但是,如果您的密钥(用于解密/加密)本身没有受到保护,它也不会像您希望的那样安全。对我来说,在运行时将调试器附加到您的代码(甚至是发布版本)并恢复和记录字符串堆中的所有字符串是非常容易的,甚至不用费心破解您的加密,即使您使用了上述真正的库。我同意安德烈亚斯的看法,维格纳似乎是一个合理的保护和努力,为您的目的,我认为ROT13和一个单级凯撒密码本身是一种可笑的。更新:Andreas发布的vignere非常出色,但我更喜欢它,而不是一个庞大的外部库


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

它不是“重新转录的”。这完全是一样的。@Andreas:是的,你说得对。我解释得不好。有点相关:
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;