kone base64 자동복호화

base64코드 자동복호화

目前為 2025-05-26 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         kone base64 자동복호화
// @namespace    http://tampermonkey.net/
// @version      0.244
// @description   base64코드 자동복호화
// @author       SYJ
// @match        https://arca.live/*
// @match https://kone.gg/s/somisoft*
// @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
// @license MIT
// ==/UserScript==

// 자주 바뀜. 취약한 셀렉터
const SHADOW_ROOT_SELECTOR = "body  main div.prose-container";

async function main(){
    const isAutoMode = await GM_getValue('toggleVal', true);

    if (isAutoMode) {
        autoApply();
        setInterval(autoApply, 1500);
    }
    else {
        setTimeout(manuallyApply, 1000);
    }
}

function doDecode(text) {
    ///'use strict';
    let result = text;
    result = dec(/aHR0c[0-9A-Za-z+]{20,}[=]{0,2}/, result); //aHR0c:1회인코딩된것.
    result = dec(/YUhSMGN[0-9A-Za-z]{20,}[=]{0,2}/, result); //YUhSMGN:2회인코딩된것.
    result = dec(/WVVoU01HTklUVFp[0-9A-Za-z+]{20,}[=]{0,2}/, result); //aHR0c:1회인코딩된것.
    result = dec(/V1ZWb1UwMUhUa2[0-9A-Za-z]{20,}[=]{0,2}/, result); //YUhSMGN:2회인코딩된것.
    result = dec(/[0-9A-Za-z]{30,}[=]{1,2}/, result); //문자열 30회 + '=' 1~2회
    result = dec(/[0-9A-Za-z]{200,}[=]{0,2}/, result); //문자열 200회 + '=' 0~2회
    return result;


}
function dec(reg, text) {
    let result = text;
    try {
        while (reg.test(result)) {
            const original = reg.exec(result)[0];
            let decoded = original;
            while (decoded.match(/aHR0c[0-9A-Za-z]{8,}[=]{0,2}/) == null){
                decoded = atob(decoded);
            }
            decoded = atob(decoded); console.log(decoded);
            result = result.replace(original, decoded);
        }
        return result;
    }
    catch(e) { console.log('er', e);
              return text;}
}

function applyATag(el){
    if (original === decodedLink) return;
    while(el.firstChild) el.removeChild(el.firstChild);
    el.appendChild(makeATag(decodedLink));
}

function manuallyApply() {
    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);
        }
    })
}

// 텍스트노드 중 url을 찾아 a태그로 변환. (액션 포함)
function linkifyTextNode(Node, text) {
  // URL 매칭 (https:// 로 시작해서 공백 전까지)
  const urlRegex = /(https?:\/\/[^\s]+)/;
  const match = urlRegex.exec(text);
  if (!match) return;  // URL 없으면 종료

  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);
}

const textTagNames = 'p, span, div, a, li,' +      // 일반 컨테이너
  'h1, h2, h3, h4, h5, h6,' +    // 제목 요소
  'em, strong, b, i, small,' +   // 인라인 포맷팅 요소
  'label, button, option, textarea' // 폼/인터페이스 요소

function autoApply() {
    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;}
            linkifyTextNode(node, decodedLink);
        }
    }
}


function makeATag(link){
    const aTag = document.createElement('a');
    aTag.href = link;
    aTag.textContent = link;
    aTag.target = '_blank';
    aTag.rel = 'noreferrer';
    return aTag;
}

window.addEventListener('load', ()=>{
    main();
    
});

// UI

/* 프롬프트형 입력
(async function(){
    let v = await GM_getValue('myValue', 123);
    let menuId;

    function registerMenu(){
        if(menuId) GM_unregisterMenuCommand(menuId);
        // 레이블에 현재 v 를 포함
        menuId = GM_registerMenuCommand(
            `설정 입력 (현재 값: ${v})`,
            async () => {
                const input = prompt('새 값을 입력하세요:', v);
                if(input !== null){
                    const n = parseInt(input);
                    if(!isNaN(n)){
                        v = n;
                        await GM_setValue('myValue', v);
                        registerMenu(); // 메뉴 레이블 갱신
                    } else {
                        alert('숫자만 입력하세요');
                    }
                }
            }
        );
    }

    registerMenu();
    // — 여기서 v 를 실제 화면에 표시하거나 쓰고 싶다면,
    //   document.body.append(`현재 값: ${v}`) 같은 DOM 추가로 처리하세요.
})();
*/


(async function() {
    // 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();
})();