您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
base64코드 자동복호화
当前为
// ==UserScript== // @name kone base64 자동복호화 // @namespace http://tampermonkey.net/ // @version 1.2.4 // @description base64코드 자동복호화 // @author SYJ // @match https://arca.live/* // @match https://kone.gg/* // @icon https://www.google.com/s2/favicons?sz=64&domain=arca.live // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_addValueChangeListener // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @license MIT // ==/UserScript== // 자주 바뀜. 취약한 셀렉터 const SHADOW_ROOT_SELECTOR = "body main div.prose-container"; const MAX_DECODE_COUNT = 10+1; window.addEventListener('load', ()=>setTimeout(main, 1000)); async function main(){ observeUrlChange(renderUI); const isAutoMode = await GM_getValue('toggleVal', true); if (isAutoMode) { observeUrlChange(applyAuto); } else { setTimeout(applyManually, 1000); } } function applyManually() { document.body.addEventListener('dblclick', function(e) { console.log('더블클릭 감지! 🎉',e.target,event.composedPath()[0]); const el = e.composedPath()[0]; const nodes = Array.from(el.childNodes).filter(node=>node.nodeType ===Node.TEXT_NODE) console.log(nodes) for (const node of nodes){ const original = node.textContent; const decodedLink = doDecode(original); // console.log(node, original, decodedLink); if (original === decodedLink) continue; linkifyTextNode(node, decodedLink); } }) } function applyAuto() { const contents = Array.from(document.body.querySelectorAll(`main ${textTagNames}`)); const mainContents = Array.from(document.querySelector(SHADOW_ROOT_SELECTOR)?.shadowRoot?.querySelectorAll(textTagNames) ?? []); contents.push(...mainContents); for (const tag of contents) { const nodes = Array.from(tag.childNodes).filter(node=>node.nodeType ===Node.TEXT_NODE) for (const node of nodes){ const original = node.textContent; const decodedLink = doDecode(original); if (original === decodedLink) continue; console.log('[DECODE] ',original, decodedLink); linkifyTextNode(node, decodedLink); } } } const textTagNames = 'p, span, div, a, li,' + // 일반 컨테이너 'h1, h2, h3, h4, h5, h6,' + // 제목 요소 'em, strong, u, b, i, small, mark, ' + // 인라인 포맷팅 요소 'label, button, option, textarea' // 폼/인터페이스 요소 function linkifyTextNode(Node, text) { // 텍스트노드 중 url을 찾아 a태그로 변환. (액션 포함) // URL 매칭 (https:// 로 시작해서 공백 전까지) const urlRegex = /(https?:\/\/[^\s]+)/; const match = urlRegex.exec(text); if (!match) { // URL 없으면 텍스트 덮어씌우고 종료 Node.textContent = text; return; } const url = match[0]; const start = match.index; const urlLen = url.length; // "텍스트1 URL 텍스트2" 꼴의 텍스트노드를 세 개로 분리 // 1) URL 앞부분과 뒤를 분리 const textNode = document.createTextNode(text); const afterUrlStart = textNode.splitText(start); const afterUrlEnd = afterUrlStart.splitText(urlLen); const beforeUrlStart = textNode; // 3) <a> 요소 생성 후 URL 텍스트 노드 대신 교체 const a = makeATag(url) Node.parentNode.replaceChild(a, Node); a.before(beforeUrlStart); a.after(afterUrlEnd); function makeATag(link){ const aTag = document.createElement('a'); aTag.href = link; aTag.textContent = link; aTag.target = '_blank'; aTag.rel = 'noreferrer'; return aTag; } } function doDecode(text) { ///'use strict'; let result = text; result = dec(/[0-9A-Za-z]{6,}[=]{0,2}/, result); //문자열 6회 + '=' 0~2회 return result; function dec(reg, text) { let result = text; const originals = Array.from(reg.exec(result) ?? []); for (const original of originals){ const decoded = decodeNtime(original); result = result.replace(original, decoded); } return result; } } function decodeNtime(str) { let decoded = str; for (let i=0; i<MAX_DECODE_COUNT; i++){ const old = decoded; decoded = decodeOneTime(decoded); if (decoded === old) return decoded; } function decodeOneTime(str) { try { return base64DecodeUnicode(str); } catch { return str; } } function base64DecodeUnicode(str) { // 1) atob으로 디코딩 → 바이너리(한 글자당 1바이트) 문자열 // 2) 각 문자 코드를 16진수 %xx 형태로 변환 // 3) decodeURIComponent로 UTF-8 해석 const percentEncodedStr = Array .from(atob(str)) .map(char => '%' + char.charCodeAt(0).toString(16).padStart(2, '0')) .join(''); return decodeURIComponent(percentEncodedStr); } } // UI async function renderUI() { // 1) 값 로드 let val = await GM_getValue('toggleVal', false); let menuId; // 2) 배지 생성 /* const badge = document.createElement('div'); Object.assign(badge.style, { position: 'fixed', top: '10px', right: '10px', padding: '4px 8px', background: 'rgba(0,0,0,0.7)', color: '#fff', fontSize: '14px', borderRadius: '4px', zIndex: '9999', }); document.body.append(badge); */ // 3) 렌더 함수 function render() { // 메뉴 해제 후 다시 등록 if (menuId) GM_unregisterMenuCommand(menuId); menuId = GM_registerMenuCommand( `자동모드 토글 (현재: ${val?'ON':'OFF'})`, toggleValue ); // 배지 업데이트 //badge.textContent = `현재 값: ${val}`; } // 4) 토글 함수 (즉시 UI 업데이트 포함) async function toggleValue() { const newVal = !val; await GM_setValue('toggleVal', newVal); val = newVal; // 변수 갱신 render(); // 메뉴·배지 즉시 갱신 } // 초기 렌더 render(); } const observeUrlChange = (func) => { func(); let oldHref = document.location.href; const body = document.querySelector('body'); const observer = new MutationObserver(mutations => { if (oldHref !== document.location.href) { oldHref = document.location.href; setTimeout(func, 1000); } }); observer.observe(body, { childList: true, subtree: true }); };
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址