Sin Imaginación

De todo un poco

¿Esta vez sí, o todavía me harás seguir esperando?

September 14th, 2012

Todavía recuerdo la última vez que quise escribir. Ha pasado mucho tiempo desde la primera vez que subí un cms a un servidor ftp público en sintonía de emprender mi propio proyecto personal, de obtener ese espacio limitado en donde yo y mis pensamientos comparten puestos … de abrir mi propio blog.

Como siempre sentado frente a la pantalla del monitor con la luz de éste reflejándose sobre mi cara, después de tantos años, vuelvo a intentar competir en la carrera. No sé si será otras de esas veces en donde se me revuelcan las venas de escritor y a los días termino por dejarlo a un lado o si por fin podré renunciar a mi autocomplacencia y abordar el reto. No lo sé, y, diferente a otras veces no prentendo hacer promesas que no cumpliré, tampoco intentaré hacer de este espacio un lugar ambicioso, sólamente quiero escribir, de lo que sea, no importa el tema.

Voy a intentar hacer de esto un diario personal más, en donde me relataré mis problemas a mí mismo y dejaré de engañarme pensando que tengo la respuesta a mis problemas (aunq a veces si la tengo), ojalá y esto me ayude a encontrarla. Para una persona con mi personalidad ( difícil definiéndose ) resulta extremandamente complicado el hablar de si mismo, debo admitir que me resulta un poco intimidante que estos escritos se hagan públicos, pero independientemente de eso, trataré de divertirme escribiendo : )

 

Hasta aquí por ahora, me ha tomado un buen rato el hacer estos tres párrafos, sigo sin serme honesto y con dificultad prar expresarme abiertamente. Lo apuntaré en las cosas a mejorar.

 

 

Introducción al Cracking

April 3rd, 2012

Este artículo fue escrito para una colaboración con un amigo en un esfuerzo de tener una distribución local parecida a las famosas revistas HackXCrack.

Huelga decir que ese proyecto no avanzó (no recuerdo las razones) pero ya tenía escrito parte del artículo sobre el tema que quería abordar. A continuación la versión inédita.

Introducción al Cracking

INDICE:
0x00 Introducción
0x01 Conceptos básicos de Assembler
0x02 Ollydbg
0x03 Ejemplos
0x04 Final

0x01 Introducción

Buenas a todos, en este mini paper se explicará una breve introducción al mundo del cracking y la ingeniería inversa de modo que el lector que comienza su travesía por estas calles pueda orientarse de manera  práctica y sencilla. Tratare de escribir el contenido lo mas llano y dinámico posible para que sea fácil de entender. Hay que dejar claro que el paper esta enfocado en Windows y las nociones que se explicaran de assembler serán sobre el ensamblador  FASM de 32 bits y que trabaja con sintaxis Intel. Si aun no entienden bien esto no se preocupen, mas adelante tratare el tema pero pienso que es oportuno aclarar esto.

Pues nada, comencemos refrescando los conceptos básicos:

Los programas informáticos están escritos en lenguajes de programación  (C/C++, Visual Basic, Perl, Python, Delphy, etc.) y almacenados en lo que se conoce como código fuente, este es compilado o interpretado (depende del lenguaje) para procrear el ejecutable.

Como estoy seguro que ya todos sabrán, nuestro ordenador solo entiende secuencias de ceros y unos, por lo tanto, el código de cualquier lenguaje de programación le es indiferente, o sea no lo puede entender así tal cual. Aquí es donde entra el  lenguaje máquina que consta de secuencias de estos 0 y 1 que el microprocesador entiende directamente.

El procesador trabaja con código binario (ceros y unos) ya que se opera con transistores que sólo pueden estar de dos formas: abierto o cerrado, 1 o 0 Un bit es una unidad de información que sólo puede representar dos valores 1 ó 0. Dado que es muy difícil e incómodo representar cualquier cosa en binario, el sistema más usado para la representación de datos y valores es el Sistema Hexadecimal.

Un byte (8bits) es la unidad básica en la que se mide la información. Cada una de las celdillas lógicas en que se divide la memoria del ordenador, tanto RAM como ROM, tienen capacidad para un byte. Aparte del bit y byte se suelen utilizar a menudo word y dword. En resumen:

1 bit  =  0 ó 1;  1 byte   =   8 bits;   1 word  =  2 bytes;   1 dword  =  4 bytes.

