2

最近,我研究使用 OnGuard 来帮助诚实的人遵守他们的原则。我同意这里许多人所表达的观点,即没有任何许可系统可以保护您免受想要使用您的软件并且不想为此付费的人的侵害。另一方面,我想避免让其他人太容易为我的程序创建有效密钥。

在研究了手册和示例之后,我在主表单的代码中添加了以下内容:

const
  TheKey: TKey = ($4A,$62,$F3,$2B,$9C,$D2,$84,$BF,$CB,$04,$0A,$C3,$3D,$11,$47,$1A);


function TfrmMain1.MakeCode(sName, sNumber: String; dtExpiration: TDate): String;
var Key: TKey;
    Code: TCode;
    sCode: String;
begin
  Key := TheKey;
  InitRegCode(Key, sName + ' - ' + sNumber, dtExpiration, Code);
  sCode := BufferToHex(Code, SizeOf(Code));
  Insert('-', sCode, 13);
  Insert('-', sCode, 09);
  Insert('-', sCode, 05);
  Result := sCode
end;

function TfrmMain1.TestCode(sName, sNumber, sTestCode: String; dtExpiration: TDate): Boolean;
var Key: TKey;
    Code: TCode;
    sCode: String;
begin
  sCode := MakeCode(sName, sNumber, dtExpiration);

  Result := SameText(sCode, sTestCode);
end;

这带来了一些问题:

  1. 似乎是正确的使用方法?我宁愿不将它们的组件添加到我的表单中。

  2. 既然 OnGuard 源是可用的,黑客就不能对我将选择的密钥进行逆向工程并生成有效的发布代码吗?因此,我是否应该在代码中添加一些额外的混淆,或者我可能只是削弱系统。

  3. Key 在这里设置为常数。它不会在代码中显示为连续字节并且易于复制吗?

  4. 我的程序将需要(至少)年度更新,我的计划是通过年度订阅许可它。在我的程序中将年份添加为常量并在几个地方针对该年份测试过时的用户条目是否会更强。

这里有 4 个问题密切相关且非常具体。在四个单独的条目中询问这些似乎会更尴尬,并且必须添加上下文参考,但如果这样更可取,我会很高兴这样做。感谢您的帮助。

杰克

4

3 回答 3

2
  constructor TLincenceManager.Create;
  begin
    FSpecialCode := TOgSpecialCode.Create(nil);
    FSpecialCode.OnGetModifier := OgNetCodeGetModifier;
    FSpecialCode.OnChecked := OgNetCodeChecked;
    FSpecialCode.OnGetCode := OgNetCodeGetCode;
    FSpecialCode.OnGetKey := OgNetCodeGetKey;
    FSpecialCode.AutoCheck := False;
  end;

  function TLincenceManager.InitializeLicenceCode: Boolean;
  begin
    Result := FSpecialCode.CheckCode(True) = ogValidCode;
  end;

  procedure TLincenceManager.OgNetCodeChecked(Sender: TObject; Status: TCodeStatus);
  begin
    case Status of
      ogValidCode    : FMaxUsers := FSpecialCode.GetValue;
      ogInvalidCode  : FMaxUsers := 0;
      ogPastEndDate  : FMaxUsers := 0;
      ogDayCountUsed : FMaxUsers := 0;
      ogRunCountUsed : FMaxUsers := 0;
      ogNetCountUsed : FMaxUsers := 0;
      ogCodeExpired  : FMaxUsers := 0;
    else
      FMaxUsers := 0;
    end;
  end;

  procedure TLincenceManager.OgNetCodeGetCode(Sender: TObject; var Code: TCode);
  var
    FileName: string;
    SerialData: string;
    LicenceData: TStringList;
  begin
    FileName := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
    FileName := FileName + cLicenseFileName;
    SerialData := '';

    LicenceData := TStringList.Create;
    try
      if FileExists(FileName) then
      begin
        LicenceData.LoadFromFile(FileName);
        SerialData := LicenceData.Values['Serial'];
      end;

      {convert to proper form}
      HexToBuffer(SerialData, Code, SizeOf(Code));
    finally
      LicenceData.Free;
    end;
  end;

  procedure TLincenceManager.OgNetCodeGetKey(Sender: TObject; var Key: TKey);
  const
    CKey : TKey = ($4A,$62,$F3,$2B,$9C,$D2,$84,$BF,$CB,$04,$0A,$C3,$3D,$11,$47,$1A);
  begin
    Key := CKey;
  end;

  procedure TLincenceManager.OgNetCodeGetModifier(Sender: TObject; var Value: Integer);
  begin
    Value := GenerateMachineModifierPrim;
  end;
  1. 我已经发布了我这样做的方式。我不使用“视觉”组件。我这样做的方式就是要走的路,在您的情况下,您只需应用日期修饰符(我有机器修饰符)

  2. 没有,理论上没有。用于生成许可证的密钥至关重要。如果您有密钥,您可以破解许可证。但是只有你不能的代码。这就像加密算法一样。你可以知道算法是如何工作的,但如果你没有密钥,你就无法破解它。看看XTEA。它非常简单,但很难破解。

  3. 是的,如果知道在做什么,可以从二进制文件中提取密钥。你可以在这里使用某种混淆。但我不会打扰。对于大多数人来说,这样的保护就足够了,所以如果你不制作下一个 MS Office,我不会打扰。人们对他们的产品很偏执。先卖了再考虑。哦,因为它不是一个字符串,所以无论如何都很难找到。

  4. 只需查看 onGuard 附带的计时演示,即可了解如何获得限时许可。但是请注意,只需简单地操纵计算机时钟就足以欺骗它。在我看来,最好的试用软件就是这样,它缺少一些重要的功能(保存按钮......)。在我看来,很难进行良好的计时赛。

