@@ -61,6 +61,10 @@ function decodeObject(ast) {
6161 if ( ! Object . prototype . hasOwnProperty . call ( obj_node , name . name ) ) {
6262 return
6363 }
64+ if ( t . isIdentifier ( key ) && path . node . computed ) {
65+ // In this case, the identifier points to another value
66+ return
67+ }
6468 path . replaceWith ( obj_node [ name . name ] [ key . name ] )
6569 obj_used [ name . name ] = true
6670 }
@@ -112,23 +116,24 @@ function stringArrayV2(ast) {
112116 if (
113117 ! callee . isFunctionExpression ( ) ||
114118 callee . node . params . length !== 2 ||
115- args . length !== 2 ||
119+ args . length == 0 ||
120+ args . length > 2 ||
116121 ! t . isIdentifier ( args [ 0 ] )
117122 ) {
118123 return
119124 }
120125 const arr = callee . node . params [ 0 ] . name
121- const cmpV = callee . node . params [ 1 ] . name
122- const fp = `while (){try{if(== ${ cmpV } )else ${ arr } push(${ arr } shift())}catch(){${ arr } push(${ arr } shift())}}`
126+ // const cmpV = callee.node.params[1].name
127+ const fp = `(){try{if()break ${ arr } push(${ arr } shift())}catch(){${ arr } push(${ arr } shift())}}`
123128 const code = '' + callee . get ( 'body' )
124129 if ( ! checkPattern ( code , fp ) ) {
125130 return
126131 }
127132 obj . stringArrayName = args [ 0 ] . name
128133 // The string array can be found by its binding
129134 const bind = path . scope . getBinding ( obj . stringArrayName )
130- const def = bind . path . parentPath
131- obj . stringArrayCodes . push ( generator ( def . node , { minified : true } ) . code )
135+ const def = t . variableDeclaration ( 'var' , [ bind . path . node ] )
136+ obj . stringArrayCodes . push ( generator ( def , { minified : true } ) . code )
132137 // The calls can be found by its references
133138 for ( let ref of bind . referencePaths ) {
134139 if ( ref ?. listKey === 'arguments' ) {
@@ -172,12 +177,16 @@ function stringArrayV2(ast) {
172177 up2 . remove ( )
173178 }
174179 // Remove the string array
175- def . remove ( )
180+ bind . path . remove ( )
176181 // Add the rotate function
177182 const node = t . expressionStatement ( path . node )
178183 obj . stringArrayCodes . push ( generator ( node , { minified : true } ) . code )
179184 path . stop ( )
180- path . remove ( )
185+ if ( path . parentPath . isUnaryExpression ( ) ) {
186+ path . parentPath . remove ( )
187+ } else {
188+ path . remove ( )
189+ }
181190 }
182191 traverse ( ast , { CallExpression : find_rotate_function } )
183192 if ( obj . stringArrayCodes . length < 3 || ! obj . stringArrayCalls . length ) {
@@ -363,13 +372,18 @@ function decodeGlobal(ast) {
363372 function do_collect_remove ( path ) {
364373 // 可以删除所有已收集混淆函数的定义
365374 // 因为根函数已被删除 即使保留也无法运行
366- let name = path . node ?. left ?. name
367- if ( ! name ) {
368- name = path . node ?. id ?. name
375+ let node = path . node ?. left
376+ if ( ! node ) {
377+ node = path . node ?. id
369378 }
379+ let name = node ?. name
370380 if ( exist_names . indexOf ( name ) != - 1 ) {
371381 // console.log(`del: ${name}`)
372- path . remove ( )
382+ if ( path . parentPath . isCallExpression ( ) ) {
383+ path . replaceWith ( node )
384+ } else {
385+ path . remove ( )
386+ }
373387 }
374388 }
375389 function do_collect_func ( path ) {
@@ -445,6 +459,44 @@ function decodeGlobal(ast) {
445459 return true
446460}
447461
462+ function stringArrayLite ( ast ) {
463+ const visitor = {
464+ VariableDeclarator ( path ) {
465+ const name = path . node . id . name
466+ if ( ! path . get ( 'init' ) . isArrayExpression ( ) ) {
467+ return
468+ }
469+ const elements = path . node . init . elements
470+ for ( const element of elements ) {
471+ if ( ! t . isLiteral ( element ) ) {
472+ return
473+ }
474+ }
475+ const bind = path . scope . getBinding ( name )
476+ if ( ! bind . constant ) {
477+ return
478+ }
479+ for ( const ref of bind . referencePaths ) {
480+ if (
481+ ! ref . parentPath . isMemberExpression ( ) ||
482+ ref . key !== 'object' ||
483+ ! t . isNumericLiteral ( ref . parent . property )
484+ ) {
485+ return
486+ }
487+ }
488+ console . log ( `Extract string array: ${ name } ` )
489+ for ( const ref of bind . referencePaths ) {
490+ const i = ref . parent . property . value
491+ ref . parentPath . replaceWith ( elements [ i ] )
492+ }
493+ bind . scope . crawl ( )
494+ path . remove ( )
495+ } ,
496+ }
497+ traverse ( ast , visitor )
498+ }
499+
448500function mergeObject ( path ) {
449501 // var _0xb28de8 = {};
450502 // _0xb28de8["abcd"] = function(_0x22293f, _0x5a165e) {
@@ -673,7 +725,7 @@ function unpackCall(path) {
673725 if ( ! t . isIdentifier ( retStmt . argument . callee ) ) {
674726 return
675727 }
676- if ( retStmt . argument . callee . name !== prop . value . params [ 0 ] . name ) {
728+ if ( retStmt . argument . callee . name !== prop . value . params [ 0 ] ? .name ) {
677729 return
678730 }
679731 repfunc = function ( _path , args ) {
@@ -1328,6 +1380,7 @@ module.exports = function (jscode) {
13281380 console . log ( '提高代码可读性...' )
13291381 ast = purifyCode ( ast )
13301382 console . log ( '处理代码块加密...' )
1383+ stringArrayLite ( ast )
13311384 ast = decodeCodeBlock ( ast )
13321385 console . log ( '清理死代码...' )
13331386 ast = cleanDeadCode ( ast )
0 commit comments