Ahora, aclaremos conceptos que son muy utilizados en el ámbito del cracking:

  • Ingeniería Inversa: es el arte de examinar algún programa (del cual no se posee su código fuente) con el único objetivo de conocer su estructura y funcionamiento hasta el punto de poder imitarlo a la perfección. El termino no solo se aplica al área de software, también se puede emplear  a cualquier otra cosa si se posee el mismo fin.
  • Cracking: consiste en la modificación de algún programa  con el fin de cambiar su comportamiento y obtener un beneficio ilícito. En la mayoría de los casos esto varía desde conseguir el número serial de un software hasta saltarse un tipo de protección que implemente un programa.
  • Depurador o Debugger: es el programa que se utiliza para probar de manera detallada (paso x paso) el funcionamiento de un programa. Más simple, nos permite saber que esta sucediendo dentro de otro programa mientras se esta ejecutando. Usualmente es utilizado por los programadores para facilitar la corrección de errores en la creación de algún software y en el cracking es la herramienta esencial para alcanzar nuestro objetivo. Entre los depuradores más comunes esta: el GDB, Ollydbg, Cheat Engine, Ida Pro y el SoftICE.
  • Desensambladores: es el programa encargado de traducir las instrucciones de un ejecutable de código maquina (binario [ceros y unos]) a ensamblador (ASM). En ocasiones el código obtenido puede no estar de la manera esperada ya que puede estar empaquetado o comprimido. Ejemplo de desensambladores: Ollydbg, Cheat Engine, Ida.
  • Empacadores o Packers: son programas que protegen, ofuscan, comprimen o reducen una aplicación.  Ejemplos: UPX, Armadillo, Themida.
  • Editor Hexadecimal: es un programa que nos permite ver y modificar un ejecutable en el sistema hexadecimal. Es muy utilizado para tareas sencillas como modificar un número específico de bytes. Modificando los bytes también se modifican las instrucciones que estén asociadas a ellos, influyendo en su comportamiento. Ejemplo: 010 Editor, Hex Editor.
  • Compilador: programa encargado de traducir el código fuente de un lenguaje de programación al código maquina.
  • Dumper: es un programa que puede volcar o extraer datos de la memoria de un proceso. Tomar rangos o posiciones aleatorias y vertirlos en otro lado para ver y analizar su contenido.
  • Dirección de memoria: es un identificador para una localización de memoria. Las direcciones son asignadas por el sistema operativo a cada programa en ejecución. El rango de valores naturales que pueden ser almacenados en un sistema de 32 bits es de 0 hasta 4.294.967.295 direcciones.
  • Dirección HardCodeada: es usa dirección encontrada a mano, debido a que pude variar dependiendo del sistema operativo o la versión de algún software.
  • Offset: es una dirección dentro de un binario, que indica un número de bytes.
  • Interfaz de programación de aplicaciones o API: es el conjunto de funciones y procedimientos  que ofrece una librería para ser utilizado por otro software.

Teniendo esos conceptos claros solo nos falta una breve introducción de la memoria y los procesos. Empecemos por lo más básico:

Un programa, aplicación, fichero, o ejecutable son los términos empleados para referirse a  un archivo con un conjunto de instrucciones compactadas en binario, esto ya lo dejamos claro arriba. En cambio un proceso es un programa en ejecución con su espacio de memoria en donde posteriormente se cargaran las instrucciones contenidas en el archivo. Para cada proceso se carga un espacio de memoria diferente.

Ahora ¿qué sucede? Que cuando se coloca un programa en memoria para ejecutarlo, no se coloca de la misma manera en la cual esta en el archivo. Cuando esta cargado en la memoria el contenido del archivo se separa y se alinea en secciones. Esto no sucede en el archivo puesto que todo está más pegado. Uno encima de otro.

Por lo tanto una dirección de memoria y una dirección del archivo son totalmente diferentes. Cuando se habla de memoria física o RAW se esta refiriendo al archivo aun no cargado en memoria, en cambio cuando se habla de memoria virtual es el programa ya cargado en memoria para ejecutarlo.

  • RVA = VA – ImageBase;
  • VA    =RVA + ImageBase;
  • RAW = RVA – (VirtualAddress PointerToRawData)
  • VirtualAddress          =  dirección en donde comienza la sección en la memoria.
  • PointerToRawData   =  dirección en donde comienza la sección en el archivo.

Después de esta larga y tediosa información que es vital para entender lo que viene, pasemos a explicar los principios básicos de ensamblador. Creo que con lo que acabo de explicar ya es suficiente para crear una base sobre el tema.