于 2010-12-04T08:23:08.603 回答
2

我使用较低级别的 OnGuard API,而不是 Runner 建议的类。两者都可以正常工作,无论如何这些类最终都会调用较低级别的 API。以下是这些较低级别 API 方法的包装实用程序函数。

{ Used by you to generate the unlock code you send to your customer, do not include in the customer software }

function GenerateReleaseCode(const inAppKey : string; inExpiryDate : TDateTime; inRegCode : string) : string;
(* inAppKey is the byte sequence key you already have
   inRegCode can be anything, typically customers name
   Returns the release code for the customer to type into the software *)
var
  releaseCode : TCode;
  key : TKey;
begin
  HexToBuffer(inAppKey, key, SizeOf(TKey));
  InitRegCode(key, inRegCode, inExpiryDate, releaseCode);
  Result := BufferToHex(unlockCode, SizeOf(releaseCode));
end;

{ Used in your program to authenticate if the release code is valid - does not check for expiry }

function AuthenticateReleaseCode(const inReleaseCodeHexString : string; const inAppKey : TKey) : Boolean;
var
  releaseCode : TCode;
begin
  HexToBuffer(inReleaseCodeHexString, releaseCode, SizeOf(releaseCode));
  Result := IsRegCodeValid(inAppKey, releaseCode);
end;

{ Used in your program to test if the license has expired }

function UnlockCodeExpiryDate(const inReleaseCodeHexString : string; const inAppKey : TKey) : TDateTime;
var
  releaseCode : TCode;
begin
  HexToBuffer(inReleaseCodeHexString, releaseCode, SizeOf(releaseCode));
  Result := GetExpirationDate(inAppKey, releaseCode);
end;

我确实广泛使用 OnGuard,但仅用于盗版问题不大的企业软件。如果您正在销售消费者软件并且担心盗版,我建议您使用更强大的解决方案,例如加密 exe 的商业版权保护库。

即使这样,您也可以减慢饼干的速度,但您无法阻止它们。

于 2010-12-04T08:47:52.367 回答
2

3)您应该“分散”密钥,并且可能以某种方式计算其中的一部分。识别密钥越简单,绕过保护当然越简单。但是,如果在适当位置的简单 JMP 指令将绕过整个保护检查,那么即使是复杂的密钥也是无用的。这些支票也应该不止一张,而且还散落在各处。

4) 小心使用此类许可证 - 通常用户不喜欢它们,除非年费也意味着一些感知价值(即防病毒软件为您提供更新签名,或 GPS 应用程序更新地图)。仅仅强迫用户按年付费可能对你来说看起来不错,但对用户来说却不是,即使你添加了他们可能认为无用的新功能。如果应用程序停止工作就更糟了。当具有相同功能但没有年费的 Windows 应用程序可用时,这是杀死许多 Unix 应用程序的问题之一。我知道许多公司都在考虑回归这种模式——它是否会成功还有待观察。

于 2010-12-04T22:18:20.597 回答