mirror of
https://github.com/elder-plinius/P4RS3LT0NGV3.git
synced 2026-06-06 06:53:56 +02:00
Fix emoji encoding and improve universal decoder
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/* Copy notification styles */
|
||||
.copy-notification {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background-color: #25282c;
|
||||
color: #00FF41;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
animation: fade-in 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.copy-notification.error {
|
||||
color: #ff4141;
|
||||
}
|
||||
|
||||
.copy-notification.fade-out {
|
||||
animation: fade-out 0.3s ease-in-out forwards;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 1; transform: translateY(0); }
|
||||
to { opacity: 0; transform: translateY(20px); }
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Parseltongue 2.0 - LLM Payload Crafter</title>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<link rel="stylesheet" href="css/notification.css">
|
||||
<!-- Vue.js -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
|
||||
<!-- Font Awesome for icons -->
|
||||
|
||||
@@ -83,23 +83,15 @@ new Vue({
|
||||
return;
|
||||
}
|
||||
|
||||
// Try invisible text decoding
|
||||
let decoded = window.steganography.decodeInvisible(this.decodeInput);
|
||||
if (decoded) {
|
||||
this.decodedMessage = decoded;
|
||||
this.copyToClipboard(decoded);
|
||||
return;
|
||||
// Use the universal decoder
|
||||
const result = this.universalDecode(this.decodeInput);
|
||||
|
||||
if (result) {
|
||||
this.decodedMessage = `Decoded (${result.method}): ${result.text}`;
|
||||
this.copyToClipboard(result.text);
|
||||
} else {
|
||||
this.decodedMessage = 'No encoded message detected';
|
||||
}
|
||||
|
||||
// Try emoji decoding
|
||||
decoded = window.steganography.decodeEmoji(this.decodeInput);
|
||||
if (decoded) {
|
||||
this.decodedMessage = decoded;
|
||||
this.copyToClipboard(decoded);
|
||||
return;
|
||||
}
|
||||
|
||||
this.decodedMessage = 'No hidden message found';
|
||||
},
|
||||
previewInvisible(text) {
|
||||
return '[invisible]';
|
||||
@@ -107,11 +99,120 @@ new Vue({
|
||||
|
||||
// Utility Methods
|
||||
async copyToClipboard(text) {
|
||||
if (!text) return;
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
|
||||
// Show a brief notification
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'copy-notification';
|
||||
notification.innerHTML = '<i class="fas fa-check"></i> Copied!';
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// Remove after animation
|
||||
setTimeout(() => {
|
||||
notification.classList.add('fade-out');
|
||||
setTimeout(() => document.body.removeChild(notification), 300);
|
||||
}, 1000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy text:', err);
|
||||
// Show error notification
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'copy-notification error';
|
||||
notification.innerHTML = '<i class="fas fa-times"></i> Copy failed';
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.classList.add('fade-out');
|
||||
setTimeout(() => document.body.removeChild(notification), 300);
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
// Universal Decoder - tries all decoding methods
|
||||
universalDecode(input) {
|
||||
if (!input) return '';
|
||||
|
||||
// Try all decoders in order
|
||||
|
||||
// 1. Try steganography decoders
|
||||
// - Check for emoji steganography first
|
||||
// The emoji encoding uses variation selectors which are hard to see
|
||||
if (/[\u{1F300}-\u{1F6FF}\u{2600}-\u{26FF}]/u.test(input)) {
|
||||
const decoded = window.steganography.decodeEmoji(input);
|
||||
if (decoded) {
|
||||
return { text: decoded, method: 'Emoji Steganography' };
|
||||
}
|
||||
}
|
||||
|
||||
// - Invisible text
|
||||
let decoded = window.steganography.decodeInvisible(input);
|
||||
if (decoded) {
|
||||
return { text: decoded, method: 'Invisible Text' };
|
||||
}
|
||||
|
||||
// 2. Try transform reversals
|
||||
// - Binary
|
||||
if (/^[01\s]+$/.test(input.trim())) {
|
||||
try {
|
||||
// Use binary transform's reverse function if available
|
||||
if (window.transforms.binary && window.transforms.binary.reverse) {
|
||||
const result = window.transforms.binary.reverse(input);
|
||||
if (result && /[\x20-\x7E]/.test(result)) { // Make sure it's readable ASCII
|
||||
return { text: result, method: 'Binary' };
|
||||
}
|
||||
} else {
|
||||
// Fallback implementation
|
||||
const binText = input.replace(/\s+/g, '');
|
||||
let result = '';
|
||||
for (let i = 0; i < binText.length; i += 8) {
|
||||
const byte = binText.substr(i, 8);
|
||||
if (byte.length === 8) {
|
||||
result += String.fromCharCode(parseInt(byte, 2));
|
||||
}
|
||||
}
|
||||
if (result && /[\x20-\x7E]/.test(result)) { // Make sure it's readable ASCII
|
||||
return { text: result, method: 'Binary' };
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Binary decode error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// - Morse code
|
||||
if (/^[.\-\s\/]+$/.test(input.trim())) {
|
||||
try {
|
||||
// Use morse transform's reverse function if available
|
||||
if (window.transforms.morse && window.transforms.morse.reverse) {
|
||||
const result = window.transforms.morse.reverse(input);
|
||||
if (result !== input && /[a-zA-Z0-9]/.test(result)) {
|
||||
return { text: result, method: 'Morse Code' };
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Morse decode error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// - Try reverse each transform
|
||||
for (const name in window.transforms) {
|
||||
const transform = window.transforms[name];
|
||||
if (transform.reverse) {
|
||||
try {
|
||||
const result = transform.reverse(input);
|
||||
// Only return if the result is different and contains readable characters
|
||||
if (result !== input && /[a-zA-Z0-9\s]/.test(result)) {
|
||||
return { text: result, method: transform.name };
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error decoding with ${name}:`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
},
|
||||
// Initialize theme
|
||||
|
||||
+27
-17
@@ -6,24 +6,22 @@ const carriers = [
|
||||
{ emoji: '🐊', name: 'CROCODILE', desc: 'Dangerous Croc', preview: text => `🐊${text}` }
|
||||
];
|
||||
|
||||
// Variation selector functions
|
||||
function toVariationSelector(byte) {
|
||||
return String.fromCodePoint(0xFE00 + byte);
|
||||
}
|
||||
|
||||
function fromVariationSelector(codePoint) {
|
||||
return codePoint - 0xFE00;
|
||||
}
|
||||
|
||||
// Emoji encoding/decoding
|
||||
function encodeEmoji(emoji, text) {
|
||||
if (!text) return '';
|
||||
if (!text) return emoji;
|
||||
|
||||
// Convert text to binary string
|
||||
const binary = Array.from(text)
|
||||
.map(c => c.charCodeAt(0).toString(2).padStart(8, '0'))
|
||||
.join('');
|
||||
|
||||
// Use variation selectors to encode binary
|
||||
const vs15 = '\ufe0e'; // text variation selector (0)
|
||||
const vs16 = '\ufe0f'; // emoji variation selector (1)
|
||||
|
||||
const bytes = new TextEncoder().encode(text);
|
||||
let result = emoji;
|
||||
|
||||
for (const byte of bytes) {
|
||||
result += toVariationSelector(byte);
|
||||
for (const bit of binary) {
|
||||
result += bit === '0' ? vs15 : vs16;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -32,11 +30,23 @@ function encodeEmoji(emoji, text) {
|
||||
function decodeEmoji(text) {
|
||||
if (!text) return '';
|
||||
|
||||
const matches = [...text.matchAll(/[\uFE00-\uFE0F]/g)];
|
||||
// Extract variation selectors
|
||||
const matches = [...text.matchAll(/[\ufe0e\ufe0f]/g)];
|
||||
if (!matches.length) return '';
|
||||
|
||||
const bytes = new Uint8Array(matches.map(m => fromVariationSelector(m[0].codePointAt(0))));
|
||||
return new TextDecoder().decode(bytes);
|
||||
// Convert variation selectors to binary
|
||||
const binary = matches.map(m => m[0] === '\ufe0e' ? '0' : '1').join('');
|
||||
|
||||
// Convert binary to text
|
||||
let decoded = '';
|
||||
for (let i = 0; i < binary.length; i += 8) {
|
||||
const byte = binary.slice(i, i + 8);
|
||||
if (byte.length === 8) {
|
||||
decoded += String.fromCharCode(parseInt(byte, 2));
|
||||
}
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
// Invisible text encoding/decoding
|
||||
|
||||
+48
-2
@@ -15,11 +15,23 @@ const transforms = {
|
||||
'(': ')', ')': '(', '[': ']', ']': '[', '{': '}', '}': '{', '<': '>', '>': '<',
|
||||
'&': '⅋', '_': '‾'
|
||||
},
|
||||
// Create reverse map for decoding
|
||||
reverseMap: function() {
|
||||
const revMap = {};
|
||||
for (const [key, value] of Object.entries(this.map)) {
|
||||
revMap[value] = key;
|
||||
}
|
||||
return revMap;
|
||||
},
|
||||
func: function(text) {
|
||||
return [...text].map(c => this.map[c] || c).reverse().join('');
|
||||
},
|
||||
preview: function(text) {
|
||||
return this.func(text);
|
||||
},
|
||||
reverse: function(text) {
|
||||
const revMap = this.reverseMap();
|
||||
return [...text].map(c => revMap[c] || c).reverse().join('');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -130,11 +142,29 @@ const transforms = {
|
||||
'3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...',
|
||||
'8': '---..', '9': '----.'
|
||||
},
|
||||
func: function(text) {
|
||||
return [...text.toLowerCase()].map(c => this.map[c] || c).join(' ');
|
||||
// Create reverse map for decoding
|
||||
reverseMap: function() {
|
||||
const revMap = {};
|
||||
for (const [key, value] of Object.entries(this.map)) {
|
||||
revMap[value] = key;
|
||||
}
|
||||
return revMap;
|
||||
},
|
||||
func: function(text, decode = false) {
|
||||
if (decode) {
|
||||
// Decode mode
|
||||
const revMap = this.reverseMap();
|
||||
return text.split(/\s+/).map(c => revMap[c] || c).join('');
|
||||
} else {
|
||||
// Encode mode
|
||||
return [...text.toLowerCase()].map(c => this.map[c] || c).join(' ');
|
||||
}
|
||||
},
|
||||
preview: function(text) {
|
||||
return this.func(text);
|
||||
},
|
||||
reverse: function(text) {
|
||||
return this.func(text, true);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -145,8 +175,24 @@ const transforms = {
|
||||
},
|
||||
preview: function(text) {
|
||||
return this.func(text);
|
||||
},
|
||||
reverse: function(text) {
|
||||
// Remove spaces and ensure we have valid binary
|
||||
const binText = text.replace(/\s+/g, '');
|
||||
let result = '';
|
||||
|
||||
// Process 8 bits at a time
|
||||
for (let i = 0; i < binText.length; i += 8) {
|
||||
const byte = binText.substr(i, 8);
|
||||
if (byte.length === 8) {
|
||||
result += String.fromCharCode(parseInt(byte, 2));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Note: other transforms don't have reverse functions because they're not easily reversible
|
||||
// The universal decoder will only try to reverse transforms that have a reverse function
|
||||
};
|
||||
|
||||
// Export transforms for use in app.js
|
||||
|
||||
Reference in New Issue
Block a user