0x01 Conceptos básicos de Assembler

El lenguaje ensamblador, assembler  (o assembly) en ingles o simplemente ASM en siglas, es un lenguaje de bajo nivel que tiene la capacidad de interactuar de manera directa con la arquitectura de el procesador. Al momento de programar en ensamblador se debe tener en cuenta la arquitectura bajo la cual se este trabajando debido a que si el programa se crea para una determinada plataforma (x86)  no servirá en otra (x64).

¿Por qué es importante ensamblador? Pues por su increíble potencia, rapidez y versatilidad al momento de realizar tareas que requieran una interacción mas cercana con el procesador. Además como vimos mas arriba es imprescindible en el cracking y la ingeniería inversa.

Pues bien, en ensamblador existen lo que se llaman los registros. Los registros son pequeñas zonas en donde se almacenan datos de manera temporal. Son prácticamente las variables del procesador.

Existen diferentes tipos de registros que tienen diferentes propósitos, están:

Registros de propósito general:
Registro Puntero de Instrucciones (EIP)
Registro de Estado o de Señalizadores (EFLAGS)
Registros de Segmento

Registros de propósito general: Son 8 registros capaces de trabajar con información de 32 bits en su mayor tamaño. Pueden usarse tanto para almacenar datos como direcciones. Su nombre empieza por “E” que significa extendido. Son los siguientes:

  • EAX: Acumulador.
  • EBX: Base.
  • ECX: Contador.
  • EDX: Datos.
  • ESP: Puntero de pila.
  • EBP: Puntero de base.
  • ESI: Índice fuente.
  • EDI: Índice destino.

Nota: en la programación de 64 bits se agregan otra forma para representar los registros: rax, rbx, rcx, rdx, rdi, rsi, rip, rbp, rsp.

Estos registros, son capaces de trabajar con información de 32 bits, pueden manejar datos de 16 bits y cuatro de ellos pueden manejar información de 8 bits. Cuando se accede únicamente a los 16 bits de menos peso, se designan por AX, BX, CX, DX, SP, BP, SI, DI, respectivamente. A los registros AX, BX, CX y DX se puede acceder a sus registros AL, BL, CL y DL cuando se accede al byte de menos peso y AH, BH, CH y DH cuando se accede al byte de más peso.

Ejemplo:

  • RAX: registro de 64 bits =  8 bytes. Ej. 0000000011223344
  • EAX: registro de 32 bits =  4 bytes => Ej. 11223344
  • AX:    registro de 16 bits =  2 bytes de menor peso de EAX => Ej. 3344
  • AH:    registro de 8 bits  =  1 byte de mayor peso de AX => Ej. 33
  • AL:    registro de 8 bits   =  1 byte de menor peso de AX => Ej. 44
  • EAX: (EAX, AX, AH, AL).
  • EBX: (EBX, BX, BH, BL).
  • ECX: (ECX, CX, CH, CL).
  • EDX: (EDX, DX, DH, DL).
  • ESP (ESP, SP) y EBP (EBP, BP)

Estos registros son todos de propósito general porque son usados para desarrollar las tareas más comunes como almacenar datos o realizar las operaciones aritméticas. El de más importancia es el EAX porque la mayoría de las API tienen su valor de retorno en este registro.

Para entender los últimos dos registros debemos conocer que es la pila. La pila es una estructura de tipo LIFO (ultimo en entrar, primero en salir) en donde se almacenan todo tipo de datos de manera temporal para luego utilizarse en alguna operación. Nos podemos imaginar la pila como un montón de libros uno encima del otro. En donde solo puedo tomar el que esta en la cima para leerlo, los que están mas abajo no puedo tomarlos puesto que debo quitar el que esta mas próximo primero.

A esto hace referencia estos dos registros, al dato que esta en la cima (ESP)  y el que esta mas abajo (EBP).

Registro Puntero de Instrucciones (EIP): (EIP IP) Es el registro que apunta a la siguiente instrucción a se ejecutada.

Registro de Estado o de Señalizadores (EFLAGS): Consta de 32 bits, de los cuales la mayoría son señalizadores de estado. Esto se vera bien mas adelante cuando llegemos a la parte del Ollydbg.

Registros de Segmento: son registros que apuntan a una determinada zona de memoria ya sea la pila, el código o los datos. Para controlar los segmentos, se dispone de varios registros de 16 bits. Estos son:

  • -CS: Contiene la dirección al segmento de código, es decir, a las instrucciones.
  • -DS: Contiene la dirección al segmento de datos del programa.
  • -SS: Contiene la dirección del segmento de la pila.
  • -FS y GS: son registros de propósito auxiliar.
  • -ES: es un segmento extra.

