本帖最后由 CrLf 于 2015-4-27 20:58 编辑
碰到变量加花的加密批处理是一件很蛋疼的事情,手工解密费时费力,用预处理来解密又不能对代码中的 set 随机应变
现有的做法基本都是利用预处理来解析,其实之前也写过(嗯,代码在这儿),本来想写个加强版的 bat,后来觉得预处理易,解析 set 难...
考虑到日后改写 js 版 cmd 的可能性(就像联盟的那个在线 cmd——我是懒得搞的,不过如果有人要做,代码可以随便取用不客气),索性用 js 实现
写了个框架,基本实现了初步的语法解析,能够判断代码块、&&、||、句柄、内部命令名称、读写变量
函数名应该比较直观了,大概看一下带注释的主体内容(10~45行)也就知道怎么用了,再不懂就问我
本脚本的优势:
1、静态解析,可尝试解密安全性不确定的加密脚本
2、能解析出脚本中的 set 命令,并更新环境变量
3、支持代码块
目前的已知缺陷有:
1、静态解密天生的硬伤,因流程控制语句的结果不确定,所以无法预知脚本的执行顺序
2、目前只实现了 set 命令的基础语法,尚不能处理 set 命令的 /a、prompt、path 以及其他可改变环境变量的命令
3、还未添加对动态环境变量的支持,不过对解密的影响好像不大
4、对 if 命令的兼容性很差
加密.txt 的内容可以参照以下几贴:
http://www.bathome.net/thread-27912-1-1.html(此例效果最好,因为加密时未使用系统变量,比较恒定)
http://www.bathome.net/thread-35380-1-1.html(此例使用系统变量加密,可能因环境不同而无法执行)
http://www.bathome.net/thread-17490-1-1.html(同上)- 1>1/* :
- @echo off
- cscript -nologo -e:jscript "%~0" <解密.txt | more
- pause & exit /b
- */
-
- var undefined = void 0
- var arrCodeBlock = []
-
- while(!WScript.StdIn.AtEndOfStream){
- var line_base = WScript.StdIn.ReadLine()
- //循环读取一行
-
- var line_analyze = analyze_ExpandString(line_base)
- //对该行中的 % 进行扩展
-
- arrCodeBlock.push(line_analyze)
- //“压栈”到代码块数组
-
- if(!test_AtEndOfCodeBlock&&!WScript.StdIn.AtEndOfStream)continue
- //若测试发现代码块未结束则继续读取下一行
-
- var text_CodeBlock = arrCodeBlock.join('\n')
- //连接代码块数组
-
- WSH.Echo(text_CodeBlock)
- //输出代码块
-
- var text_CodeBlock = analyze_CleanCrLf(text_CodeBlock)
- //行格式化
-
- var split_CodeBlock = analyze_Split(text_CodeBlock)
- //根据 | 和 & 拆分代码块为多条命令
-
- for(var i=0;i<split_CodeBlock.length;i++){
- split_CodeBlock[i] = analyze_Handle(split_CodeBlock[i])
- //解析一条语句中的句柄
-
- split_CodeBlock[i] = analyze_Command(split_CodeBlock[i])
- //解析一条语句中的命令
- }
-
- arrCodeBlock = []
- //清空代码块
- }
-
-
-
- function test_AtEndOfCodeBlock(strText){
- var tmpText = strText
- .replace(/[<>&|]/g,' ')
- .replace(/\^[\s\S]|"[^"\n]*"|[^()]\(|\)[^()]/g,' ')
- .replace(/[^()]+/g,'')
-
- while(/\(\)/.test(tmpText)){
- tmpText=tmpText.replace(/\(\)/g,'')
- }
-
- return tmpText.length == 0
- }
-
-
-
- function analyze_CleanCrLf(strText){
- return strText
- .replace(/\r\n/g,'\n')
- .replace(/\^\n/g,'')
- }
-
- function analyze_ExpandString(strText){
- return strText
- .replace(
- /%([0-9])|%:|%[^%]*%|%$/g,
- function(strText,intArgv){
- if(strText==='%')return ''
-
- if(strText==='%%')return strText
-
- if(strText==='%:')return ':'
-
- if(intArgv !== undefined)return strText //return WScript.Arguments.length>intArgv ? WScript.Arguments(intArgv) : ''
-
- return analyze_Variable(strText.replace(/%/g,''))
- }
- )
- }
-
- function analyze_Variable(strText){
-
- var match = strText.match(/([^:]+)(?::(.*))?/)
- var variableName = match[1]
- var variableCode = match[2] ? match[2] : ''
-
- var ws = new ActiveXObject("Wscript.Shell")
- var variableValue = ws.ExpandEnvironmentStrings('%'+variableName+'%')
-
- if(!variableCode)return variableValue
- //扩展普通变量
-
- var match = variableCode.match(/^~\s*(-?0x[0-9a-f]+|-?[0-9]+)?,?\s*(-?0x[0-9a-f]+|-?[0-9]+)?$/i)
- if(match){
- var splitStart = match[1] ? match[1]*1 : 0
- var splitLength = match[2] ? match[2]*1 : 8191 - variableName.length
-
- return cut(variableValue,splitStart,splitLength)
- }
- //扩展变量截取
-
- var match = variableCode.match(/^([^=]+)=?(\*)?([s\S]+)?$/)
- if(match){
- var replaceFrom = match[1].replace(/\W/g,'\\$&')
- var replaceHead = !!match[2]
- var replaceTo = match[3] ? match[3].replace(/\$/g,'$$$$') : ''
-
- if(replaceHead){
- return variableValue.replace(new RegExp('^.*?'+replaceFrom,'i'),replaceTo)
- } else {
- return variableValue.replace(new RegExp(replaceFrom,'ig'),replaceTo)
- }
- }
- //扩展变量替换
-
- return strText
-
- function cut(strText,intStart,intLength){
- if(intStart<0){
- variableValue = variableValue.substr(variableValue.length - -intStart)
- } else {
- variableValue = variableValue.substr(intStart)
- }
-
- if(intLength<0){
- return variableValue.substring(0,-intLength)
- } else {
- return variableValue.substr(0,intLength)
- }
- }
-
- }
-
-
- function analyze_Split(strText){
- var retArr = []
- var strText = strText.replace(
- /(^|&&?|\|\|?)?[\(\s]*([^\^\"&|]*(?:"[^"]*(?:"|$))*[^\^\"&|]*)?[\s\)]*/mg,
- function(strMatch,strSpecial,strCommand){
- retArr.push({strSpecial:strSpecial,strCommand:strCommand})
- }
- )
- return retArr
- }
-
-
- function analyze_Handle(objCommand){
- var tmpArr = []
- var strCommand = objCommand.strCommand.replace(
- /"[^"]*"|\^[<>]|([0-9]?)(&?[<>]|\>\>)([^\^\"\s&|<>]*(?:"[^"]*(?:"|$))*[^\^\"\s&|<>]*)?/mg,
- function(strMatch,intHandle,strSpecial,strTarget){
- intHandle = intHandle?intHandle:''
- strTarget = strTarget?strTarget:''
- if(strSpecial){
- tmpArr.push(' '+intHandle+strSpecial+strTarget)
- return ''
- } else {
- return strMatch
- }
- }
- )
- return {Command:strCommand,Handle:tmpArr}
- }
-
-
- function analyze_Command(objCommand){
- var RegExp_command = /^\s*(ASSOC|BREAK|CALL|CD|CHDIR|CLS|COLOR|COPY|DEL|ENDLOCAL|ERASE|EXIT|FOR|FTYPE|GOTO|GRAFTABL|IF|MD|MKLINK|MOVE|PATH|PAUSE|POPD|PROMPT|PUSHD|RD|REM|REN|SET|SETLOCAL|SHIFT|START|TIME|TITLE|TYPE|VER|VERIFY|VOL)(?:([ \t,;=]*|$)(.*))?$/mi
-
- var match = objCommand.Command.match(RegExp_command)
- if(match){
- objCommand.commandName = match[1]
- objCommand.spaceChar = match[2] ? match[2] : ''
- objCommand.commandValue = match[3] ? match[3] : ''
-
- if(objCommand.commandName.toUpperCase()==='SET'){
- Command_SET(objCommand.commandValue)
- }
- }
-
- return objCommand
- }
-
-
- function Command_SET(strText){
- strText = strText.replace(/^"(.*)"?$/,'$1')
-
- var match = strText.match(/^\s*([^=]+)=?([^\^\"&|]*(?:"[^"]*(?:"|$))*[^\^\"&|]*)?\s*/)
- if(match){
- var variableName = match[1]
- var variableCode = match[2] ? match[2] : ''
-
- var ws = new ActiveXObject("Wscript.Shell")
- ws.Environment("Process")(variableName) = variableCode
-
- }
- }
复制代码
|