破解对象: luaide
破解目的:学习如何破解vscode插件
破解背景:
vsscode用了这么多年,安装了很多插件,其中luaide插件是收费的. 说实话,100块并不贵, 我本来准备买的.
结果我想加入luaide群,问几个插件相关问题,结果需要回答验证码.太扯了. 既然有7天试用,为何还要入群权限?真搞不懂
一般群我也懒得加,反正加入群,基本上是划水,没什么软用.
刚好之前没有破解vscode插件经验, 那就拿这个练手好了. 纯属破解学习用, 不做非法用途.
我破解的过程中,发现luaide作者还是很用心的, 对防破解用心了,对lua调试插件用心了,对文档用心了, 代码质量不错. 这个插件不贵, 建议lua开发同学购买.
有一个用户系统, 在线统计等功能, 这个肯定得需要一台服务器. 这些都是成本.
这个破解花了我好几个晚上,其中有几个晚上,由于对VScode工具的实现不熟悉,vscode插件开发流程不熟悉, 所以一直在探索,一直在走弯路.
这是我当时想问的:
插件有不完美的地方, 想调试要在main.lua中新增几行代码
这样会污染源文件main.lua.可不可以不污染?
当然我本人是可以解决的这个问题的, 就是不知道luaide作者是如何想的.
方案是新增一个文件, 名字叫debug2.lua. 把需要新增的几行代码写在 debug2中, 然后在require "main"
修改AppDelegate文件, 如果是DEBUG模式,就 执行 debug2文件 否则就是 main文件.
发布的时候肯定都是release模式, 所以没有任何影响.
当然还有一个方案, 修改引擎,让config.json 使其在 mac平台或者win平台生效. 直接修改entry字段的内容就OK
终极方案:
我觉得这个事情应该可以完全插件处理的, 包括端口啥的可以自动分配处理. 不需要使用者额外再加任何代码.
这个得luaide插件作者来做吧, 我做的话就严重违法了. 即使做了,也顶多自己使用, 浪费时间,没有啥意义.
加的几行代码也仅仅是拷贝, 时间上无伤大雅.
插件安装目录:
~/.vscode/extensions/kangping.luaide-1.1.3
当我用vscode打开这个目录的时候, 找到了.node文件, 我以为是node项目, 用node各种版本去尝试调试它, 一直报错.
没有一个nodejs版本是支持x64_69版本的. 这个就让我很郁闷了. 只能换个思路, 直接调试vscode 编辑器. 因为插件是寄生在编辑器上的.
code 仅仅是一个shell脚本, 实质上真正调用的是 Electron可执行程序. 查了一下资料, 它是跨平台的应用框架.
和nodejs很像, 都是在v8上实现的, 所有逻辑都是js 或者 .node文件.
查找了一下Electron调试方法,发现可以调试,那太完美. 初始化的数据是 luaide.info 这个数据是加密, 在.node文件中进行解密.
从这个.node的文件逻辑中可以看到luaide原来的逻辑是啥样的:
class Persisten_1{
getScriptValue()
initWarp()
static createNew()
}
js 层面有3个方法:[
init,
getScriptValue,
luaIdecreate
]
createNew的实现
很明显这个是一个单例, 没什么好说的.
其实关键还是在于init函数, 和getScriptValue
init 函数功能加载luaide.info文件, 然后按照换行符切割, 保存到scriptmap中
getScriptValue函数的功能是根据key值获取脚本值, 这里有一个解密的过程, 本人懒得分析怎么解密了, 这里直接获取结果就好.
通过断点调试发现确实可以拿到数据. 接下来就好办了.
在readFileSync函数包装一层,先保存到文件. 文件名为 ${key}.js
fs.readFileSync = function (path, options) { var newPath = path.replace(/\\/g, "/"); var lastIndex = newPath.lastIndexOf("/") if(lastIndex > -1){ newPath = newPath.substring(lastIndex+1) newPath = newPath.replace(".js","") } var value = luaideIde.getScriptValue(newPath) if (!!value) { fs.writeFile(`${tempPath}/${newPath}.js`, value, { 'flag': 'w' }, function(err) { if (err) { throw err; } console.log('OK:',newPath); }); return value; }else { return readFileSync(path, options); } };
最后所有代码都已经拿到了,效果如图:
有了代码,接下来想怎么玩耍就怎么玩耍了.
我发现作者真是煞费苦心啊, 防破解方面是花了大功夫了, 发现部分代码, 是走的网络. aes解密后,动态执行代码.
看了一下代码, 代码量很多,并且质量不错, 花100块还是很划算的.
声明: 本人破解的软件, 破解的代码, 百分百不会放到网上,全部仅供个人娱乐. 学习使用.
launch.json
// A launch configuration that launches the extension inside a new window // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 { "version": "0.2.0", "configurations": [ { "name": "Run Extension", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}" ] }, { "name": "Extension Tests", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/test/suite/index" ] } ] }
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var fs = require("fs"); function activate(context) { var fss = fs.readFileSync; fs.readFileSync = function(path, op) { return fss(path, op); }; const vscode = require("vscode"); var path = require("path"); var fileName = process.platform + "_" + process.arch + "_" + process.versions.modules + ".node"; var extensionPath = vscode.extensions.getExtension("kangping.luaide") .extensionPath; var libpath = path.join(extensionPath, "runtime", fileName); var hotlib = require(libpath); // new Function("require", "context", "hotlib", "luaIdeStart(require,context,hotlib);")(require, context,hotlib) luaIdeStart(require, context, hotlib); } function saveFiles(extensionPath, luaideIde) { let list = [ "ApiInit", "ApiUtils", "AutoLuaComment", "Base64", "BaseChildProcess", "BreakPointData", "CacheCompletionInfo", "ChangeCaseExtension", "CheckDebug", "CheckLuaDebugFile", "CommentLuaCompletionManager", "Common", "ConstInfo", "CreateFunction", "CreateMoudleFunction", "CreateNewTemplate", "CreateTemplateFile", "DCommon", "DebugCommon", "DebugReLoadFile", "DownLoad", "ExInit", "ExtensionManager", "FileCompletionItemManager", "FunctionCall", "FunctionParameter", "GVarRefNameInfo", "HttpClient", "LoadLuaScript", "LoadScriptResponse", "LoadStringTest", "LuaCheckDoEnd", "LuaCheckLuaInfos", "LuaCheckRepeat", "LuaCheckReturn", "LuaCheckUnary", "LuaChuckInfo", "LuaComment", "LuaCompletionItemControler", "LuaCompletionItemFunControler", "LuaCompletionItemGolbalControler", "LuaCompletionItemProvider", "LuaCompletionItemProviderUtils", "LuaDebug", "LuaDefinitionProvider",