En ensamblador existen las instrucciones con las cuales el lenguaje opera y funciona. La mayoría tiene la siguiente estructura.
Instruccion destino, fuente.

Las más comunes son:

MOV, mueve datos de un sitio a otro.

Ejs:

mov eax,0x7.                Se mueve el valor 7 al registro eax.
mov ebx, [eax].             Se mueve el contenido del valor del registro eax a ebx.
mov [0x1007000],eax   Se mueve el valor de eax a la direccion de memoria 0x1007000.

Nota: no se puede mover un dato entre dos direcciones de manera directa, para eso se debe pasar primero al algún registro.

ADD, suma un número a un registro.

Ej: add eax, 3.

SUB, resta un número a un registro.

Ej: sub eax, 3.

MUL, multiplica con eax el multiplicando.

Ej: mov eax, 0x3

mul eax         ;eax valdrá 0x9

DIV, divide con edx.eax el divisor.

Ej:  mov edx, 0x9

mov eax, 0x9

div   eax        ;eax valdrá 0x1

INC, incrementa el operando en 1.

Ej: inc eax

DEC, decrementa el operando en 1.

Ej: dec eax

PUSH, mete un valor a la pila.

Ej: push, eax     ;pone el valor de eax en la pila

PUSHPAD, mete todos los registros a la pila.

Ej: pushpad

POP, saca un calor de la pila.

Ej. pop eax     ;toma el valor apuntado por esp y lo pone en eax

POPAD, saca los últimos valores de la pila y los pone en los registros.

Ej. popad         ;equivale a pop edi,esi,ebp,esp,ebx,edx,ecx,eax

JMP, salta hacia la direccion que se indique.

Ej.  mov eax, [0x01005FD2]

jmp eax        ; se salta hacia 01005FD2

jmp [eax]      ; se salta hacia el contenido de 01005FD2

A este salto se le conoce como salto incondicional porque procede sin importar nada. En cambio existen algunos  saltos que conllevan una condición para poder proceder.

  • JE    – Salta si los números comparados son iguales.
  • JNE – Salta si los valores no son iguales.
  • JG    – Salta si Valor1 es mayor que Valor2.
  • JGE – Salta si Valor1 es mayor o igual que Valor2.
  • JB    – Salta si Valor1 es menor que Valor2.
  • JBE – Salta si Valor1 es menor o igual que Valor2.

CMP, compara dos valores y es el complemento para los saltos condicionales y otras instrucciones.

Ej: mov eax, 6

cmp  eax,4

je  01005FD2   ; Aquí si eax es igual a 4 saltaría a la direccion de memoria

dec eax             ; pero como no es el caso se ignora el salto y sigue la otra instrucción

CALL, llama a una función, prácticamente guarda en la pila la próxima direccion a ejecutarse después del CALL para tener un punto de retorno y luego salta hacia la direccion de la función, se ejecuta y cuando encuentra un ret, salta hacia la direccion que se había guardado en la pila (que es la direccion próxima desde donde se llamo al CALL).

Cuando se hace uso de la instrucción CALL para llamar a una función primero se colocan dentro de la pila los parámetros de la función.

Ej: push 0

call    ExitProcess    ; con esto se llama a la API ExitProcess y se termina la ejecución.

Estas son las nociones mas básicas del lenguaje con esto ya están listos para adentrarse en temas más profundos y empezar con el cracking. : )

0x02 Ollydbg

Ollydbg es un debugger de 32 bits bits para Windows. Es nuestra herramienta crucial para la ingeniería inversa y el cracking porque es  práctico, fácil y versátil además de ser gratis.

……

Hasta ahí escribí.

 

Hasta pronto.

Trainer BuscaMinas (hook + cheat)

December 14th, 2011

Este artículo pertenece a una serie de dudas antiguas que fueron publicadas en foros de internet antes de la creación del blog, lo plasmo aquí para no perderlas y que formen parte de la antología.

Post:

Saludos,

Aqui les dejo un programa que modifica la memoria del buscaminas para sobreescribir las direcciones donde hayan bombas en mapa.

[code language=”cpp”]
#include <iostream>
#include <windows.h>
#include <Tlhelp32.h>

using namespace std;

DWORD Buscar_Proceso();

