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/replacer.js"></script>
<script src="./tools/error_front.js"></script>
<script src="./tools/cryptojs.js"></script>
<script src="background.js"></script>
</head>
<body>

View File

@ -11,17 +11,33 @@
// });
// background.js
chrome.contextMenus.create({
title: "打开 v_jstools 动态调试",
title: "打开 ast 动态挂钩",
contexts: ['all'],
onclick: function(){
ast_dyn_hook = true
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){
chrome.debugger.sendCommand(source, method, params, function(result){
if (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) } }
});
}
@ -45,48 +61,56 @@ chrome.debugger.onEvent.addListener(function (source, method, params){
break; }
sendCommand("Fetch.getResponseBody", { requestId: params.requestId }, source, function(result){
var fillfunc = fillresponse.bind(null, params, source)
if ( params.resourceType == 'Script'
|| params.resourceType == 'Document'
|| params.resourceType == 'Stylesheet'
|| params.resourceType == 'Image'
|| params.resourceType == 'Font'
|| params.resourceType == 'Other'
){
if (params.resourceType == 'Script'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Document'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Stylesheet'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Image'){ var save_info = result.body }
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}
chrome.storage.local.get(["config-fetch_hook"], function (res) {
if (!result.body){ fillfunc(result.body); return }
// save html
if (html_copy){
if ( params.resourceType == 'Script'
|| params.resourceType == 'Document'
|| params.resourceType == 'Stylesheet'
|| params.resourceType == 'Image'
|| params.resourceType == 'Font'
|| params.resourceType == 'Other'
){
if (params.resourceType == 'Script'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Document'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Stylesheet'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Image'){ var save_info = result.body }
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)
}
console.log(params.resourceType, params.request.url)
if (result.body !== undefined){ // 收到的 result.body 是 base64(代码) 的代码,使用时需要解码一下
if (params.resourceType == 'Script' || params.resourceType == 'Document'){
chrome.storage.local.get(["config-fetch_hook"], function (res) {
// ast hook
if (ast_dyn_hook){
if ( params.resourceType == 'Script'
|| params.resourceType == 'Document'
){
try{
var respboby = decodeURIComponent(escape(atob(result.body)))
var replacer = eval((res["config-fetch_hook"]||'')+';fetch_hook')
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)) }
fillfunc(btoa(unescape(encodeURIComponent(replbody)))) }
fillfunc(btoa(unescape(encodeURIComponent(replbody))))
return }
catch(e){
send_error_info_to_front(e.stack, currtab.tabId, params.request.url)
fillfunc(result.body) }
})
return
send_error_info_to_front(e.stack, currtab.tabId, params.request.url) }
}
}
}
fillfunc(result.body) // body 只能传 base64(指定代码)
fillfunc(result.body) // body 只能传 base64(指定代码)
})
return
});
break; }
}
})
chrome.debugger.onDetach.addListener(function(){ attached = false })
chrome.debugger.onDetach.addListener(function(){
close_debugger()
})
var attached = false
var currtab;
function AttachDebugger() {
@ -315,6 +339,36 @@ function get_html(url){
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.browserAction.setBadgeBackgroundColor({color: '#BC1717'});
if (e['config-hook-global']){
@ -322,4 +376,32 @@ chrome.storage.local.get(['config-hook-global'], function(e){
}else{
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",
"version": "0.0.0",
"description": "v_jstools js hook工具",
"permissions": ["storage",
"unlimitedStorage",
"permissions": ["unlimitedStorage",
"activeTab",
"webRequest",
"webRequestBlocking",
"tabs",
"debugger",
"storage",
"contextMenus",
"http://*/*",
"https://*/*",
"<all_urls>",
"cookies",
"downloads",
"proxy"

View File

@ -17,7 +17,7 @@
<ul>
<button class="act">dom对象 hook 配置</button>
<button>注入代码</button>
<button>高级 hook 修改 response 返回值</button>
<button>修改返回值</button>
<button>AST混淆解密</button>
<button>代码模板(RPC...)</button>
<button>混淆器</button>
@ -132,7 +132,14 @@
<!-- <div>修改代理:<input type="text" data-key="config-proxy_config" id="proxy_config"></div> -->
</section>
<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>*能直接用插件的方式实现 ast 修改代码,用处还是非常大的。不过目前感觉功能稍微有点干瘪,因为暂时还在想有什么 ast 修改模板代码会更好的捕捉代码信息,让代码更方便的调试。</div>
<HR>
@ -230,6 +237,7 @@
<textarea id='jsobfuscator_code' style="width: 100%; height: 500px" placeholder="输出代码"></textarea>
</section>
</div>
<script src="tools/jquery.min.js"></script>
<script src="options.js"></script>
<script src="tools/model_funcs.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
}
})
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'
});
}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