Hola amigos hoy no vengo con un crackme sino con un simple programa que se me vino ala mente, ya que los que hacemos ingeniería inversa usamos mucho los editores hexadecimales, así que se me ocurrió hacer uno simple en JavaScript y HTML solo que hay un inconveniente solo acepta ejecutables o archivos que pesen menos de 1 megabyte, ya que si le pongo un valor mayor este programa o mejor dicho el navegador se nos trabaría y si así con 700 kb se quiere trabar en fin aquí una foto del programa ya terminado, otra cosa use chatgpt para hacerlo es una herramienta muy cómoda de programar y sin quebrarte tanto la cabeza y no por eso nos va a sustituir, ya que tenemos que revisar bien el código, bueno aquí la foto
Y si se preguntan que podemos hacer, pues les cuento al cargar el ejecutable nos muestra sus valores en hexadecimal y podemos seleccionar los bytes para modificarlos y si quieren descargar la nueva versión solo dan en clic en el botón guardar, también pueden comparar los archivos si son iguales o diferentes en algunos bytes y si es diferente estos se marcaran a color, también puedes ir a alguna dirección dada y también te muestra el peso del archivo en bytes...bueno sin tanto rollo aquí les dejo el código por si lo quieren probar solo copean y pegan en el bloc de notas como editor.html
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Editor Hexadecimal</title>
<style>
*
{
box-sizing: border-box;
}
body
{
margin: 0;
background: #1e1e1e;
color: #ddd;
font-family:
Consolas,
"Courier New",
monospace;
}
#barra
{
background: #252526;
padding: 10px;
border-bottom:
1px solid #444;
display: flex;
gap: 6px;
align-items: center;
flex-wrap: wrap;
}
button
{
background: #333;
color: white;
border:
1px solid #555;
padding:
7px 10px;
cursor: pointer;
}
button:hover
{
background: #444;
}
input[type="text"]
{
background: #1e1e1e;
color: white;
border:
1px solid #555;
padding: 7px;
}
input[type="file"]
{
display: none;
}
#info
{
margin-left: auto;
color: #aaa;
}
#resultado
{
padding:
8px 12px;
background: #202020;
border-bottom:
1px solid #444;
color: #aaa;
}
#contador
{
color: #ffcc00;
}
#cabecera
{
display: grid;
grid-template-columns:
90px
1fr
1fr
170px;
padding:
8px 12px;
background: #333;
border-bottom:
1px solid #555;
}
#editor
{
height:
calc(100vh - 180px);
overflow: auto;
}
.fila
{
display: grid;
grid-template-columns:
90px
1fr
1fr
170px;
min-height: 27px;
padding:
2px 12px;
}
.fila:hover
{
background: #292929;
}
.offset
{
color: #569cd6;
padding-top: 4px;
}
.hex
{
display: flex;
gap: 4px;
}
.byte
{
width: 24px;
height: 23px;
background: transparent;
color: #dcdcaa;
border:
1px solid transparent;
text-align: center;
font-family:
Consolas,
monospace;
}
.byte:focus
{
outline: none;
border:
1px solid #569cd6;
background: #264f78;
}
.byte2
{
width: 24px;
height: 23px;
color: #9cdcfe;
text-align: center;
padding-top: 3px;
}
.ascii
{
white-space: pre;
color: #ce9178;
}
/*
Byte diferente
*/
.diferente
{
background:
#672727 !important;
color:
#ff9999 !important;
border-color:
#ff5555 !important;
}
/*
Diferencia seleccionada
*/
.actual
{
background:
#b06000 !important;
color:
white !important;
border-color:
#ffcc00 !important;
}
/*
Coincidencias de búsqueda
*/
.busqueda
{
background:
#665c00 !important;
color:
#ffff99 !important;
border-color:
#ffff00 !important;
}
/*
Coincidencia actual
*/
.busquedaActual
{
background:
#b06000 !important;
color:
white !important;
border-color:
#ffcc00 !important;
}
</style>
</head>
<body>
<!-- ===================================
BARRA DE HERRAMIENTAS
=================================== -->
<div id="barra">
<button onclick="abrir1()">
Abrir archivo 1
</button>
<button onclick="abrir2()">
Abrir archivo 2
</button>
<button onclick="comparar()">
Comparar
</button>
<button onclick="primeraDiferencia()">
|<
</button>
<button onclick="anteriorDiferencia()">
<
</button>
<button onclick="siguienteDiferencia()">
>
</button>
<button onclick="ultimaDiferencia()">
>|
</button>
<span id="contador">
Diferencias: 0
</span>
<input type="text" id="buscar" placeholder="Buscar HEX/texto">
<button onclick="buscar()">
Buscar
</button>
<button onclick="anteriorBusqueda()">
Buscar anterior
</button>
<button onclick="siguienteBusqueda()">
Buscar siguiente
</button>
<input type="text" id="offset" placeholder="Offset HEX" style="width: 100px;">
<button onclick="irAOffset()">
Ir
</button>
<button onclick="guardar()">
Guardar
</button>
<span id="info">
Sin archivos
</span>
</div>
<!-- ===================================
RESULTADO
=================================== -->
<div id="resultado">
Abre dos archivos y pulsa Comparar.
</div>
<!-- ===================================
INPUTS DE ARCHIVOS
=================================== -->
<input type="file" id="archivo1">
<input type="file" id="archivo2">
<!-- ===================================
CABECERA
=================================== -->
<div id="cabecera">
<div>
OFFSET
</div>
<div>
ARCHIVO 1
</div>
<div>
ARCHIVO 2
</div>
<div>
ASCII
</div>
</div>
<!-- ===================================
EDITOR
=================================== -->
<div id="editor"></div>
<script>
/*
====================================
VARIABLES
====================================
*/
let datos1 = new Uint8Array(0);
let datos2 = new Uint8Array(0);
let nombre1 = "archivo1.bin";
let nombre2 = "archivo2.bin";
const MAX_TAMANO = 1024 * 1024;
/*
Lista de diferencias
*/
let diferencias = [];
/*
Índice de diferencia actual
*/
let indiceDiferencia = -1;
/*
Lista de resultados de búsqueda
*/
let resultadosBusqueda = [];
/*
Índice de búsqueda actual
*/
let indiceBusqueda = -1;
/*
Elementos HTML
*/
const archivo1 = document.getElementById("archivo1");
const archivo2 = document.getElementById("archivo2");
const editor = document.getElementById("editor");
/*
====================================
ABRIR ARCHIVO 1
====================================
*/
function abrir1()
{
archivo1.click();
}
archivo1.addEventListener("change", async function()
{
const archivo = this.files[0];
if(!archivo)
{
return;
}
if(archivo.size > MAX_TAMANO)
{
alert("El archivo no puede superar 1 MB.");
this.value = "";
return;
}
nombre1 = archivo.name;
const buffer = await archivo.arrayBuffer();
datos1 = new Uint8Array(buffer);
/*
Limpiar comparación
*/
diferencias = [];
indiceDiferencia = -1;
mostrar();
actualizarInfo();
});
/*
====================================
ABRIR ARCHIVO 2
====================================
*/
function abrir2()
{
archivo2.click();
}
archivo2.addEventListener("change", async function()
{
const archivo = this.files[0];
if(!archivo)
{
return;
}
if(archivo.size > MAX_TAMANO)
{
alert("El archivo no puede superar 1 MB.");
this.value = "";
return;
}
nombre2 = archivo.name;
const buffer = await archivo.arrayBuffer();
datos2 = new Uint8Array(buffer);
diferencias = [];
indiceDiferencia = -1;
mostrar();
actualizarInfo();
});
/*
====================================
ACTUALIZAR INFORMACIÓN
====================================
*/
function actualizarInfo()
{
document.getElementById("info").textContent = "Archivo 1: " + datos1.length + " bytes | Archivo 2: " + datos2.length + " bytes";
}
/*
====================================
MOSTRAR ARCHIVOS
====================================
*/
function mostrar()
{
editor.innerHTML = "";
const max = Math.max(datos1.length, datos2.length);
const fragment = document.createDocumentFragment();
/*
Recorrer archivo
en grupos de 16 bytes
*/
for(let i = 0; i < max; i += 16)
{
const fila = document.createElement("div");
fila.className = "fila";
/*
----------------------------
OFFSET
----------------------------
*/
const offset = document.createElement("div");
offset.className = "offset";
offset.textContent = i.toString(16).padStart(8, "0").toUpperCase();
fila.appendChild(offset);
/*
----------------------------
HEX ARCHIVO 1
----------------------------
*/
const hex1 = document.createElement("div");
hex1.className = "hex";
/*
----------------------------
HEX ARCHIVO 2
----------------------------
*/
const hex2 = document.createElement("div");
hex2.className = "hex";
/*
----------------------------
ASCII
----------------------------
*/
const ascii = document.createElement("div");
ascii.className = "ascii";
let texto = "";
/*
Mostrar 16 bytes
*/
for(let j = 0; j < 16; j++)
{
const pos = i + j;
/*
------------------------
ARCHIVO 1
------------------------
*/
if(pos < datos1.length)
{
const input = document.createElement("input");
input.className = "byte";
input.maxLength = 2;
input.value = datos1[pos].toString(16).padStart(2, "0").toUpperCase();
input.dataset.pos = pos;
input.addEventListener("input", editarByte);
input.addEventListener("keydown", navegar);
hex1.appendChild(input);
}
else
{
const espacio = document.createElement("span");
espacio.style.width = "24px";
hex1.appendChild(espacio);
}
/*
------------------------
ARCHIVO 2
------------------------
*/
if(pos < datos2.length)
{
const span = document.createElement("span");
span.className = "byte2";
span.textContent = datos2[pos].toString(16).padStart(2, "0").toUpperCase();
span.dataset.pos = pos;
hex2.appendChild(span);
}
else
{
const espacio = document.createElement("span");
espacio.style.width = "24px";
hex2.appendChild(espacio);
}
/*
------------------------
ASCII
------------------------
*/
let b = null;
if(pos < datos1.length)
{
b = datos1[pos];
}
else if(pos < datos2.length)
{
b = datos2[pos];
}
if(b !== null)
{
if(b >= 32 && b <= 126)
{
texto += String.fromCharCode(b);
}
else
{
texto += ".";
}
}
else
{
texto += " ";
}
}
ascii.textContent = texto;
fila.appendChild(hex1);
fila.appendChild(hex2);
fila.appendChild(ascii);
fragment.appendChild(fila);
}
editor.appendChild(fragment);
/*
Marcar diferencias
*/
if(diferencias.length > 0)
{
marcarDiferencias();
}
/*
Marcar búsquedas
*/
if(resultadosBusqueda.length > 0)
{
marcarBusquedas();
}
}
/*
====================================
COMPARAR
====================================
*/
function comparar()
{
diferencias = [];
indiceDiferencia = -1;
const max = Math.max(datos1.length, datos2.length);
/*
Comparar cada byte
*/
for(let i = 0; i < max; i++)
{
const a = i < datos1.length ? datos1[i] : null;
const b = i < datos2.length ? datos2[i] : null;
if(a !== b)
{
diferencias.push(i);
}
}
document.getElementById("contador").textContent = "Diferencias: " + diferencias.length;
/*
No existen diferencias
*/
if(diferencias.length === 0)
{
document.getElementById("resultado").textContent = "Los archivos son idénticos.";
mostrar();
return;
}
/*
Existen diferencias
*/
document.getElementById("resultado").textContent = "Se encontraron " + diferencias.length + " diferencias.";
mostrar();
/*
Ir a la primera
*/
indiceDiferencia = 0;
irADiferencia();
}
/*
====================================
MARCAR DIFERENCIAS
====================================
*/
function marcarDiferencias()
{
for(let i = 0; i < diferencias.length; i++)
{
const pos = diferencias[i];
const e1 = document.querySelector('.byte[data-pos="' + pos + '"]');
const e2 = document.querySelector('.byte2[data-pos="' + pos + '"]');
if(e1)
{
e1.classList.add("diferente");
}
if(e2)
{
e2.classList.add("diferente");
}
}
}
/*
====================================
IR A DIFERENCIA
====================================
*/
function irADiferencia()
{
if(diferencias.length === 0)
{
return;
}
/*
Quitar selección anterior
*/
document.querySelectorAll(".actual").forEach(function(elemento)
{
elemento.classList.remove("actual");
});
const pos = diferencias[indiceDiferencia];
const e1 = document.querySelector('.byte[data-pos="' + pos + '"]');
const e2 = document.querySelector('.byte2[data-pos="' + pos + '"]');
if(e1)
{
e1.classList.add("actual");
e1.scrollIntoView(
{
behavior: "smooth",
block: "center"
});
}
if(e2)
{
e2.classList.add("actual");
}
const a = pos < datos1.length ? datos1[pos] : null;
const b = pos < datos2.length ? datos2[pos] : null;
const offset = "0x" + pos.toString(16).toUpperCase().padStart(8, "0");
const valorA = a === null ? "--" : a.toString(16).padStart(2, "0").toUpperCase();
const valorB = b === null ? "--" : b.toString(16).padStart(2, "0").toUpperCase();
document.getElementById("resultado").textContent = "Diferencia " + (indiceDiferencia + 1) + " de " + diferencias.length + " | Offset " + offset + " | " + valorA + " → " + valorB;
}
/*
====================================
PRIMERA DIFERENCIA
====================================
*/
function primeraDiferencia()
{
if(diferencias.length === 0)
{
return;
}
indiceDiferencia = 0;
irADiferencia();
}
/*
====================================
DIFERENCIA ANTERIOR
====================================
*/
function anteriorDiferencia()
{
if(diferencias.length === 0)
{
return;
}
indiceDiferencia--;
if(indiceDiferencia < 0)
{
indiceDiferencia = diferencias.length - 1;
}
irADiferencia();
}
/*
====================================
SIGUIENTE DIFERENCIA
====================================
*/
function siguienteDiferencia()
{
if(diferencias.length === 0)
{
return;
}
indiceDiferencia++;
if(indiceDiferencia >= diferencias.length)
{
indiceDiferencia = 0;
}
irADiferencia();
}
/*
====================================
ÚLTIMA DIFERENCIA
====================================
*/
function ultimaDiferencia()
{
if(diferencias.length === 0)
{
return;
}
indiceDiferencia = diferencias.length - 1;
irADiferencia();
}
/*
====================================
EDITAR BYTE
====================================
*/
function editarByte(e)
{
let valor = e.target.value.replace(/[^0-9a-fA-F]/g, "");
e.target.value = valor.toUpperCase();
if(valor.length === 2)
{
const pos = parseInt(e.target.dataset.pos);
const numero = parseInt(valor, 16);
if(!isNaN(numero))
{
datos1[pos] = numero;
}
}
}
/*
====================================
NAVEGAR ENTRE BYTES
====================================
*/
function navegar(e)
{
const pos = parseInt(e.target.dataset.pos);
let nueva = null;
if(e.key === "ArrowRight")
{
nueva = document.querySelector('.byte[data-pos="' + (pos + 1) + '"]');
}
if(e.key === "ArrowLeft")
{
nueva = document.querySelector('.byte[data-pos="' + (pos - 1) + '"]');
}
if(e.key === "ArrowDown")
{
nueva = document.querySelector('.byte[data-pos="' + (pos + 16) + '"]');
}
if(e.key === "ArrowUp")
{
nueva = document.querySelector('.byte[data-pos="' + (pos - 16) + '"]');
}
if(nueva)
{
e.preventDefault();
nueva.focus();
nueva.select();
}
}
/*
====================================
BUSCAR
====================================
*/
function buscar()
{
const texto = document.getElementById("buscar").value.trim();
if(!texto)
{
return;
}
const limpio = texto.replace(/\s+/g, "");
let patron = [];
/*
-------------------------------
BUSCAR HEX
-------------------------------
*/
if(/^[0-9a-fA-F]+$/.test(limpio) && limpio.length % 2 === 0)
{
for(let i = 0; i < limpio.length; i += 2)
{
patron.push(parseInt(limpio.substr(i, 2), 16));
}
}
/*
-------------------------------
BUSCAR TEXTO
-------------------------------
*/
else
{
for(let i = 0; i < texto.length; i++)
{
patron.push(texto.charCodeAt(i));
}
}
/*
Limpiar resultados
*/
resultadosBusqueda = [];
indiceBusqueda = -1;
/*
Buscar TODAS las coincidencias
*/
for(let i = 0; i <= datos1.length - patron.length; i++)
{
let encontrado = true;
for(let j = 0; j < patron.length; j++)
{
if(datos1[i + j] !== patron[j])
{
encontrado = false;
break;
}
}
if(encontrado)
{
resultadosBusqueda.push(i);
}
}
/*
No encontrado
*/
if(resultadosBusqueda.length === 0)
{
document.getElementById("resultado").textContent = "No encontrado.";
mostrar();
return;
}
/*
Primera coincidencia
*/
indiceBusqueda = 0;
mostrar();
irABusqueda();
}
/*
====================================
MARCAR RESULTADOS DE BÚSQUEDA
====================================
*/
function marcarBusquedas()
{
/*
Primero marcar todas
*/
for(let i = 0; i < resultadosBusqueda.length; i++)
{
const pos = resultadosBusqueda[i];
const elemento = document.querySelector('.byte[data-pos="' + pos + '"]');
if(elemento)
{
elemento.classList.add("busqueda");
}
}
/*
Marcar la actual
*/
if(indiceBusqueda >= 0)
{
const pos = resultadosBusqueda[indiceBusqueda];
const elemento = document.querySelector('.byte[data-pos="' + pos + '"]');
if(elemento)
{
elemento.classList.remove("busqueda");
elemento.classList.add("busquedaActual");
}
}
}
/*
====================================
IR A BÚSQUEDA
====================================
*/
function irABusqueda()
{
if(resultadosBusqueda.length === 0)
{
return;
}
/*
Quitar selección actual
*/
document.querySelectorAll(".busquedaActual").forEach(function(elemento)
{
elemento.classList.remove("busquedaActual");
elemento.classList.add("busqueda");
});
const pos = resultadosBusqueda[indiceBusqueda];
const elemento = document.querySelector('.byte[data-pos="' + pos + '"]');
if(elemento)
{
elemento.classList.remove("busqueda");
elemento.classList.add("busquedaActual");
elemento.scrollIntoView(
{
behavior: "smooth",
block: "center"
});
elemento.focus();
elemento.select();
}
const offset = "0x" + pos.toString(16).toUpperCase().padStart(8, "0");
document.getElementById("resultado").textContent = "Coincidencia " + (indiceBusqueda + 1) + " de " + resultadosBusqueda.length + " | Offset " + offset;
}
/*
====================================
SIGUIENTE BÚSQUEDA
====================================
*/
function siguienteBusqueda()
{
if(resultadosBusqueda.length === 0)
{
return;
}
indiceBusqueda++;
if(indiceBusqueda >= resultadosBusqueda.length)
{
indiceBusqueda = 0;
}
irABusqueda();
}
/*
====================================
BÚSQUEDA ANTERIOR
====================================
*/
function anteriorBusqueda()
{
if(resultadosBusqueda.length === 0)
{
return;
}
indiceBusqueda--;
if(indiceBusqueda < 0)
{
indiceBusqueda = resultadosBusqueda.length - 1;
}
irABusqueda();
}
/*
====================================
IR A OFFSET
====================================
*/
function irAOffset()
{
const valor = document.getElementById("offset").value.trim();
const pos = parseInt(valor, 16);
if(isNaN(pos) || pos < 0 || pos >= datos1.length)
{
alert("Offset inválido.");
return;
}
irAPosicion(pos);
}
/*
====================================
IR A POSICIÓN
====================================
*/
function irAPosicion(pos)
{
const elemento = document.querySelector('.byte[data-pos="' + pos + '"]');
if(!elemento)
{
return;
}
elemento.scrollIntoView(
{
behavior: "smooth",
block: "center"
});
elemento.focus();
elemento.select();
}
/*
====================================
GUARDAR ARCHIVO 1
====================================
*/
function guardar()
{
if(datos1.length === 0)
{
alert("No hay archivo abierto.");
return;
}
const blob = new Blob(
[datos1],
{
type: "application/octet-stream"
});
const enlace = document.createElement("a");
enlace.href = URL.createObjectURL(blob);
enlace.download = nombre1;
enlace.click();
URL.revokeObjectURL(enlace.href);
}
/*
====================================
ATAJOS DE TECLADO
====================================
*/
document.addEventListener("keydown", function(e)
{
/*
Ctrl + S
*/
if(e.ctrlKey && e.key.toLowerCase() === "s")
{
e.preventDefault();
guardar();
}
/*
Ctrl + F
*/
if(e.ctrlKey && e.key.toLowerCase() === "f")
{
e.preventDefault();
document.getElementById("buscar").focus();
}
/*
F3
Siguiente búsqueda
*/
if(e.key === "F3" && !e.shiftKey)
{
e.preventDefault();
if(resultadosBusqueda.length > 0)
{
siguienteBusqueda();
}
else
{
siguienteDiferencia();
}
}
/*
Shift + F3
Anterior búsqueda
*/
if(e.key === "F3" && e.shiftKey)
{
e.preventDefault();
if(resultadosBusqueda.length > 0)
{
anteriorBusqueda();
}
else
{
anteriorDiferencia();
}
}
});
</script>
</body>
</html>
Bueno creo que eso es todo aquí les dejo una foto donde compare un ejecutable el original y el modificado
Espero les guste saludos Flamer y si le falta algo me dicen ya que es algo muy simple

