/*
Name: trainer buscaminas
Author: @aps
Date: 14/12/11 17:51
*/

HANDLE CProc;
HANDLE hProc;
PROCESSENTRY32 Proceso;
DWORD pid;

int main()
{

BYTE *celda;
DWORD mapa = 0x01005360;
DWORD aux;

if(Buscar_Proceso() != 0)
{
cout << "Se encontro el proceso. " << endl;
cout << "El pid es : " << hex << pid << endl;
}else cout << "No se encontro el proceso." ;

if( (hProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid) ) == NULL)
{
cout << "No se pudo abrir el proceso. " << endl;
}else cout << "Se abrio el proceso." << endl;

if( (VirtualProtectEx(hProc ,(void *)mapa, 0x2FF, PAGE_EXECUTE_READWRITE, &aux)) == 0)
{
cout << "Error al cambiar los permisos de la zona " << mapa << endl;
}else cout << "Se modificaron los permisos en " << mapa << endl;

for(int x(0); (mapa+x) <= (mapa + 0x2ff ); x++ )
{

if ( ReadProcessMemory( hProc, (LPVOID)(mapa+x), celda, 1, NULL) == 0)
{
cout << "Error al leer en " << (mapa+x) << endl;
}else cout << "Se leyo en " << (mapa+x) << " el valor " << celda << endl;

if( *celda == 0x8f )
{
*celda = 0x48;

if( WriteProcessMemory(hProc, (void *)(mapa+x), celda,
1, NULL) == 0 )
{
cout << "Error al escribir en " << (mapa+x) << endl;
}else{ cout << "Se modifico " << (mapa+x) << endl;}

}
}

setbuf(stdin, NULL);
cin.get();
return 0;
}

DWORD Buscar_Proceso()
{

//Con esto creamos una captura de la lista de procesos y la guardamos en CProc
CProc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

Proceso.dwSize = sizeof(PROCESSENTRY32);

Process32First(CProc,&Proceso); //Leemos el primer proceso

//Mientras haya procesos para leer leemos el siguiente
while(Process32Next(CProc,&Proceso))
{

if(!strcmp(Proceso.szExeFile, "winmine.exe") )
{
return pid = Proceso.th32ProcessID;

}
}
return pid = 0;
}
[/code]

Y aqui una dll que hookea la api CreatePen, intente hacer una combinacion de dos metodos para hacer api-hooking de practica. Esto me llevo toda la tarde hacerlo asi que apreciaria si alguien puede hacerle algun comentario, verle un fallo, algo a mejorar? : )

[code language=”cpp”]
/* Replace "dll.h" with the name of your header */

#include <windows.h>
#include <Tlhelp32.h>
#include <stdio.h>

/*
Name: trainer buscaminas
Author: @aps
Date: 14/12/11 17:51
*/

void HookImport();
HPEN __stdcall CreatePenF( int , int , COLORREF );

BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
HookImport();
break;

case DLL_PROCESS_DETACH:
break;

case DLL_THREAD_ATTACH:
break;

case DLL_THREAD_DETACH:
break;
}

/* Returns TRUE on success, FALSE on failure */
return TRUE;
}

void HookImport()
{
HMODULE Prog = GetModuleHandle(0);
HMODULE Gdi32 = GetModuleHandle("Gdi32.dll");
DWORD CreatePen = (DWORD)GetProcAddress(Gdi32, "CreatePen");
int x;

PIMAGE_DOS_HEADER Img = (PIMAGE_DOS_HEADER)Prog;

//e lfanew apunta a donde empieza el encabezado nt
PIMAGE_NT_HEADERS Pe = (PIMAGE_NT_HEADERS) ((BYTE*)Img + Img->e_lfanew);

// obtengo la direccion del import en la seccion .text
LPDWORD ImportAddr = (LPDWORD)(
Pe->OptionalHeader.BaseOfCode + (DWORD)Img);

DWORD old;

//le cambio los privilegios
VirtualProtect(ImportAddr,
Pe->OptionalHeader.SizeOfCode, PAGE_READWRITE, &old);

for ( x= 0; x < Pe->OptionalHeader.SizeOfCode; x += 4, ImportAddr++)
{
//si la funcion es CreatePen
if (*ImportAddr == CreatePen)
{
//cambio los primeros cuatro bytes que apuntan a la direccion de memoria de CreatePen
//por los de mi funcion
*ImportAddr = (DWORD)&CreatePenF;
break;
}

}

}

