초기 PM 소스 전체 업로드

This commit is contained in:
koj729
2026-06-12 17:14:03 +09:00
commit 4e33c9a02a
1769 changed files with 377797 additions and 0 deletions

821
views/anti_debugging.js Normal file
View File

@@ -0,0 +1,821 @@
export class AntiDebug {
constructor() {
this.checks = [];
this.isDestroyed = false;
this.originalScripts = new Map();
this.detectionCount = 0;
this.monitoringIntervals = [];
// 감지 시작(개발자 모드에서는 주석처리)
// this.emergencyProtection();
// this.init();
}
emergencyProtection() {
// 페이지 로드 즉시 실행
const script = document.createElement('script');
script.textContent = `
(function() {
const start = Date.now();
debugger;
if (Date.now() - start > 100) {
document.documentElement.innerHTML = '<h1 style="color:red;text-align:center;margin-top:50vh;">Access Denied</h1>';
while(true) { debugger; }
}
})();
`;
if (document.head) {
document.head.insertBefore(script, document.head.firstChild);
}
}
async init() {
// 모든 스크립트의 실제 내용을 메모리에 저장
await this.captureAllScriptContents();
// 체크 메서드 등록
this.checks.push(this.checkConsole.bind(this));
this.checks.push(this.checkDebugger.bind(this));
this.checks.push(this.checkToString.bind(this));
// this.checks.push(this.checkDevToolsSize.bind(this)); //사이즈는 사이니지때문에 우선 주석
// 다층 보호 시작
this.protectFunctions();
this.blockDevToolsShortcuts();
this.overrideNetworkAPIs();
this.polluteDOMWithFakes();
// 체크 시작
this.startAggressiveMonitoring();
}
async captureAllScriptContents() {
try {
const scripts = document.querySelectorAll('script');
for (const script of scripts) {
if (script.src) {
try {
// 외부 스크립트 fetch
const response = await fetch(script.src);
const content = await response.text();
this.originalScripts.set(script.src, {
type: 'external',
content: content,
element: script,
url: script.src
});
} catch(e) {
console.error('Failed to capture:', script.src);
}
} else if (script.textContent) {
this.originalScripts.set(`inline_${Date.now()}_${Math.random()}`, {
type: 'inline',
content: script.textContent,
element: script
});
}
}
} catch(e) {
console.error('Script capture failed:', e);
}
}
startAggressiveMonitoring() {
// 다양한 간격으로 체크 (회피 어렵게)
const intervals = [500, 1000, 1500, 2000, 3000];
intervals.forEach(interval => {
const id = setInterval(() => this.runChecks(), interval);
this.monitoringIntervals.push(id);
});
// requestAnimationFrame으로도 체크
const rafCheck = () => {
if (!this.isDestroyed) {
this.runChecks();
requestAnimationFrame(rafCheck);
}
};
requestAnimationFrame(rafCheck);
}
checkConsole() {
try {
const start = performance.now();
const devtools = {};
Object.defineProperty(devtools, 'toString', {
get: function() {
return true;
}
});
console.log('%c', devtools);
const end = performance.now();
return (end - start) > 100;
} catch(e) {
return false;
}
}
checkDebugger() {
try {
const start = performance.now();
debugger;
const end = performance.now();
return (end - start) > 100;
} catch(e) {
return false;
}
}
checkToString() {
try {
let detected = false;
const detector = /./;
detector.toString = function() {
detected = true;
};
console.log('%c', detector);
return detected;
} catch(e) {
return false;
}
}
checkDevToolsSize() {
const widthThreshold = window.outerWidth - window.innerWidth > 160;
const heightThreshold = window.outerHeight - window.innerHeight > 160;
return widthThreshold || heightThreshold;
}
protectFunctions() {
try {
const originalToString = Function.prototype.toString;
const self = this;
Function.prototype.toString = function() {
const fnString = originalToString.call(this);
const fnName = this.name || '';
// AntiDebug 관련 함수는 숨김
if (fnName.includes('check') ||
fnName.includes('Anti') ||
fnName.includes('destroy') ||
fnName.includes('protect') ||
fnString.includes('debugger')) {
return `function ${fnName}() { [native code] }`;
}
return fnString;
};
// Object.defineProperty도 보호
const originalDefineProperty = Object.defineProperty;
Object.defineProperty = function(obj, prop, descriptor) {
// console 조작 방지
if (obj === console || obj === window.console) {
return obj;
}
return originalDefineProperty(obj, prop, descriptor);
};
} catch(e) {}
}
blockDevToolsShortcuts() {
// 모든 개발자 도구 단축키 차단
document.addEventListener('keydown', (e) => {
const forbidden = [
e.keyCode === 123, // F12
e.ctrlKey && e.shiftKey && e.keyCode === 73, // Ctrl+Shift+I
e.ctrlKey && e.shiftKey && e.keyCode === 74, // Ctrl+Shift+J
e.ctrlKey && e.shiftKey && e.keyCode === 67, // Ctrl+Shift+C
e.ctrlKey && e.keyCode === 85, // Ctrl+U
e.metaKey && e.altKey && e.keyCode === 73, // Cmd+Option+I (Mac)
e.metaKey && e.altKey && e.keyCode === 74, // Cmd+Option+J (Mac)
e.metaKey && e.altKey && e.keyCode === 67, // Cmd+Option+C (Mac)
];
if (forbidden.some(x => x)) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// this.increaseDetectionCount();
return false;
}
}, true);
// 우클릭 완전 차단
// document.addEventListener('contextmenu', (e) => {
// e.preventDefault();
// e.stopPropagation();
// return false;
// }, true);
// 선택 차단
// document.addEventListener('selectstart', (e) => {
// e.preventDefault();
// return false;
// });
// 드래그 차단
// document.addEventListener('dragstart', (e) => {
// e.preventDefault();
// return false;
// });
}
overrideNetworkAPIs() {
// fetch API 오버라이드
const originalFetch = window.fetch;
const self = this;
window.fetch = async function(...args) {
const url = args[0];
// DevTools가 감지된 경우
if (self.isDestroyed && typeof url === 'string' && url.endsWith('.js')) {
console.log('Blocked fetch request:', url);
// 가짜 응답 반환
return new Response(
self.generateMassiveGarbageCode(),
{
status: 200,
headers: { 'Content-Type': 'application/javascript' }
}
);
}
return originalFetch.apply(this, args);
};
// XMLHttpRequest 오버라이드
const originalXHROpen = XMLHttpRequest.prototype.open;
const originalXHRSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
this._url = url;
return originalXHROpen.call(this, method, url, ...rest);
};
XMLHttpRequest.prototype.send = function(...args) {
if (self.isDestroyed && this._url && this._url.endsWith('.js')) {
console.log('Blocked XHR request:', this._url);
// 가짜 응답 설정
Object.defineProperty(this, 'responseText', {
writable: true,
value: self.generateMassiveGarbageCode()
});
Object.defineProperty(this, 'response', {
writable: true,
value: self.generateMassiveGarbageCode()
});
// 성공 이벤트 발생
setTimeout(() => {
this.readyState = 4;
this.status = 200;
if (this.onload) this.onload();
if (this.onreadystatechange) this.onreadystatechange();
}, 0);
return;
}
return originalXHRSend.apply(this, args);
};
}
polluteDOMWithFakes() {
const fakeCount = 200; // 200개의 가짜 스크립트
const scriptPaths = [
'main/main.js',
'main/app.js',
'main/utils.js',
'main/api.js',
'main/config.js',
'login/login.js',
'login/auth.js',
'login/validator.js',
'index/index.js',
'index/controller.js',
'index/router.js'
];
// 각 파일명마다 여러 버전의 가짜 생성
scriptPaths.forEach(path => {
for (let i = 0; i < 20; i++) {
const fakeScript = document.createElement('script');
fakeScript.setAttribute('data-fake-source', path);
fakeScript.setAttribute('data-version', `v${i}`);
fakeScript.type = 'text/javascript';
fakeScript.textContent = this.generateRealisticFakeCode(path, i);
if (document.head) {
document.head.appendChild(fakeScript);
}
}
});
}
generateRealisticFakeCode(filename, version) {
const modules = ['auth', 'api', 'utils', 'config', 'router', 'store'];
const functions = ['init', 'setup', 'validate', 'process', 'handle', 'execute'];
return `
// ===================================================================
// Module: ${filename} (Protected Version ${version})
// Build: ${Math.random().toString(36).substr(2, 10).toUpperCase()}
// Status: ENCRYPTED - Original source removed
// ===================================================================
(function(global, factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory();
} else {
global._Module_${Math.random().toString(36).substr(2, 8)} = factory();
}
}(typeof window !== 'undefined' ? window : this, function() {
'use strict';
// ============ Obfuscated Configuration ============
const _config_${Math.random().toString(36).substr(2, 6)} = {
${this.generateFakeConfig()}
};
// ============ Protected Functions ============
${functions.map(fn => this.generateFakeFunction(fn)).join('\n\n')}
// ============ Anti-Tampering ============
const _protect = function() {
try {
debugger;
const _check = function() {
if (window.console || window.devtools) {
debugger;
}
};
setInterval(_check, ${Math.floor(Math.random() * 50) + 30});
} catch(e) {}
};
_protect();
// ============ Encrypted Variables ============
${this.generateEncryptedVars(50)}
// ============ Return Protected Module ============
return Object.freeze({
version: '${version}.0.0',
protected: true,
${functions.map(fn => `${fn}: _fn_${fn}`).join(',\n ')}
});
}));
// Additional protection layer
${this.generateComplexGarbageCode()}
`;
}
generateFakeConfig() {
const configs = [];
for (let i = 0; i < 15; i++) {
configs.push(` key_${i}: "${Math.random().toString(36).substr(2, 12)}"`);
}
return configs.join(',\n');
}
generateFakeFunction(name) {
return ` const _fn_${name} = function(params) {
const _internal_${Math.random().toString(36).substr(2, 6)} = params || {};
// Protected logic
${Array(5).fill(0).map((_, i) =>
`const _var${i} = "${Math.random().toString(36).substr(2, 8)}";`
).join('\n ')}
try { debugger; } catch(e) {}
return _internal_${Math.random().toString(36).substr(2, 6)};
};`;
}
generateEncryptedVars(count) {
let vars = [];
for (let i = 0; i < count; i++) {
vars.push(` const _0x${Math.random().toString(36).substr(2, 8)} = ${Math.random()};`);
}
return vars.join('\n');
}
generateComplexGarbageCode() {
return `
(function() {
const _obf = {
${Array(30).fill(0).map(() =>
`_${Math.random().toString(36).substr(2, 8)}: "${Math.random().toString(36).substr(2)}"`
).join(',\n ')}
};
setInterval(() => { try { debugger; } catch(e) {} }, ${Math.floor(Math.random() * 100) + 50});
})();
`;
}
generateMassiveGarbageCode() {
let code = `
// ============================================
// PROTECTED SOURCE - ACCESS DENIED
// ============================================
// This is not the original source code
// All sources have been encrypted
// Timestamp: ${Date.now()}
// ============================================
`;
// 대량의 가짜 코드 생성
for (let i = 0; i < 100; i++) {
code += `const _obf_${i}_${Math.random().toString(36).substr(2, 8)} = ${Math.random()};\n`;
}
code += `\n(function() {\n`;
code += ` 'use strict';\n\n`;
for (let i = 0; i < 50; i++) {
code += ` var _${Math.random().toString(36).substr(2, 8)} = "${Math.random().toString(36).substr(2)}";\n`;
}
code += `\n setInterval(function() {\n`;
code += ` debugger;\n`;
code += ` }, 50);\n`;
code += `\n (function infiniteDebugger() {\n`;
code += ` try {\n`;
code += ` debugger;\n`;
code += ` setTimeout(infiniteDebugger, 10);\n`;
code += ` } catch(e) {}\n`;
code += ` })();\n`;
code += `})();\n`;
return code;
}
increaseDetectionCount() {
this.detectionCount++;
if (this.detectionCount >= 2) {
this.onDetected();
}
}
runChecks() {
if (this.isDestroyed) return;
let detectedCount = 0;
for (let check of this.checks) {
try {
if (check()) {
detectedCount++;
}
} catch(e) {}
}
if (detectedCount >= 2) {
this.onDetected();
}
}
nukeAllScripts() {
try {
// 1. 모든 기존 script 태그의 내용을 가짜로 교체
const allScripts = document.querySelectorAll('script');
allScripts.forEach(script => {
if (script.src) {
// src가 있는 스크립트는 제거하고 inline으로 가짜 삽입
const fakeInline = document.createElement('script');
fakeInline.textContent = this.generateMassiveGarbageCode();
fakeInline.setAttribute('data-original-src', script.src);
if (script.parentNode) {
script.parentNode.replaceChild(fakeInline, script);
}
} else {
// inline 스크립트는 내용만 교체
script.textContent = this.generateMassiveGarbageCode();
}
});
// 2. 추가로 대량의 가짜 스크립트 주입 (이미 polluteDOMWithFakes에서 했지만 더 추가)
for (let i = 0; i < 100; i++) {
const fakeScript = document.createElement('script');
fakeScript.textContent = this.generateMassiveGarbageCode();
fakeScript.setAttribute('data-protection-layer', i);
if (document.body) {
document.body.appendChild(fakeScript);
}
}
} catch(e) {
console.error('Script nuking failed:', e);
}
}
destroyDOMCompletely() {
try {
// DOM 전체를 새로운 내용으로 교체
const newHTML = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Access Denied</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #000000 0%, #1a0000 100%);
color: #ff0000;
font-family: 'Courier New', Courier, monospace;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
position: relative;
}
.glitch {
position: relative;
font-size: 5em;
font-weight: bold;
text-transform: uppercase;
animation: glitch 1s infinite;
}
.glitch::before,
.glitch::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.glitch::before {
animation: glitch-before 0.3s infinite;
clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%);
transform: translate(-5px, -5px);
opacity: 0.8;
}
.glitch::after {
animation: glitch-after 0.3s infinite;
clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%);
transform: translate(5px, 5px);
opacity: 0.8;
}
@keyframes glitch {
0%, 100% { transform: translate(0); }
25% { transform: translate(-5px, 5px); }
50% { transform: translate(5px, -5px); }
75% { transform: translate(-5px, -5px); }
}
@keyframes glitch-before {
0%, 100% { clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%); }
50% { clip-path: polygon(0 20%, 100% 20%, 100% 60%, 0 60%); }
}
@keyframes glitch-after {
0%, 100% { clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%); }
50% { clip-path: polygon(0 30%, 100% 30%, 100% 80%, 0 80%); }
}
.container {
text-align: center;
z-index: 10;
}
.subtitle {
font-size: 1.5em;
margin-top: 30px;
opacity: 0.8;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.8; }
50% { opacity: 0.3; }
}
.warning {
margin-top: 20px;
font-size: 1.2em;
color: #ff3333;
}
</style>
</head>
<body>
<div class="container">
<h1 class="glitch" data-text="⚠ ACCESS DENIED ⚠">⚠ ACCESS DENIED ⚠</h1>
<p class="subtitle">DEVELOPER TOOLS DETECTED</p>
<p class="warning">All source code has been encrypted</p>
<p class="warning">Unauthorized access logged</p>
</div>
${this.generateInlineProtectionScripts()}
</body>
</html>
`;
// 문서 전체 교체
document.open();
document.write(newHTML);
document.close();
} catch(e) {
console.error('DOM destruction failed:', e);
}
}
generateInlineProtectionScripts() {
let scripts = '';
// 10개의 보호 스크립트 레이어
for (let i = 0; i < 10; i++) {
scripts += `
<script>
${this.generateMassiveGarbageCode()}
</script>
`;
}
return scripts;
}
createMultiLayerDebuggerTrap() {
// 레이어 1: 초고속 interval
setInterval(() => {
if (this.isDestroyed) debugger;
}, 10);
// 레이어 2: 중속 interval
setInterval(() => {
if (this.isDestroyed) debugger;
}, 50);
// 레이어 3: 저속 interval
setInterval(() => {
if (this.isDestroyed) debugger;
}, 200);
// 레이어 4: setTimeout 재귀
const timeoutTrap = () => {
if (this.isDestroyed) {
debugger;
setTimeout(timeoutTrap, 30);
}
};
timeoutTrap();
// 레이어 5: requestAnimationFrame
const rafTrap = () => {
if (this.isDestroyed) {
debugger;
requestAnimationFrame(rafTrap);
}
};
requestAnimationFrame(rafTrap);
// 레이어 6: Promise 체인
const promiseTrap = () => {
if (this.isDestroyed) {
debugger;
Promise.resolve().then(promiseTrap);
}
};
promiseTrap();
// 레이어 7: setImmediate (Node.js style, 있으면)
if (typeof setImmediate !== 'undefined') {
const immediateTrap = () => {
if (this.isDestroyed) {
debugger;
setImmediate(immediateTrap);
}
};
immediateTrap();
}
// 레이어 8: 최후의 무한 루프 (3초 후 실행)
setTimeout(() => {
if (this.isDestroyed) {
while(true) {
debugger;
}
}
}, 3000);
}
lockPageCompletely() {
try {
// 뒤로가기 완전 차단
history.pushState(null, null, location.href);
window.onpopstate = function() {
history.go(1);
};
// 새로고침 차단
window.onbeforeunload = function(e) {
e.preventDefault();
return "Developer tools detected";
};
// 모든 키보드 입력 차단
document.addEventListener('keydown', (e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
return false;
}, true);
// 모든 마우스 이벤트 차단
['click', 'mousedown', 'mouseup', 'dblclick', 'contextmenu'].forEach(eventType => {
document.addEventListener(eventType, (e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
return false;
}, true);
});
// 모든 터치 이벤트 차단
['touchstart', 'touchend', 'touchmove'].forEach(eventType => {
document.addEventListener(eventType, (e) => {
e.preventDefault();
e.stopPropagation();
return false;
}, true);
});
} catch(e) {}
}
onDetected() {
if (this.isDestroyed) return;
console.clear();
// 상태 플래그 설정
this.isDestroyed = true;
// 모든 모니터링 interval 중지
this.monitoringIntervals.forEach(id => clearInterval(id));
this.monitoringIntervals = [];
// 경고
// alert('⚠️ Developer Tools Detected!\n\nPM에서는 개발자툴 사용이 불가능합니다.');
// 실행 순서 (매우 중요!)
// 1단계: 모든 스크립트 즉시 파괴
this.nukeAllScripts();
// 2단계: 네트워크 요청 오버라이드 (이미 init에서 했지만 재확인)
this.overrideNetworkAPIs();
// 3단계: 페이지 완전 잠금
this.lockPageCompletely();
// 4단계: 다층 디버거 트랩 시작
this.createMultiLayerDebuggerTrap();
// 5단계: DOM 완전 파괴 (선택적 - 매우 공격적)
setTimeout(() => {
this.destroyDOMCompletely();
}, 1000);
// 6단계: localStorage에 감지 기록
try {
localStorage.setItem('devtools_detected', Date.now().toString());
localStorage.setItem('access_blocked', 'true');
} catch(e) {}
}
}