This commit is contained in:
cilame 2023-06-05 19:13:30 +08:00
parent a92c75d52f
commit 1cfe3d6480
4 changed files with 271 additions and 33 deletions

View File

@ -1441,7 +1441,7 @@ function injectfunc(e, window) {
if (e["config-hook-cookie"] && e["config-hook-cookie-get"]){ if (e["config-hook-cookie"] && e["config-hook-cookie-get"]){
var expstr=v_Error().stack.v_split('\n')[2] var expstr=v_Error().stack.v_split('\n')[2]
v_cache_node(expstr, "Document", "cookie", "get", r) v_cache_node(expstr, "Document", "cookie", "get", r)
if (expurl.v_test(expstr)){ if (expurl.v_test(expstr) && typeof expstr == 'string'){
window.v_log(..._mk_logs('(*) [cookie get]', r, get_log_at(expstr.trim()))) window.v_log(..._mk_logs('(*) [cookie get]', r, get_log_at(expstr.trim())))
} }
if (e["config-hook-cookie-add-debugger"] && r.indexOf(e["config-hook-cookie-match"]) != -1){ debugger } if (e["config-hook-cookie-add-debugger"] && r.indexOf(e["config-hook-cookie-match"]) != -1){ debugger }
@ -1457,7 +1457,7 @@ function injectfunc(e, window) {
if (e["config-hook-cookie"] && e["config-hook-cookie-set"]){ if (e["config-hook-cookie"] && e["config-hook-cookie-set"]){
var expstr=v_Error().stack.v_split('\n')[2] var expstr=v_Error().stack.v_split('\n')[2]
v_cache_node(expstr, "Document", "cookie", "set") v_cache_node(expstr, "Document", "cookie", "set")
if (expurl.v_test(expstr)){ if (expurl.v_test(expstr) && typeof expstr == 'string'){
window.v_log(..._mk_logs('(*) [cookie set]', v, get_log_at(expstr.trim())) ) window.v_log(..._mk_logs('(*) [cookie set]', v, get_log_at(expstr.trim())) )
} }
} }
@ -1485,7 +1485,7 @@ function injectfunc(e, window) {
window.v_settimeout(arguments) window.v_settimeout(arguments)
}else{ }else{
if (e["config-hook-settimeout"]){ if (e["config-hook-settimeout"]){
if (expurl.v_test(expstr=v_Error().stack.v_split('\n')[2])){ if (expurl.v_test(expstr=v_Error().stack.v_split('\n')[2]) && typeof expstr == 'string'){
window.v_log(..._mk_logs('[settimeout]', ...arguments, get_log_at(expstr.trim()))) window.v_log(..._mk_logs('[settimeout]', ...arguments, get_log_at(expstr.trim())))
} }
} }
@ -1504,7 +1504,7 @@ function injectfunc(e, window) {
window.v_setinterval(arguments) window.v_setinterval(arguments)
}else{ }else{
if (e["config-hook-setinterval"]){ if (e["config-hook-setinterval"]){
if (expurl.v_test(expstr=v_Error().stack.v_split('\n')[2])){ if (expurl.v_test(expstr=v_Error().stack.v_split('\n')[2]) && typeof expstr == 'string'){
window.v_log(..._mk_logs('[setinterval]', ...arguments, get_log_at(expstr.trim())) ) window.v_log(..._mk_logs('[setinterval]', ...arguments, get_log_at(expstr.trim())) )
} }
} }
@ -1541,7 +1541,7 @@ function injectfunc(e, window) {
} }
} }
var v_logs = function (a, b, c) { var v_logs = function (a, b, c) {
if (expurl.v_test(expstr=v_Error().stack.v_split('\n')[3])){ if (expurl.v_test(expstr=v_Error().stack.v_split('\n')[3]) && typeof expstr == 'string'){
window.v_log(..._mk_logs(' (*)', a, util.inspect(b), '===>', c, get_log_at(expstr.trim()))) window.v_log(..._mk_logs(' (*)', a, util.inspect(b), '===>', c, get_log_at(expstr.trim())))
} }
return c return c
@ -1602,22 +1602,22 @@ function make_domhooker_funcs(){
var expstr = v_Error().stack.v_split('\\n')[2] var expstr = v_Error().stack.v_split('\\n')[2]
v_cache_node(expstr, "${obname}", "${name}", "get", r) v_cache_node(expstr, "${obname}", "${name}", "get", r)
inspect_arguments(this, arguments, r, "${obname}", "${name}", "get") inspect_arguments(this, arguments, r, "${obname}", "${name}", "get")
if (expurl.v_test(expstr)){ if (expurl.v_test(expstr) && typeof expstr == 'string'){
window.v_log(..._mk_logs('(*) [${obname} ${name} get]', r, get_log_at(expstr.trim()))) window.v_log(..._mk_logs('(*) [${obname} ${name} get]', r, get_log_at(expstr.trim())))
} }
} }
return r }) return r }, 'get ${name}')
if (_old_set){ if (_old_set){
var _new_set = saf(function set(v){ var _new_set = saf(function set(v){
if (e["config-hook-domobj"] && e["config-hook-domobj-set"] && e["config-hook-${obname}-${name}"]){ if (e["config-hook-domobj"] && e["config-hook-domobj-set"] && e["config-hook-${obname}-${name}"]){
var expstr = v_Error().stack.v_split('\\n')[2] var expstr = v_Error().stack.v_split('\\n')[2]
v_cache_node(expstr, "${obname}", "${name}", "set") v_cache_node(expstr, "${obname}", "${name}", "set")
inspect_arguments(this, arguments, null, "${obname}", "${name}", "set") inspect_arguments(this, arguments, null, "${obname}", "${name}", "set")
if (expurl.v_test(expstr)){ if (expurl.v_test(expstr) && typeof expstr == 'string'){
window.v_log(..._mk_logs('(*) [${obname} ${name} set]', v, get_log_at(expstr.trim()))) window.v_log(..._mk_logs('(*) [${obname} ${name} set]', v, get_log_at(expstr.trim())))
} }
} }
return _old_set.apply(this, arguments) }) return _old_set.apply(this, arguments) }, 'set ${name}')
}else{ _new_set = undefined } }else{ _new_set = undefined }
Object.defineProperty(${obname}.prototype, '${name}', { get: _new_get, set: _new_set, enumerable: _desc['enumerable'], configurable: _desc['configurable'], }) Object.defineProperty(${obname}.prototype, '${name}', { get: _new_get, set: _new_set, enumerable: _desc['enumerable'], configurable: _desc['configurable'], })
}() }()
@ -1640,7 +1640,7 @@ function make_domhooker_funcs(){
if (e["config-hook-domobj"] && e["config-hook-domobj-func"] && e["config-hook-${obname}-${name}"]){ if (e["config-hook-domobj"] && e["config-hook-domobj-func"] && e["config-hook-${obname}-${name}"]){
var expstr = v_Error().stack.v_split('\\n')[2] var expstr = v_Error().stack.v_split('\\n')[2]
v_cache_node(expstr, "${obname}", "${name}", "func") v_cache_node(expstr, "${obname}", "${name}", "func")
if (expurl.v_test(expstr)){ if (expurl.v_test(expstr) && typeof expstr == 'string'){
window.v_log(..._mk_logs(' (f) [${obname} ${name} func]', origslice.call(arguments), '===>', err ? '[ERROR]' : r, get_log_at(expstr.trim()))) window.v_log(..._mk_logs(' (f) [${obname} ${name} func]', origslice.call(arguments), '===>', err ? '[ERROR]' : r, get_log_at(expstr.trim())))
} }
} }

View File

@ -27,6 +27,7 @@
<section class="tab"> <section class="tab">
<div> <div>
<label ><input type="checkbox" data-key="config-hook-global">是否挂钩总开关</label> <label ><input type="checkbox" data-key="config-hook-global">是否挂钩总开关</label>
<label id='debug_hook' style="color: #FFEEEE">cilame</label>
<br/> <br/>
<!-- <label ><input type="checkbox" data-key="config-hook-alt-w">启动 alt + w 快捷键(快捷键开启/关闭日志,当前焦点需在网页上才有效)</label> <!-- <label ><input type="checkbox" data-key="config-hook-alt-w">启动 alt + w 快捷键(快捷键开启/关闭日志,当前焦点需在网页上才有效)</label>
<br/> --> <br/> -->
@ -195,6 +196,10 @@
<button id='open_diff_text'>打开文本对比工具</button> <button id='open_diff_text'>打开文本对比工具</button>
<label id='env' style="color: #FFEEEE">cilame</label> <label id='env' style="color: #FFEEEE">cilame</label>
<br/> <br/>
<label ><input type="checkbox" id="clear_not_use" data-key="config-clear_not_use">【解密ob高级混淆】 尝试清理未被使用到的变量和函数</label>
<br/>
<label ><input type="checkbox" id="clear_ob_extra" data-key="config-clear_ob_extra">【解密ob高级混淆】 尝试清理ob混淆的反调试代码</label>
<br/>
<label>source</label> <label>source</label>
<textarea id='txt' style="width: 100%; height: 500px"></textarea> <textarea id='txt' style="width: 100%; height: 500px"></textarea>
<label>code</label> <label>code</label>

View File

@ -91,12 +91,15 @@ function ConditionVarToIf(path) {
// | // |
// | // |
// v // v
// var a;
// if (m) { // if (m) {
// var a = 11; // a = 11;
// } else { // } else {
// var a = 22; // a = 22;
// } // }
// let 和 const 的作用域为块,所以不能直接把定义用的 kind 放在 if 的子块里面
if (t.isForStatement(path.parentPath)) return; if (t.isForStatement(path.parentPath)) return;
if (path.node.kind == 'const') return;
var decl = path.node.declarations var decl = path.node.declarations
var rpls = [] var rpls = []
var togg = false var togg = false
@ -104,10 +107,11 @@ function ConditionVarToIf(path) {
if (t.isConditionalExpression(decl[i].init)){ if (t.isConditionalExpression(decl[i].init)){
togg = true togg = true
let {test, consequent, alternate} = decl[i].init; let {test, consequent, alternate} = decl[i].init;
rpls.push(t.variableDeclaration(path.node.kind, [t.variableDeclarator(decl[i].id)]))
rpls.push(t.ifStatement( rpls.push(t.ifStatement(
test, test,
t.blockStatement([t.variableDeclaration(path.node.kind, [t.variableDeclarator(decl[i].id, consequent)]),]), t.blockStatement([t.ExpressionStatement(t.AssignmentExpression("=", decl[i].id, consequent))]),
t.blockStatement([t.variableDeclaration(path.node.kind, [t.variableDeclarator(decl[i].id, alternate)]),]) t.blockStatement([t.ExpressionStatement(t.AssignmentExpression("=", decl[i].id, alternate))]),
)) ))
}else{ }else{
rpls.push(t.VariableDeclaration(path.node.kind, [decl[i]])) rpls.push(t.VariableDeclaration(path.node.kind, [decl[i]]))
@ -412,18 +416,50 @@ function calcBinary(path){
} }
function clearNotuseFunc(path){ function clearNotuseFunc(path){
if (!path.getFunctionParent()){ return }
var id = path.node.id; var id = path.node.id;
var binding = path.scope.getBinding(id.name); function is_used(path, name){
//如果变量被修改过,则不能进行删除动作。 var binding = path.scope.getBinding(name);
if (!binding || binding.constantViolations.length > 0) { if (!binding || binding.constantViolations.length > 0) {
return; return;
}
if (binding.referencePaths.length === 0) {
return true
}
} }
//长度为0说明变量没有被使用过。 if (is_used(path, id.name)){
if (binding.referencePaths.length === 0) {
path.remove(); path.remove();
} }
} }
function clearNotuseVar(path){
if (!path.getFunctionParent()){ return }
var _new_var = []
function is_used(path, name){
var binding = path.scope.getBinding(name);
if (!binding || binding.constantViolations.length > 0) {
return;
}
if (binding.referencePaths.length === 0) {
return true
}
}
for (var i = 0; i < path.node.declarations.length; i++) {
var inode = path.node.declarations[i]
if (t.isIdentifier(inode.id)
&& is_used(path, inode.id.name)
){
}else{
_new_var.push(inode)
}
}
if (_new_var.length){
path.node.declarations = _new_var
}else{
path.remove()
}
}
function AddCatchLog(path){ function AddCatchLog(path){
var err_name = path.node.param.name var err_name = path.node.param.name
path.node.body.body.unshift({ path.node.body.body.unshift({
@ -776,10 +812,6 @@ function del_ob_extra(ast){
var once = false var once = false
function remove_a(path){ function remove_a(path){
if ( path.node.value == '(((.+)+)+)+$' if ( path.node.value == '(((.+)+)+)+$'
&& path.parentPath.node.type == 'CallExpression'
&& path.parentPath.node.callee.type == 'MemberExpression'
&& path.parentPath.node.callee.property.type == 'Identifier'
&& path.parentPath.node.callee.property.name == 'search'
&& !once && !once
){ ){
var a = path.getFunctionParent().parentPath var a = path.getFunctionParent().parentPath
@ -854,12 +886,12 @@ function del_ob_extra(ast){
var ra = a.node.callee.name var ra = a.node.callee.name
var rb = b.node.id.name var rb = b.node.id.name
function remove_a1(path){ function remove_a1(path){
if (path.node.id.name == ra && path.getFunctionParent() == c || path.getFunctionParent() == null){ if (path.node.id.name == ra && (path.getFunctionParent() == c || path.getFunctionParent() == null)){
path.remove() path.remove()
} }
} }
function remove_a2(path){ function remove_a2(path){
if (path.node.callee.name == rb && path.getFunctionParent() == c || path.getFunctionParent() == null){ if (path.node.callee.name == rb && (path.getFunctionParent() == c || path.getFunctionParent() == null)){
path.remove() path.remove()
} }
} }
@ -885,6 +917,121 @@ function del_ob_extra(ast){
} }
} }
function cache_const_var(path){
// 收集匹配某种模式的对象, VariableDeclaration 下的 ObjectExpression
// 并且每个键值对都是 Identifier: (StringLiteral/NumericLiteral)
// 收集后存储到对象的 getFunctionParent 的 body 中
// const _0xd8926c = {
// _0x77eed: 0xef,
// _0x1e4fbf: 0xf1,
// _0x71271e: 0x11f,
// _0xfa6d5d: 0xf7
// }
// , _0x42f139 = {
// _0x55d096: 0x104,
// _0x2c29ee: 0x107
// }
// , _0x3c47ca = {
// _0x3a14ec: 0x118,
// _0x158b76: 0x10f,
// _0x35fcb5: 0x11d
// }
var parent = path.getFunctionParent()
if (!parent){ return }
var pbody = parent.node.body
for (var i = 0; i < path.node.declarations.length; i++) {
var temp = path.node.declarations[i]
if (t.isObjectExpression(temp.init) && t.isIdentifier(temp.id)){
var is_ok = true
for (var j = 0; j < temp.init.properties.length; j++) {
var temp2 = temp.init.properties[j]
if (!(
t.isNumericLiteral(temp2.value) ||
t.isStringLiteral(temp2.value))
){
is_ok = false
}
}
if (!is_ok){ return }
for (var j = 0; j < temp.init.properties.length; j++) {
var temp2 = temp.init.properties[j]
var name;
if (t.isIdentifier(temp2.key)){
name = temp2.key.name
}
if (t.isStringLiteral(temp2.key)){
name = temp2.key.value
}
pbody.dec_number = pbody.dec_number || {}
pbody.dec_number[temp.id.name] = pbody.dec_number[temp.id.name] || {}
pbody.dec_number[temp.id.name][name] = temp2.value.value
}
temp.is_remove = true
temp.init.properties = []
}
}
var newlist = []
for (var i = 0; i < path.node.declarations.length; i++) {
var temp = path.node.declarations[i]
if (temp.is_remove){
}else{
newlist.push(temp)
}
}
if (newlist.length){
path.node.declarations = newlist
}else{
path.remove()
}
}
function dec_obj_numbers(path){
// 使用 cache_const_var 函数收集到的对象
// 将使用到这些常量的地方直接修改成目标常量
// const _0xd8926c = {
// _0xfa6d5d: 123
// }
// console.log(_0xd8926c._0xfa6d5d)
// |
// |
// |
// v
// console.log(123)
var parent = path.getFunctionParent()
if (!parent){ return }
if (t.isIdentifier(path.node.object)){
var objname = path.node.object.name
var propname;
if (t.isIdentifier(path.node.property)){
propname = path.node.property.name
}
else if (t.isStringLiteral(path.node.property)){
propname = path.node.property.value
}
else{
return
}
}
var temp = path.getFunctionParent()
while(temp){
if(temp.node.body.dec_number){
var dec_number = temp.node.body.dec_number
if (dec_number[objname] && typeof dec_number[objname][propname] != 'undefined'){
if (typeof dec_number[objname][propname] == 'number'){
path.replaceWith(t.NumericLiteral(dec_number[objname][propname]))
return
}else if(typeof dec_number[objname][propname] == 'string'){
path.replaceWith(t.StringLiteral(dec_number[objname][propname]))
return
}else{
throw Error(`unhandle type ${typeof dec_number[objname][propname]}`)
}
}
}
temp = temp.getFunctionParent()
}
}
@ -1018,8 +1165,12 @@ function muti_process_sojsondefusion(jscode){
return code; return code;
} }
function muti_process_obdefusion(jscode){ function muti_process_obdefusion(jscode, config){
var ast = parser.parse(jscode); var ast = parser.parse(jscode);
config = config || {}
traverse(ast, {VariableDeclaration: cache_const_var})
traverse(ast, {MemberExpression: dec_obj_numbers})
// ob 解混淆处理部分 // ob 解混淆处理部分
pas_ob_encfunc(ast) pas_ob_encfunc(ast)
@ -1042,10 +1193,16 @@ function muti_process_obdefusion(jscode){
traverse(ast, {IfStatement: ClearDeadCode}); // 清理死代码 traverse(ast, {IfStatement: ClearDeadCode}); // 清理死代码
traverse(ast, {BinaryExpression: {exit: calcBinary}}) // 二元运算合并 traverse(ast, {BinaryExpression: {exit: calcBinary}}) // 二元运算合并
traverse(ast, {CatchClause: AddCatchLog}); // 给所有的 catch(e){} 后面第一条语句添加异常输出。 traverse(ast, {CatchClause: AddCatchLog}); // 给所有的 catch(e){} 后面第一条语句添加异常输出。
// traverse(ast, {FunctionDeclaration: clearNotuseFunc}) // 该处有问题 // 该处可以使用 Uglify 库优化功能自动删除
// ob 解混淆部分,去除额外代码 if (config.clear_not_use){
del_ob_extra(ast) var ast = parser.parse(generator(ast).code) // 更新一下 ast 节点信息,否则清理未使用的变量可能出现问题
traverse(ast, {FunctionDeclaration: clearNotuseFunc}) // 不知道现在还有没有问题,不管了
traverse(ast, {VariableDeclaration: clearNotuseVar}) // 不知道现在还有没有问题,不管了
}
if (config.clear_ob_extra){
del_ob_extra(ast) // ob 解混淆部分,去除额外代码
}
var { code } = generator(ast, { jsescOption: { minimal: true, } }); var { code } = generator(ast, { jsescOption: { minimal: true, } });
return code; return code;
@ -1077,8 +1234,8 @@ function muti_process_jsfuckdefusion(jscode){
} }
function muti_process_aline(jscode){ function muti_process_aline(jscode){
var ast = parser.parse(jscode) var ast = parser.parse(jscode)
traverse(ast, {enter: function(path){t.removeComments(path.node);}}) traverse(ast, {enter: function(path){t.removeComments(path.node);}})
return generator(ast, {minified:true}).code return generator(ast, {minified:true}).code
} }

View File

@ -45,7 +45,11 @@ sojsontn.addEventListener('click', function(e){
obtn.addEventListener('click', function(e){ obtn.addEventListener('click', function(e){
try{ try{
;(txt2||txt).value = muti_process_obdefusion(txt.value) var config = {
clear_ob_extra: clear_ob_extra.checked,
clear_not_use: clear_not_use.checked,
}
;(txt2||txt).value = muti_process_obdefusion(txt.value, config)
}catch(e){ }catch(e){
;(txt2||txt).value = e.stack ;(txt2||txt).value = e.stack
} }
@ -101,4 +105,76 @@ uglify_minibtn.addEventListener('click', function(e){
var envb = document.getElementById('env'); var envb = document.getElementById('env');
envb.addEventListener('dblclick', function(e){ envb.addEventListener('dblclick', function(e){
;(txt2||txt).value = '!'+v_mk+'()'; ;(txt2||txt).value = '!'+v_mk+'()';
})
var envb = document.getElementById('debug_hook');
envb.addEventListener('dblclick', function(e){
get_file('inject.js', function(e){
var ast = parser.parse(e)
var fdecls = []
for (var i = 0; i < ast.program.body.length; i++) {
if (t.isFunctionDeclaration(ast.program.body[i])){
fdecls.push(ast.program.body[i])
}
else if(t.isVariableDeclaration(ast.program.body[i])){
fdecls.push(ast.program.body[i])
}
}
ast.program.body = fdecls
var code = generator(ast).code
code = code + `
add_config_hook(getsets)
add_config_hook(funcs)
chrome.storage.local.get(hookers, function (result) {
result["config-hook-global"] = true
var replacer_injectfunc = (injectfunc + '').replace('$domobj_placeholder', make_domhooker_funcs())
var replacer_injectfunc = replacer_injectfunc.replace('$make_v_func', make_v+';')
var inject_code = \`(\${replacer_injectfunc})(\${JSON.stringify(result)},window)\`
var log_toggle = result["config-hook-log-toggle"]
if(!log_toggle){
inject_code += ';globalConfig.logtogglefunc({key:"w",altKey:true})'
}
my_magic_obj['inject_code'] = inject_code
})
`
new Function('my_magic_obj', code)(new Proxy({}, {
set(a,b,c){
a[b] = c
if (b == 'inject_code'){
attach_all(c)
}
return true
}
}))
function attach_all(code){
debug_tab = true
chrome.tabs.query({}, function(tabs) {
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].url.indexOf("chrome") == 0){
continue
}
attach_tab_debug(tabs[i].id, code)
}
});
function attach_tab_debug(tabId, code){
cache_tabid_new[tabId] = 1
var tabids = Object.keys(cache_tabid_new)
for (var i = 0; i < tabids.length; i++) {
if (cache_tabid_new[tabids[i]] == 1 && !cache_tabid_att[tabids[i]]){
cache_tabid_att[tabids[i]] = 1
var currtab = { tabId: +tabids[i] };
chrome.debugger.attach(currtab, "1.2", function () {
chrome.debugger.sendCommand(currtab, "Page.enable", function(){
chrome.debugger.sendCommand(currtab, "Page.addScriptToEvaluateOnNewDocument", {
source: code
}, function(){
console.log('addScriptToEvaluateOnNewDocument ok .')
});
});
});
}
}
}
}
})
}) })