This commit is contained in:
cilame 2022-10-30 03:17:58 +08:00
parent 87588ef581
commit 230e8cd669
8 changed files with 236 additions and 40 deletions

View File

@ -7,6 +7,7 @@
<script src="./tools/cheerio.js"></script> <script src="./tools/cheerio.js"></script>
<script src="./tools/replacer.js"></script> <script src="./tools/replacer.js"></script>
<script src="./tools/error_front.js"></script> <script src="./tools/error_front.js"></script>
<script src="./tools/cryptojs.js"></script>
<script src="background.js"></script> <script src="background.js"></script>
</head> </head>
<body> <body>

View File

@ -11,17 +11,33 @@
// }); // });
// background.js // background.js
chrome.contextMenus.create({ chrome.contextMenus.create({
title: "打开 v_jstools 动态调试", title: "打开 ast 动态挂钩",
contexts: ['all'], contexts: ['all'],
onclick: function(){ onclick: function(){
ast_dyn_hook = true
AttachDebugger(); AttachDebugger();
} }
}); });
chrome.contextMenus.create({
title: "打开 html 调试拷贝",
contexts: ['all'],
onclick: function(){
html_copy = true
AttachDebugger();
}
});
var ast_dyn_hook = false
var html_copy = false
function close_debugger(){
attached = false
ast_dyn_hook = false
html_copy = false
}
function sendCommand(method, params, source, chainfun){ function sendCommand(method, params, source, chainfun){
chrome.debugger.sendCommand(source, method, params, function(result){ chrome.debugger.sendCommand(source, method, params, function(result){
if (chrome.runtime.lastError) { if (chrome.runtime.lastError) {
console.error('chrome.runtime.lastError', chrome.runtime.lastError) console.error('chrome.runtime.lastError', chrome.runtime.lastError)
if (chrome.runtime.lastError.message.indexOf('Cannot access a chrome://') != -1){ attached = false } if (chrome.runtime.lastError.message.indexOf('Cannot access a chrome://') != -1){ close_debugger() }
} else { if (chainfun){ chainfun(result) } } } else { if (chainfun){ chainfun(result) } }
}); });
} }
@ -45,48 +61,56 @@ chrome.debugger.onEvent.addListener(function (source, method, params){
break; } break; }
sendCommand("Fetch.getResponseBody", { requestId: params.requestId }, source, function(result){ sendCommand("Fetch.getResponseBody", { requestId: params.requestId }, source, function(result){
var fillfunc = fillresponse.bind(null, params, source) var fillfunc = fillresponse.bind(null, params, source)
chrome.storage.local.get(["config-fetch_hook"], function (res) {
if ( params.resourceType == 'Script' if (!result.body){ fillfunc(result.body); return }
|| params.resourceType == 'Document' // save html
|| params.resourceType == 'Stylesheet' if (html_copy){
|| params.resourceType == 'Image' if ( params.resourceType == 'Script'
|| params.resourceType == 'Font' || params.resourceType == 'Document'
|| params.resourceType == 'Other' || params.resourceType == 'Stylesheet'
){ || params.resourceType == 'Image'
if (params.resourceType == 'Script'){ var save_info = decodeURIComponent(escape(atob(result.body))) } || params.resourceType == 'Font'
if (params.resourceType == 'Document'){ var save_info = decodeURIComponent(escape(atob(result.body))) } || params.resourceType == 'Other'
if (params.resourceType == 'Stylesheet'){ var save_info = decodeURIComponent(escape(atob(result.body))) } ){
if (params.resourceType == 'Image'){ var save_info = result.body } if (params.resourceType == 'Script'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Font'){ var save_info = result.body } if (params.resourceType == 'Document'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Other'){ var save_info = result.body } if (params.resourceType == 'Stylesheet'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
function save_html_info(save_info, type, url){ if (params.resourceType == 'Image'){ var save_info = result.body }
save_cache[url] = {data: save_info, type: type} if (params.resourceType == 'Font'){ var save_info = result.body }
if (params.resourceType == 'Other'){ var save_info = result.body }
function save_html_info(save_info, type, url){
save_cache[url] = {data: save_info, type: type}
}
save_html_info(save_info, params.resourceType, params.request.url)
console.log(params.resourceType, params.request.url)
}
} }
save_html_info(save_info, params.resourceType, params.request.url) // ast hook
} if (ast_dyn_hook){
console.log(params.resourceType, params.request.url) if ( params.resourceType == 'Script'
if (result.body !== undefined){ // 收到的 result.body 是 base64(代码) 的代码,使用时需要解码一下 || params.resourceType == 'Document'
if (params.resourceType == 'Script' || params.resourceType == 'Document'){ ){
chrome.storage.local.get(["config-fetch_hook"], function (res) {
try{ try{
var respboby = decodeURIComponent(escape(atob(result.body))) var respboby = decodeURIComponent(escape(atob(result.body)))
var replacer = eval((res["config-fetch_hook"]||'')+';fetch_hook') var replacer = eval((res["config-fetch_hook"]||'')+';fetch_hook')
if (params.resourceType == 'Script'){ var replbody = (replacer(respboby, params.request.url)) } if (params.resourceType == 'Script'){ var replbody = (replacer(respboby, params.request.url)) }
if (params.resourceType == 'Document'){ var replbody = (html_script_replacer(respboby, replacer, params.request.url)) } if (params.resourceType == 'Document'){ var replbody = (html_script_replacer(respboby, replacer, params.request.url)) }
fillfunc(btoa(unescape(encodeURIComponent(replbody)))) } fillfunc(btoa(unescape(encodeURIComponent(replbody))))
return }
catch(e){ catch(e){
send_error_info_to_front(e.stack, currtab.tabId, params.request.url) send_error_info_to_front(e.stack, currtab.tabId, params.request.url) }
fillfunc(result.body) } }
})
return
} }
} fillfunc(result.body) // body 只能传 base64(指定代码)
fillfunc(result.body) // body 只能传 base64(指定代码) })
return
}); });
break; } break; }
} }
}) })
chrome.debugger.onDetach.addListener(function(){ attached = false }) chrome.debugger.onDetach.addListener(function(){
close_debugger()
})
var attached = false var attached = false
var currtab; var currtab;
function AttachDebugger() { function AttachDebugger() {
@ -315,6 +339,36 @@ function get_html(url){
return $.html() return $.html()
} }
var typeMap = {
"txt" : "text/plain",
"html" : "text/html",
"htm" : "text/html",
"css" : "text/css",
"js" : "text/javascript",
"json" : "text/json",
"xml" : "text/xml",
"jpg" : "image/jpeg",
"gif" : "image/gif",
"png" : "image/png",
"webp" : "image/webp"
}
function getLocalFileUrl(url) {
var arr = url.split('.');
var type = arr[arr.length-1];
var xhr = new XMLHttpRequest();
xhr.open('get', url, false);
xhr.send(null);
var content = xhr.responseText || xhr.responseXML;
if (!content) {
return false;
}
var wordArray = CryptoJS.enc.Utf8.parse(content);
var base64 = CryptoJS.enc.Base64.stringify(wordArray);
return ("data:" + (typeMap[type] || typeMap.txt) + ";charset=utf-8;base64," + base64);
}
chrome.storage.local.get(['config-hook-global'], function(e){ chrome.storage.local.get(['config-hook-global'], function(e){
chrome.browserAction.setBadgeBackgroundColor({color: '#BC1717'}); chrome.browserAction.setBadgeBackgroundColor({color: '#BC1717'});
if (e['config-hook-global']){ if (e['config-hook-global']){
@ -322,4 +376,32 @@ chrome.storage.local.get(['config-hook-global'], function(e){
}else{ }else{
chrome.browserAction.setBadgeText({text: ''}); chrome.browserAction.setBadgeText({text: ''});
} }
})
chrome.webRequest.onBeforeRequest.addListener(function (details) {
var url = details.url;
for (var i = 0; i < webRedirect.length; i++) {
var [mstr, rurl] = webRedirect[i]
if (url.indexOf(mstr) != -1){
if (rurl.trim().indexOf('file:///') == 0){
var rdata = getLocalFileUrl(rurl)
if (rdata){
return { redirectUrl: rdata };
}
}
}
}
return {}
},
{urls: ["<all_urls>"]},
["blocking"]
);
var webRedirect = []
window.addEventListener('storage', function(){
webRedirect = JSON.parse(localStorage.webRedirect || "[]")
}, false);
chrome.storage.local.get(["response_changer"], function(res){
var init_data = JSON.parse(res["response_changer"] || "[]")
webRedirect = init_data
}) })

File diff suppressed because one or more lines are too long

View File

@ -35,15 +35,17 @@
"name": "v_jstools", "name": "v_jstools",
"version": "0.0.0", "version": "0.0.0",
"description": "v_jstools js hook工具", "description": "v_jstools js hook工具",
"permissions": ["storage", "permissions": ["unlimitedStorage",
"unlimitedStorage",
"activeTab", "activeTab",
"webRequest",
"webRequestBlocking",
"tabs", "tabs",
"debugger", "debugger",
"storage", "storage",
"contextMenus", "contextMenus",
"http://*/*", "http://*/*",
"https://*/*", "https://*/*",
"<all_urls>",
"cookies", "cookies",
"downloads", "downloads",
"proxy" "proxy"

View File

@ -17,7 +17,7 @@
<ul> <ul>
<button class="act">dom对象 hook 配置</button> <button class="act">dom对象 hook 配置</button>
<button>注入代码</button> <button>注入代码</button>
<button>高级 hook 修改 response 返回值</button> <button>修改返回值</button>
<button>AST混淆解密</button> <button>AST混淆解密</button>
<button>代码模板(RPC...)</button> <button>代码模板(RPC...)</button>
<button>混淆器</button> <button>混淆器</button>
@ -132,7 +132,14 @@
<!-- <div>修改代理:<input type="text" data-key="config-proxy_config" id="proxy_config"></div> --> <!-- <div>修改代理:<input type="text" data-key="config-proxy_config" id="proxy_config"></div> -->
</section> </section>
<section class="tab"> <section class="tab">
<div>这里的功能:在目标网页上右键菜单选择 “打开 v_jstools 动态调试” 即可开启,使用用插件的方式 hook 住目标页面的所有代码,像是在 node 里面一样使用 ast 将原始的代码修改成期望的样子</div> <h2 style="margin-bottom: 0px;margin-top: 50px;">修改匹配URL的返回值</h2>
<hr>
<div>适用的本地文件后缀txt,html,htm,css,js,json,xml,jpg,gif,png,webp</div>
<table id="response_changer"></table>
<h2 style="margin-bottom: 0px;margin-top: 50px;">动态修改被调试页面的所有js代码</h2>
<hr>
<div>这里的功能:在目标网页上右键菜单选择 “打开 ast 动态挂钩” 即可开启,使用用插件的方式 hook 住目标页面的所有代码,像是在 node 里面一样使用 ast 将原始的代码修改成期望的样子</div>
<div>这里的 hook 功能在一定的扩展之后,能 hook 住 script 链接中的 js 代码,也能 hook 到 html 内的 js 代码。</div> <div>这里的 hook 功能在一定的扩展之后,能 hook 住 script 链接中的 js 代码,也能 hook 到 html 内的 js 代码。</div>
<div>*能直接用插件的方式实现 ast 修改代码,用处还是非常大的。不过目前感觉功能稍微有点干瘪,因为暂时还在想有什么 ast 修改模板代码会更好的捕捉代码信息,让代码更方便的调试。</div> <div>*能直接用插件的方式实现 ast 修改代码,用处还是非常大的。不过目前感觉功能稍微有点干瘪,因为暂时还在想有什么 ast 修改模板代码会更好的捕捉代码信息,让代码更方便的调试。</div>
<HR> <HR>
@ -230,6 +237,7 @@
<textarea id='jsobfuscator_code' style="width: 100%; height: 500px" placeholder="输出代码"></textarea> <textarea id='jsobfuscator_code' style="width: 100%; height: 500px" placeholder="输出代码"></textarea>
</section> </section>
</div> </div>
<script src="tools/jquery.min.js"></script>
<script src="options.js"></script> <script src="options.js"></script>
<script src="tools/model_funcs.js"></script> <script src="tools/model_funcs.js"></script>
<script src="tools/babel_asttool.js"></script> <script src="tools/babel_asttool.js"></script>

View File

@ -678,3 +678,105 @@ document.getElementById('mydec').addEventListener('click', function(e){
mycode_dec.value = e mycode_dec.value = e
} }
}) })
function response_changer_init(idname, titlenames, init_data, callback) {
var cid = "#" + idname
var trlast = cid + " tr:last"
var opindex = titlenames.length
var title = "<tr>"
for (var i = 0; i < titlenames.length; i++) {
title += "<td>" + titlenames[i] + "</td>"
}
title += "<td>操作</td>"
title += "</tr>"
title += '<tr><td colspan="5"><button>添加行</button><button>添加示例</button></td></tr>'
$(cid).html(title)
$($(trlast).find("button")[0]).click(function() {
addRow()
})
$($(trlast).find("button")[1]).click(function() {
addRow(["baidu.com", "file:///C:/Users/Administrator/Desktop/test.html"])
__cache_data()
})
init_data = init_data || []
for (var i = 0; i < init_data.length; i++) {
addRow(init_data[i])
}
function __cache_data(){
var data_list = []
var trs = $(cid).find("tr")
for (var i = 0; i < trs.length; i++) {
var tds = $(trs[i]).find("td")
var data_line = []
for (var j = 0; j < tds.length; j++) {
var ipt = $(tds[j]).find("input")[0]
if (ipt){
data_line.push(ipt.value)
}
}
if (data_line.length){
data_list.push(data_line)
}
}
while(init_data.length){ init_data.pop() }
while(data_list.length){ init_data.unshift(data_list.pop()) }
callback(init_data)
}
function __add_remover(index){
$(cid).find("tr").eq(index).find("td").eq(opindex).remove();
var htmlStr = "<td><button>删除行</button></td>"
$(cid).find("tr").eq(index).append(htmlStr)
$(cid).find("tr").eq(index).find("td").find("button").click(function(){
removeRow(index)
})
}
function __add_changer(index){
var tds = $(cid).find("tr").eq(index).find("td")
for (var i = 0; i < tds.length; i++) {
var ipt = $(tds[i]).find("input")[0]
if (ipt){
$(ipt).on("input", function(){
__cache_data()
})
}
}
}
function addRow(data) {
var trArray = $(cid).find("tr");
var thisIndex = trArray.length - 1;
var addRowHtmlStr = "<tr>"
for (var i = 0; i < titlenames.length; i++) {
addRowHtmlStr += "<td style='width: 300px'><input type='text' style='width: 300px'></td>"
}
"<td></td></tr>"
$(trlast).before(addRowHtmlStr);
__add_changer(thisIndex)
__add_remover(thisIndex)
if (data){
var ctds = $(cid).find("tr").eq(thisIndex).find("td")
var leng = Math.min(data.length, titlenames.length)
for (var i = 0; i < leng; i++) {
$(ctds[i]).find('input').val(data[i])
}
}
}
function removeRow(index) {
$(cid).find("tr").eq(index).remove();
var trArrayNow = $(cid).find("tr");
for (var i = index; i < trArrayNow.length - 1; i++) {
__add_remover(i)
}
__cache_data()
}
}
chrome.storage.local.get(["response_changer"], function(res){
var init_data = JSON.parse(res["response_changer"] || "[]")
localStorage.webRedirect = JSON.stringify(init_data)
response_changer_init("response_changer", ["(URL)字符串匹配", "重定向地址"], init_data, function(data){
chrome.storage.local.set({
response_changer: JSON.stringify(data)
})
localStorage.webRedirect = JSON.stringify(data)
})
})

View File

@ -86,7 +86,7 @@ document.getElementById('clone_page').addEventListener('click', function(e){
filename: 'clone_html.html' filename: 'clone_html.html'
}); });
}else{ }else{
alert('获取html结构失败请右键需要拷贝的页面的空白处选择“打开 v_jstools 动态调试”。刷新页面后,确保页面资源加载充足后再重新点击“拷贝当前页面”') alert('获取html结构失败请右键需要拷贝的页面的空白处选择“打开 html 调试拷贝”。刷新页面后,确保页面资源加载充足后再重新点击“拷贝当前页面”')
} }
}); });
}) })

4
tools/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long