haxqer / confluence

The simplest docker file of Confluence. Support v8.9.6(latest) v9.0.3(latest) and v8.5.15(lts)
420 stars 219 forks source link

AI for Confluence 插件破解失败 #78

Open gary0121 opened 3 weeks ago

gary0121 commented 3 weeks ago

激活成功 但是设置 license 被识别

Common Configuration

The license is suspected to be cracked. Please consider purchasing a legitimate license.

For further assistance, please visit: Support

voarsh2 commented 5 days ago

I saw this too. I haven't extracted the jar file to see what the plugin is doing to make this decision. Possibly it's not air-gapped supported, meaning they check on their side... or perhaps the licence expiry. I might have a look into this out of curiosity

voarsh2 commented 5 days ago

There's a specific function in the jar: image


  private boolean isLicenseCracked(PluginLicense license) {
    try {
      ZonedDateTime expiryZonedDate = null;
      if (ClassUtils.doesMethodExist(PluginLicense.class, "getExpiryDate")) {
        logger.debug("---> getExpiryDate method exists in PluginLicense class.");
        Option<DateTime> expiryDateOp = license.getExpiryDate();
        if (expiryDateOp.isDefined()) {
          DateTime expiryDate = (DateTime)expiryDateOp.get();
          expiryZonedDate = Instant.ofEpochMilli(expiryDate.getMillis()).atZone(ZonedDateTime.now().getZone());
        } 
      } else if (ClassUtils.doesMethodExist(PluginLicense.class, "getExpiryZonedDate")) {
        logger.debug("---> getExpiryZonedDate method exists in PluginLicense class.");
        Optional<ZonedDateTime> expiryZonedDateOp = license.getExpiryZonedDate();
        if (expiryZonedDateOp.isPresent())
          expiryZonedDate = expiryZonedDateOp.get(); 
      } else {
        logger.error("Neither getExpiryDate nor getExpiryZonedDate method exists in PluginLicense class.");
        return false;
      } 
      if (expiryZonedDate == null)
        return false; 
      logger.debug("---> expiryZonedDate: " + expiryZonedDate);
      ZonedDateTime currentDate = ZonedDateTime.now();
      long yearsBetween = ChronoUnit.YEARS.between(currentDate, expiryZonedDate);
      logger.debug("---> yearsBetween: " + yearsBetween);
      return (yearsBetween > 5L);
    } catch (Exception e) {
      logger.error("Error in isLicenseCracked: ", e);
      return false;
    } 
  }
}

As I suspected: The method isLicenseCracked seems to be checking for an unusual license expiration condition:

Method Detection:

It first tries to find an expiry date method in the PluginLicense class

Checks for two possible methods:

getExpiryDate() or getExpiryZonedDate()

Expiry Date Retrieval:

If getExpiryDate() exists, it converts the DateTime to ZonedDateTime If getExpiryZonedDate() exists, it directly uses that

Cracked License Logic:

The key condition is: yearsBetween > 5L This means the license is considered "cracked" if the expiry date is more than 5 years in the future

Potential Cracking Detection Strategies:

The method considers a license potentially "cracked" if:

  1. The expiry date is very far in the future (> 5 years) No valid expiry date can be retrieved

The way around this is to:

update the agent to generate a less than 5 year licence expiry, or to modify the file and recompile (which is harder)