前段时间换电脑,之前的部分软件需要重新激活。这里总结一下用到的软件的激活方式,以备不时之需。
如果有能力还请支持一下开发者。
star UML 3 是一个优秀的开源uml工具,是软件设计不可少的工具,但是价格实在是劝退门槛。以前记录的激活方式不能使用了,代码封装成了asar包。查了一下资料,软件仍然使用node js开发,使用asar打包。尝试安装asar解压,获取源码看看能不能找到
npm install -g asar
# asar使用全局安装,才能使用asar命令
找到代码包:StarUML.app/Contents/Resources/app.asar
解压到app文件夹就获取到所有的源码
asar extract app.asar app
找到文件:./app//src/engine/license-manager.js
我是通过find ./app/ -name '*license*'找到的,这算不算起名太规范的弊端(大雾)
该文件为验证license的方法。尝试阅读源码。
/*
* Copyright (c) 2013-2014 Minkyu Lee. All rights reserved.
*
* NOTICE: All information contained herein is, and remains the
* property of Minkyu Lee. The intellectual and technical concepts
* contained herein are proprietary to Minkyu Lee and may be covered
* by Republic of Korea and Foreign Patents, patents in process,
* and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Minkyu Lee (niklaus.lee@gmail.com).
*
*/
const {EventEmitter} = require('events')
const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
const UnregisteredDialog = require('../dialogs/unregistered-dialog')
const SK = 'DF9B72CC966FBE3A46F99858C5AEE'
// Check License When File Save
const LICENSE_CHECK_PROBABILITY = 0.3
var status = false
var licenseInfo = null
/**
* Set Registration Status
* This function is out of LicenseManager class for the security reason
* (To disable changing License status by API)
* @private
* @param {boolean} newStat
* @return {string}
*/
function setStatus (licenseManager, newStat) {
if (status !== newStat) {
status = newStat
licenseManager.emit('statusChanged', status)
}
}
/**
* @private
*/
class LicenseManager extends EventEmitter {
constructor () {
super()
this.projectManager = null
}
/**
* Get Registration Status
* @return {string}
*/
getStatus () {
return status
}
/**
* Get License Infomation
* @return {Object}
*/
getLicenseInfo () {
return licenseInfo
}
findLicense () {
var licensePath = path.join(app.getUserPath(), '/license.key')
if (!fs.existsSync(licensePath)) {
licensePath = path.join(app.getAppPath(), '../license.key')
}
if (fs.existsSync(licensePath)) {
return licensePath
} else {
return null
}
}
/**
* Check license validity
*
* @return {Promise}
*/
validate () {
return new Promise((resolve, reject) => {
try {
// Local check
var file = this.findLicense()
if (!file) {
reject('License key not found')
} else {
var data = fs.readFileSync(file, 'utf8')
licenseInfo = JSON.parse(data)
var base = SK + licenseInfo.name +
SK + licenseInfo.product + '-' + licenseInfo.licenseType +
SK + licenseInfo.quantity +
SK + licenseInfo.timestamp + SK
var _key = crypto.createHash('sha1').update(base).digest('hex').toUpperCase()
if (_key !== licenseInfo.licenseKey) {
reject('Invalid license key')
} else {
// Server check
$.post(app.config.validation_url, {licenseKey: licenseInfo.licenseKey})
.done(data => {
resolve(data)
})
.fail(err => {
if (err && err.status === 499) { /* License key not exists */
reject(err)
} else {
// If server is not available, assume that license key is valid
resolve(licenseInfo)
}
})
}
}
} catch (err) {
reject(err)
}
})
}
checkLicenseValidity () {
this.validate().then(() => {
setStatus(this, true)
}, () => {
setStatus(this, false)
UnregisteredDialog.showDialog()
})
}
/**
* Check the license key in server and store it as license.key file in local
*
* @param {string} licenseKey
*/
register (licenseKey) {
return new Promise((resolve, reject) => {
$.post(app.config.validation_url, {licenseKey: licenseKey})
.done(data => {
var file = path.join(app.getUserPath(), '/license.key')
fs.writeFileSync(file, JSON.stringify(data, 2))
licenseInfo = data
setStatus(this, true)
resolve(data)
})
.fail(err => {
setStatus(this, false)
if (err.status === 499) { /* License key not exists */
reject('invalid')
} else {
reject()
}
})
})
}
htmlReady () {
this.projectManager.on('projectSaved', (filename, project) => {
var val = Math.floor(Math.random() * (1.0 / LICENSE_CHECK_PROBABILITY))
if (val === 0) {
this.checkLicenseValidity()
}
})
}
appReady () {
this.checkLicenseValidity()
}
}
module.exports = LicenseManager
先看validate()方法,验证流程为从本地获取license.key文件,通过hash算法生成key串,通过post方法请求服务器,验证license是否有效。这是验证的主要方法。
然后还有checkLicenseValidity()方法,调用validate()方法验证,判断返回调用setStatus()方法,设置license状态。所以我们只要修改这个方法,让它忽视validate()方法的返回,始终调用setStatus()设置成true,应该就能绕过验证。
修改代码如下
checkLicenseValidity () {
this.validate().then(() => {
setStatus(this, true)
}, () => {
// setStatus(this, false)
// UnregisteredDialog.showDialog()
setStatus(this, true)
})
}
然后按照asar手册,再次打包代码,替换原文件
asar pack app app.asar
启动实验成功