HPEN __stdcall CreatePenF( int fnPenStyle, int nWidth, COLORREF crColor )
{
fnPenStyle = PS_DASHDOT;
nWidth = 20;
crColor = RGB(255, 0, 0);

BYTE *Buffer = (BYTE *)malloc(5);
BYTE *DirApi = (BYTE *)GetProcAddress(GetModuleHandle("Gdi32.dll"),"CreatePen");

*Buffer=0xE9;
Buffer++;

//api menos el principio del buffer
*((signed int *) Buffer) = DirApi – Buffer – 4;

return ( (HPEN(__stdcall *) (int,int, COLORREF) ) Buffer-1)(fnPenStyle, nWidth, crColor);

}
[/code]

Para inyectar la dll usen http://www.portalhacker.net/index.php/topic,146134.0.html
Luego cuando abran el buscaminas vayan a game, activen y desactiven la casilla color y ya esta.

Espero q alguien le sirva!

PD. Estoy en windows sp3, ingles y me funciona a la perfeccion.

Saludos. 😛

Respuesta:

Haha tienes razon no lo comente. 😛

Fijate en el buscaminas se reserva memoria para el mapa y cada una de las celdas. Cuando no hay nada en la celda es porque esta este byte (0x0F). Cuando hay un 1 o un 2, 3, etc, estan estos bytes (0x41 o 0x42, 0x43, etc.). Cuando hay una mina en la celda esta este byte (0x8f).

El mapa comienza en esta direccion 0x01005360 y termina en 0x01005360+0x2ff. Por lo tanto lo que hago es recorrer el mapa en busqueda de este byte 0x8f y lo cambio por este 0x48 (8).

En la dll lo que hago es hookar la api CreatePen, usando el import addres table hooking. En el buscaminas las importaciones estan dentro de la seccion .text al principio.

Asi que busco donde esta la seccion .text y le sumo el ImageBase. Luego voy avanzado cada 4 bytes hasta que encuentro la direccion d Create Pen, y la sustituyo por la direccion de mi funcion.

Luego en la funcion cambio los parametros y creo un buffer que haga un salto hacia la funcion original pasandole los parametros modificados. : D

Queda asi cuando ejecutas la dll y el cheat.

Es la primera vez que hago este tipo de cosas asi que han de haber muchos errores y formas de hacerlo mejor. xP

un saludos. : )

Saludos,
Ángel

Inyector dll – WinApi

November 22nd, 2011

Este artículo pertenece a una serie de dudas antiguas que fueron publicadas en foros de internet antes de la creación del blog, lo plasmo aquí para no perderlas y que formen parte de la antología.

Post:

Pues como tenia muchisimo sin programar nada y ultimamente he estado leyendo sobre inyecciones dll y manejo de memoria, salio esto de practica:

Es un inyector de dlls, el proceso es sencillo: escribes el proceso , buscas la ruta de la dll, verificas el proceso y lo inyectas.

[code language=”cpp”]
#include <windows.h>
#include <stdio.h>
#include <Tlhelp32.h>

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

void Buscar_Dll (HWND);
void CrearVentana (HWND);
int Inyectar ();
int Buscar_Proceso();
int Existe_A (char *);

/* Make the class name into a global variable */
char szClassName [ ] = "WindowsApp";
char ruta_dll [256];
char n_Proceso [100];
char mensaje [256];

HANDLE CProc; //Para crear la captura de la lista de procesos
HANDLE hProceso; //Para guardar el manejador del proceso
PROCESSENTRY32 Proceso; //Necesario para realizar la captura de procesos

HWND Button1, Button2, Button3, Edit1, Edit2, ComboBox, Static1, Static2;
HINSTANCE instancia;

HBRUSH hbrBackground = CreateSolidBrush(RGB(258, 205, 255));

HANDLE hProc;
DWORD pid;
LPVOID dDll;
LPVOID dLoadLibrary;

int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)

{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
instancia = hThisInstance;

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */

/* Use Windows’s default color as the background of the window */
wincl.hbrBackground = (HBRUSH) CreateSolidBrush(RGB(258, 205, 255));

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;

/* The class is registered, let’s create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);

/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);

/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);

}

/* The program return-value is 0 – The value that PostQuitMessage() gave */
return messages.wParam;
}

/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{

case WM_CREATE:
CrearVentana(hwnd);
break;

case WM_COMMAND:

//buscar dll
if( (HWND)lParam == Button1)
{
Buscar_Dll(hwnd);
}

//edit d la ruta
if( (HWND)lParam == Edit1 )
{
GetWindowText(Edit1, ruta_dll, 255);
}

//edit del proceso
if( (HWND)lParam == Edit2)
{
GetWindowText(Edit2, n_Proceso, 255);
}

//buscar proceso
if( (HWND)lParam == Button2 )
{
( Buscar_Proceso() == 0 ) ?

MessageBox(0, "El proceso esta corriendo", "Proceso", 0) :
MessageBox(0, "El proceso no esta corriendo", "Proceso", 0) ;
}

//inyectar
if( (HWND)lParam == Button3 )
{

switch( Inyectar() )
{
case 0:
case -1:
case -2:
case -3:
case -4:
case -5:
SendMessage(ComboBox, WM_SETTEXT, 0, (LPARAM)mensaje);
break;

}

}

break;

//mensaje para cambiarle el fondo al static
case WM_CTLCOLORSTATIC:
{
SetBkMode((HDC)wParam, TRANSPARENT);
//// SetTextColor((HDC)wParam, RGB(0,0,0) ) ;
return (LONG)hbrBackground;
}

case WM_DESTROY:

CloseHandle(hProc);
PostQuitMessage (0); /* send a WM_QUIT to the message queue */

break;

default: /* for messages that we don’t deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}

void CrearVentana(HWND hwnd)
{

//Static // ruta
Static1 = CreateWindowEx(0,"STATIC", "Ruta:", WS_CHILD|WS_VISIBLE|WS_TABSTOP,
10, 10, 45, 20, hwnd, 0, instancia, NULL);

//Static2 // proceso
Static2 = CreateWindowEx(0,"STATIC", "Proceso:", WS_CHILD|WS_VISIBLE|WS_TABSTOP,
10, 50, 65, 20, hwnd, 0, instancia, NULL);

//Edit // ruta
Edit1 = CreateWindowEx(0,"EDIT", "", WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER|ES_AUTOHSCROLL,
70, 10, 400, 20, hwnd, 0, instancia, NULL);

//Edit2 // proceso
Edit2 = CreateWindowEx(0,"EDIT", "", WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER|ES_AUTOHSCROLL,
85, 50, 100, 20, hwnd, 0, instancia, NULL);
//ComboBox
ComboBox = CreateWindowEx(0,"EDIT", "",
WS_CHILD|WS_VISIBLE | WS_VSCROLL | ES_MULTILINE |WS_BORDER,
85, 130, 350, 100, hwnd, 0, instancia, NULL);

//Boton
Button1 = CreateWindowEx(0,"BUTTON", "Buscar", WS_CHILD|WS_VISIBLE|WS_TABSTOP,
80, 300, 100, 20, hwnd, 0, instancia, NULL);
//Boton 2
Button2 = CreateWindowEx(0,"BUTTON", "Verificar Proceso", WS_CHILD|WS_VISIBLE|WS_TABSTOP,
200, 300, 120, 20, hwnd, 0, instancia, NULL);

//Boton 3
Button3 = CreateWindowEx(0,"BUTTON", "Inyectar", WS_CHILD|WS_VISIBLE|WS_TABSTOP,
330, 300, 100, 20, hwnd, 0, instancia, NULL);

}

void Buscar_Dll(HWND hwnd)
{
OPENFILENAME ofn;

ZeroMemory(&ofn, sizeof(ofn));

ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = ruta_dll;
*ofn.lpstrFile = 0;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = "Archivos Dll\0*.dll\0Archivos de texto\0*.TXT\0Todos los archios\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrInitialDir = "%homepath%";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

GetOpenFileName(&ofn) ?
SendMessage(Edit1, WM_SETTEXT, false, (long int) ofn.lpstrFile):
SendMessage(Edit1, WM_SETTEXT, false, (long int) "Error al obtener el archivo");
}

int Buscar_Proceso()
{

//Con esto creamos una captura de la lista de procesos y la guardamos en CProc
CProc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

Proceso.dwSize = sizeof(PROCESSENTRY32);

Process32First(CProc,&Proceso); //Leemos el primer proceso

//Mientras haya procesos para leer leemos el siguiente
while(Process32Next(CProc,&Proceso))
{

if(!strcmp(Proceso.szExeFile, n_Proceso) )
{
pid = Proceso.th32ProcessID;

return 0;
}
}

pid = 0;
return 1;
}

int Inyectar()
{
if( (hProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid) ) == NULL)
{
strcpy(mensaje,
"No se pudo abrir el proceso ya sea porque no se esta ejecutando o poque no se verifico");

return -1;
}

if( (dLoadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"),
"LoadLibraryA") ) == NULL )
{
strcpy(mensaje,
"Error al encontrar la direccion de LoadLibrary");

return -2;
}

if( (Existe_A(ruta_dll)) == 1 )
{
strcpy(mensaje,
"Verifique la ruta de la DLL");

return -3;
}

if( (dDll = (LPVOID)VirtualAllocEx(hProc,0,strlen(ruta_dll),
MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE) ) == NULL )
{
strcpy(mensaje,
"Error al reservar memoria en el proceso remoto");

return -4;
}

if( ( WriteProcessMemory(hProc,(LPVOID)dDll,ruta_dll,
strlen(ruta_dll),NULL) ) == 0 )

{
strcpy(mensaje,
"Error al escribir en el proceso remoto");

return -5;
}

if( (CreateRemoteThread(hProc, NULL ,0,(LPTHREAD_START_ROUTINE)dLoadLibrary,
(LPVOID)dDll , 0 , 0) ) == NULL )
{
strcpy(mensaje,
"Error al crear el hilo remoto");

return -6;
}

strcpy(mensaje, "Se inyecto la dll en el proceso!");
return 0;

}

int Existe_A(char *ruta)
{
FILE *arc = fopen(ruta, "r");

if(!arc)
{
return 1;
}

fclose(arc);
return 0;
}
[/code]

un salutido, capaz y a alguien le sirve 😛

Respuesta:

Justamente hoy le estaba haciendo unas modificaciones al inyector en otra pc. Me salto ese mismo error, lo solucione anyadiendo esto a linker. -lcomdlg32
Si compilas con Dev c++. Vas a Tool, Compiler Options y lo agregas en el cuadro del linker. O si creaste un proyecto (lo cual es lo ideal asi solo en el proyecto se agrega ese parametro al linker) lo agregas desde Project, Project Options, Parametres, y lo agregas en el cuadro del linker.

Si justo ayer estaba leyendo sobre el tema pero no creo que me haya quedado muy claro el concepto. Basicamente lo que se hace es modificar los primeros bytes de una api para que cada vez que se llame a la api salte hacia la direcccion de memoria de mi codigo reservado, no? No lo entendi bien :l

Saludos,
Ángel

Exploit Browser [Metasploit] en WAN

January 25th, 2011

Este artículo pertenece a una serie de dudas antiguas que fueron publicadas en foros de internet antes de la creación del blog, lo plasmo aquí para no perderlas y que formen parte de la antología.

Post:

Saludos,

El problema es que estoy tratando de hacer funcionar un exploit browser del metasploit en wan.
Por poner un ejemplo, digamos que uso este (esto esta parcheado, ya lo se, pero igual me pasa con otros (: ) exploit, al momento de setear las opciones srvhost y lhost  (uso un payload reverse), no estoy completamente seguro de que debería de colocar hay para que funcione en wan.

En LAN me funciona perfecto colocando la ip privada. Pero si pongo la ip privada en el exploit, el server no podrá ser accesado en cualquier WAN-side host.

Pueden tomar de referencia estos tres topics:

http://www.portalhacker.net/b2/fallo-metasploit-puerto-ocupado/121191/
http://www.portalhacker.net/index.php/topic,89922.0.html
http://www.portalhacker.net/index.php/topic,110103.0/prev_next,prev.html

En los cuales ninguno llego a una respuesta contundente.  :cura:

Si alguien sabe como solucionar esto, bienvenido sea.

Un saludo y gracias por adelantado. (:

PD. Los puertos usados en el exploit están abiertos.

Respuesta:

Chan, chan, chann.  . ..  ya resolví esto. :- D

Pues es mas simple de lo que pensaba, setean el srvhost y el lhost en 0.0.0.0 el exploit les va a devolver esto:
http://0.0.0.0:8080/NjlMZDAAo0y

Hacen un port forwarding al puerto que necesita el exploit redireccionandolo a su pc.

La url la forman con su ip publica que remplaza el 0.0.0.0 y listo quedando asi:

http://ip.pu.bli.ca:8080/NjlMZDAAo0y

Listo! lo envían y  en cuestiones de seg y con mucha suerte tendrán su sección.
Si tienen mala suerte al pc victima le saltara el av o el firewall bloqueando la ejecucion del exploit.

Un saludte :P

Saludos,
Ángel

Powered by WordPress. Theme by Sash Lewis modified by 0aps.