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 - The Swash

#1
Buenas,

Tengo un proyecto donde necesito obtener información de un sitio web que no provee un API, por ende necesito obtener la información mediante peticiones y parsear los datos constantemente.

El sitio básicamente es un mercado en línea, básicamente la interacción sería algo así: App: Web dame los items en venta según X criterios.
Web: item1, item2, ..., itemN
App: selecciona los que le convienen, pujar por X items.

Si se dan cuenta la aplicación estará constantemente haciendo cosas similares a lo anterior y necesito un lenguaje que cumpla con lo siguiente:


  • Buen manejo de concurrencia
  • Buen manejo de datos
  • Soporte de librerías para web requests
  • Tiempo moderado de aprendizaje y desarrollo
  • De preferencia un lenguaje moderno


Me gustaría un lenguaje como Scala, Go o D, pero me gustaría enfatizar en que cada milisegundo es realmente importante para mi aplicación y en lo posible necesito las sugerencias respecto al lenguaje que más me convenga.

Gracias.
#2
ASM / Duda con suma de números binarios!
22 Octubre 2013, 03:27 AM
Buenas, he estado estudiando arquitectura, el formato IEEE-754, y demás y me ha surgido la siguiente duda:

Teniendo los números binarios con parte fraccionaria en punto fijo:
1000011,10001100110110110110110... (periódico)
Y:
1001111,10001001

Alguien podría darme luces? necesito sumarlos pero no sé como debo proceder con el periodo,

Muchas gracias.
#3
Bueno señores pues como es común que cada mes la lista de CracksLatinos publica una lista de "retos" sobre los cuales hay que trabajar y posteriormente resolver, este mes escogí al azar uno de los 2 retos de unpacking y aquí les dejo el tutorial.

Descarga - Dropbox

Saludos.
#4
GNU/Linux / Problema con retraso del teclado.
10 Octubre 2012, 19:45 PM
Buenas,

Tengo un pequeño problema casi sin importancia respecto al teclado utilizando Linux en general pero actualmente utilizo Fedora 17 x86_64.

Mi problema radica en que suelo escribir con cierta rapidez y me suele ocurrir lo siguiente:

FRase - Cuando debería ser Frase. Irónicamente parece que hay algún retraso entre el cambio de mayúscula a minúscula.
Esto no me pasó casi nunca cuando utilizaba Windows.

Agradecería cualquier sugerencia.

Saludos.
#5
Java / [Duda] Interfaces (objetos).
8 Septiembre 2012, 21:19 PM
Buenas tardes,

Tengo una duda muy puntal respecto a las interfaces en java, las interfaces vienen siendo abstracción pura. Según mi concepto obligan a implementar métodos definidos en esta a clases que implementen la interfaz.

Mi duda surge en:
¿Si tengo una clase que implementa una interfaz, pero en dicha clase creo un método que no está definido en la interfaz funcionaría? o me veo límitado a los métodos de la interfaz?.

Con un ejemplo real:
Interfaz:
Código (java) [Seleccionar]
public interface IList<E> {
public void add(E target);
public boolean isEmpty();
public boolean isFull();
public boolean contains (E target);
public void set (int index, E target);
public E get(int index);
public E remove(int index);
public boolean remove (E target);
public void print();
}


Clase que implementa la interfaz:
Código (java) [Seleccionar]
public class CList<E> implements IList<E> {

private E[] data;
private int size;

public void add(int index, E target){
if ((index > 0) && (index < size)){
if(isFull())
stretch();
for (int i = index; i <= size; i++)
data[i+1]= data[i];
data[index]= target;
size++;
}
}

public boolean isEmpty(){
return size==0;
}

public boolean isFull(){
return data.length == size;
}

private void stretch(){
E[]temp = (E[]) new Object[data.length*2];
for (int  i=0; i<data.length; i++)
temp[i]= data[i];
data=temp;
}

public void add(E target){
if(isFull())
stretch();
data [size]= target;
size++;
}

public E get(int index){
if (index >0 && index< size)
return data[index];
return null;
}

public void set(int index, E target){
if((index >= 0)&& (index< size))
data[index]= target;
}

public CList(){
data = (E[]) new Object[1];
size=0;
}

public boolean contains (E target){
for(int i = 0; i < size; i++){
if(data[i].equals(target))
return true;
}
return false;
}

public E remove(int index){
if (index>=0 && index < size){
E element= data[index];
for (int i= index; i<size-1; i++)
data[i]=data[i+1];
size--;
return element;
}
return null;
}

public boolean remove (E target){
for (int i=0; i<size; i++){
if (data[i].equals(target)){
E element= remove(i);
size--;
return true;
}
}
return false;
}

public void print(){
if(! isEmpty()){
for (int i= 0; i<size; i++)
System.out.print(data[i] + " ");
}
}

public boolean removeAll(E target){
boolean resultado = true;
int cont = 0;
if (!isEmpty()){
while(resultado){
cont++;
resultado = remove(target);
}
if (cont > 1)
return true;
}
return false;
}

public static void main(String[] args ){
IList<String> lista=new CList<String>();
lista.print();
lista.add("B");
lista.add("F");
lista.add("A");
lista.add("Z");
lista.add("W");
lista.add("P");
lista.add("R");
lista.add("A");
lista.add("S");
lista.add("A");
lista.add("P");
lista.print();
System.out.println(lista.removeAll("A"));
lista.print();
}
}


Claramente se puede notar al compilar un error por no encontrar el símbolo de la función "removeAll". Si declaro el método en la interfaz funciona sin ningún pero, entonces sólo quiero asegurarme de que la interfaz me limita los métodos que puede tener mi clase como "públicos".

Ahora mismo comprobé que si instancio la clase utilizando su mismo tipo de dato así:

Código (java) [Seleccionar]
CList<String> lista = new CList<String>;

El problema desaparece y todo recae en crear un objeto del tipo Interfaz e instanciarlo con una clase que contiene métodos que la interfaz no contiene.

¿Estoy en lo correcto?
¿Por qué el error de la primera forma de instanciar la clase?

De poder entrar en detalle lo agradecería.

Muchas gracias,
Iván Portilla.
#6
Hola,

Hoy les traigo un pequeño análisis que le hice a este packer y bueno, también lo desempacamos!
Es mi primer unpacking y espero sepan disculparme los errores técnicos que dicho documento pueda tener.

Disfrutadlo!

Descarga:
https://dl.dropbox.com/u/26610132/Estudio%20y%20desempaquetado%20RDG%20PolyPack%20por%20The%20Swash.rar

Un saludo,
Iván Portilla.
#7
Hola,

Bueno chicos vengo a compartir con vosotros la primera entrada que hago en un blog el cual ahora administro y escribo, vamos esta sigue siendo mi comunidad pero es la primera entrada que hago. Espero les sea de utilidad y bueno a leer :)

Esta entrada es sobre algo que me llevó un poco de esfuerzo y unos cuantos días de pruebas y pruebas para que funcione. Se trata sobre el "Thread Local Storage" que es un directorio de los ejecutables de Microsoft Windows que hace parte de la estructura PE.

¿Que nos dice la documentación oficial sobre el Thread Local Storage?
Cito traduciendo:
CitarLa sección ".tls" proporciona soporte al PE y COFF de almacenamiento local de subprocesos estáticos. TLS es una clase de almacenamiento especial que Windows soporta con el que objetos de datos no son automáticos (estáticos), sin embargo es local a cada hilo que se ejecuta. Por lo tanto cada hilo puede tener un valor diferente para cada variable declarada mediante el uso de TLS.

Si nos apoyamos en lo que conocemos, podemos decir simplemente que es una rutina que sirve para inicializar los valores de objetos estáticos. Dichos valores se deben inicializar antes de la ejecución del programa y he aquí el porqué se ejecutan antes que el punto de entrada del ejecutable.

Miremos su "estructura" y con seguridad veremos algo que aprovechar:
struct Thread_Local_Storage
{
    DWORD: RawDataStartVA;
    DWORD: RawDataEndVA;
    DWORD: AddressOfIndex
    DWORD: AddressOfCallBacks;
    DWORD: SizeOfZeroFill;
}


Hablemos de algunos campos de su estructura, antes que nada recalco que los 4 primeros campos son direcciones virtuales.

  • RawDataStartVA: La dirección de inicio de la plantilla TLS. La plantilla es un bloque que es utilizado para inicializar la infor-mación TLS. El sistema copia todo de estos datos cada vez que un hilo es creado.
  • RawDataEndVA: La dirección del último byte de la información del TLS excepto para el relleno de ceros.
  • AddressOfIndex: El lugar que recibe el índice del TLS que el loader asigna. Esta ubicación es una sección de datos ordinaria por lo que se puede dar un nombre simbólico que sea ac-cesible al programa.
  • AddressOfCallBacks: Puntero a la serie de funciones TLS. El fin de la matriz se identifica por que la última entrada tiene valor nulo.
  • SizeOfZeroFill: El tamaño en bytes de la plantilla.
  • Characteristics: Reservado.

Los dos primeros campos son utilizados para delimitar la información con la cual inicializar, pero ¿Nosotros vamos a inicializar información?
No, nosotros vamos a aprovecharnos de la estructura y de dos campos suyos (AddressOfIndex y AddressOfCallBacks). Principalmente del segundo que corresponderá a un puntero a una matriz de direcciones que a cada dirección corresponde una función que se ejecutará para "inicializar información".
He aquí un pequeño gráfico para que les quede más claro:

Si nos vamos entendiendo entonces tendréis claro que no queremos inicializar objetos, pero queremos aprovechar que podemos ejecutar alguna rutina antes de que siquiera se ejecute la primera instrucción del programa, he aquí un método de infección que tiene ya su tiempo pero yo no conozco un ejemplar.

Teoría de una ¿infección?
Primero me gustaría aclarar unos detalles acerca de los "requerimientos" de una estructura TLS.
El campo AddressOfIndex debe encontrarse referenciado en una sección con permisos de lectura y escritura puesto que el "loader" de Windows tratará de escribir en él y en caso de no poder nos dará un lindo "ACCESS VIOLATION ON WRITTING". Garantizada la posibilidad de escritura en este campo tenemos casi todo, nos resta referenciar el puntero de AddressOfCallBacks que apuntará a una matriz de direcciones de 4 bytes, las cuales cada es una función distinta que se ejecutará, debéis recordar que el final de estas direcciones será un DWORD nulo.

Teoría:
Nosotros podemos ejecutar alguna rutina que más bien se conocen como "shellcodes" la cual ejecutará una acción. Imagínate poder descargar y ejecutar algo, o modificar el mismo ejecutable, y más. Todo legítimamente y solo porque "inicializamos" objetos. Bueno entonces os comento lo que debéis hacer:

  • Agregando la shellcode: Necesitaremos agregar en alguna parte del ejecutable la rutina que queremos que ejecute, hay opciones como crear una sección nueva, expandir y abrirnos un espacio en una sección u otras alternativas como aprovecharnos de una pequeña "indocumentación" y ejecutarnos en la cabecera del ejecutable. Por limpieza sería mucho mejor agregar una sección pero estaríamos dando referencia muy fácil a donde nos encontramos y creo que el método que utilicéis para agregar la shellcode depende de vuestros fines.
  • Agregando directorio TLS: Para que podamos realizar esto deberemos agregar la estructura ya mencionada y en caso de existir tan solo agregar una referencia a nuestra rutina en la matriz de AddressOfCallBacks. Debes tener muy presente que los campos más importantes son AddressOfCallBacks & AddressOfIndex, si ignoramos cualesquiera podemos contar con que no funcionará. El directorio se encuentra en la décima entrada de IMAGE_DATA_DIRECTORY y el tamaño de dicha estructura es 0x20 bytes.

Teoría, teoría y la práctica ¿qué?
Bueno, bueno como mi idea no es repetir artículos que ya escribí voy a darles unas herramientas entre ellas información que os dará más idea de todo esto. Añado un enlace a 3 documentos que hablan sobre el tema y además una sorpresa después de las imágenes.


Ejemplo de infección práctico-teórico con TLS:
https://dl.dropbox.com/u/26610132/TLS.rar

Tutorial del formato PE en español basado en el PECOFF:
https://dl.dropbox.com/u/26610132/Formato%20de%20ficheros%20ejecutables%20_Formato%20PE_.pdf

Documentación oficial de Microsoft sobre el PE - PECOFF:
http://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx

Imágenes:



Tal vez te hayas fijado en la imagen de OllyDBG y te preguntes ¿por qué ese return a NTDLL?
Bueno, pues es parte de la carga del ejecutable el lanzar la rutina que ejecute nuestro TLS así que terminada la ejecución de nuestras rutinas terminará de cargar el ejecutable y lo lanzará, por ello es que se ejecuta antes que el punto de entrada. IDA detectará que hay TLS y he ahí la imagen.
¿Y la primera imagen de qué es?
Bueno es un prototipo de un archivo que infecta a los archivos ejecutables de su mismo directorio.

¿Recuerdas que te dije que yo no conocía ejemplares?
El principal objeto de este artículo es compartir un pequeño ejemplar programado en MASM, seguramente os puede servir mucho para su estudio y bueno, es un ejemplar así que hay muchas cosas para tener en cuenta demás.

Código (asm) [Seleccionar]

; #################################################
; # Ejemplo de infección de ejecutables con TLS
; # Programado por Iván Portilla
; # Viernes, 8 de junio de 2012
; # http://reversingcode.com
; # Agradecimientos: Shaddy, Guan de dio & Lelouch 
; #################################################


Código fuente:
https://dl.dropbox.com/u/26610132/infection.asm

Hasta la próxima.

Un saludo,
Iván Portilla.
#8
Hola,

Hoy vengo a molestaros con una pequeña consulta y es referido a MASM, y es la siguiente:
Yo tengo un número de funciones que hice y quisiera poder hacer un solo archivo que contenga esas funciones para posteriormente incluirlo en mis otros proyectos. Mi duda recae en que mis funciones van así:

Código (asm) [Seleccionar]
proc MyFunc1, Param..

end proc


Pero no he logrado que funcione o no al menos con un include MyProcs.asm.
Creo que debo declarar de alguna forma las funciones en cabecera o algo, si alguien sabe agradecería me deis una pequeña manita.

Un saludo,
Iván Portilla.
#9
Programación C/C++ / [C]Resource Dumper.
31 Mayo 2012, 21:48 PM


Hola,

Hoy les vengo a traer una aplicación que programé y lo que en realidad hace es extraer todos los recursos de un ejecutable. Más que por su utilidad seguro pueden entender como funciona el directorio de recursos de un archivo ejecutable.
No utilizo ninguna función API de recursos proporcionada por Windows, todo está hecho a mano.

Un saludo,
Iván Portilla.

Actualizado 22 de junio de 2012, ahora soporta parámetros en su función principal y tiene corregidos errores de manejo de memoria y está mucho más optimizado.

/**************************************************
* Resource Dumper v0.1 .
* Programado por Iván Portilla.
* Actualizado 22 de junio de 2012
* http://www.h-sec.org & http://www.elhacker.net
**************************************************/

#include <stdio.h>
#include <windows.h>
#include <Strsafe.h>
#define STATIC_SIZE 0x20

void GetResources(PBYTE MappedFile, DWORD ResourceRVA, PCHAR Path, PIMAGE_SECTION_HEADER ish, DWORD NumberOfSections);
int RVA_TO_OFFSET(int RVA, PIMAGE_SECTION_HEADER ish, int NumberOfSections);
int RESOURCE_DUMP(PCHAR lFile, PCHAR MappedName, PCHAR DumpPath);
int RESOURCE_TO_FILE(PCHAR Path, PBYTE ResourceRVA, DWORD Size);
PCHAR ResourceType(DWORD ResType);
PCHAR UNICODE_TO_STRING(PIMAGE_RESOURCE_DIR_STRING_U String);

typedef BOOL (WINAPI * _PathIsDirectory)(PCHAR Directory);
typedef BOOL (WINAPI * _PathFileExists)(PCHAR Directory);

char STR_ID[STATIC_SIZE];
char STR_ID2[STATIC_SIZE];
char STR_ID3[STATIC_SIZE];
char STR_ID4[STATIC_SIZE];
char * RESOURCES[25] = {"RT_CURSOR","RT_BITMAP","RT_ICON","RT_MENU","RT_DIALOG",
                        "RT_STRING","RT_FONTDIR","RT_FONT","RT_ACCELERATOR","RT_RCDATA",
                        "RT_MESSAGETABLE","RT_GROUP_CURSOR","","GROUP_ICON","","RT_VERSION",
                        "RT_DLGINCLUDE","","RT_PLUGPLAY","RT_VXD","RT_ANICURSOR","RT_ANIICON",
                        "RT_HTML","RT_MANIFEST","UNKNOWN"};

int main(int argc, char * argv[])
{
    _PathIsDirectory PathIsDirectoryA = (_PathIsDirectory)GetProcAddress(LoadLibraryA("Shlwapi.dll"), "PathIsDirectoryA");
    _PathFileExists PathFileExistsA = (_PathFileExists)GetProcAddress(LoadLibraryA("Shlwapi.dll"), "PathFileExistsA");;

    printf("####  ####\n");
    printf("#  #  #   #\n");
    printf("# #   #    #\n");
    printf("##    #    #\n");
    printf("# #   #   #\n");
    printf("#  #  ####\n\n");
    printf("Resource Dumper Base Model v0.1\n\n");

    if ((PathFileExistsA != NULL) && (PathIsDirectoryA != NULL))
    {
        if (argc == 4)
        {
            if ((PathFileExistsA(argv[1]) == 1) && (PathIsDirectoryA(argv[3])) && (argv[2] != NULL))
            {
                RESOURCE_DUMP(argv[1], argv[2], argv[3]);
            }
            else
                printf("Check your parameters [File path, File Mapped Name, Path To Save Resources] (ALL STRINGS)");
        }
        else
            printf("This software should be execute with params [File path, File Mapped Name, Path To Save Resources] (ALL STRINGS)");
    }
    else
        printf("Fail to load API functions of shlwapi.dll.");
    getchar();
    return 0;
}

int RESOURCE_DUMP(PCHAR iFile, PCHAR MappedName, PCHAR DumpPath)
{
    HANDLE lFile, lMap;
    PBYTE Mapped;
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INH;
    DWORD Resource;

    lFile = CreateFileA(iFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,0,0);
    if (lFile != INVALID_HANDLE_VALUE)
    {
        lMap = CreateFileMappingA(lFile, NULL, PAGE_READONLY, 0, 0, MappedName);
        Mapped = (PBYTE)MapViewOfFile(lMap, FILE_MAP_READ, 0, 0, 0);
        IDH = (PIMAGE_DOS_HEADER)Mapped;
        if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
        {
            INH = (PIMAGE_NT_HEADERS)&Mapped[IDH->e_lfanew];
            if(INH->Signature == IMAGE_NT_SIGNATURE)
            {
                Resource = INH->OptionalHeader.DataDirectory[2].VirtualAddress;
                if (Resource > 0)
                {
                    printf("Getting resources..\n");
                    GetResources(Mapped, Resource, DumpPath,(PIMAGE_SECTION_HEADER)&Mapped[IDH->e_lfanew + 24 + INH->FileHeader.SizeOfOptionalHeader], INH->FileHeader.NumberOfSections);
                }
                else
                    printf("Resource directory not present\n");
            }

        }
        UnmapViewOfFile(Mapped);
        CloseHandle(lMap);
        CloseHandle(lFile);

    }
    else
    {
        return -1;
    }

    return 0;
}

void GetResources(PBYTE MappedFile, DWORD ResourceRVA, PCHAR Path, PIMAGE_SECTION_HEADER ish, DWORD NumberOfSections)
{
    PIMAGE_RESOURCE_DIRECTORY IRD, SUBIRD, SSUBIRD;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY IRDRE, SUBIRDRE, SSUBIRDRE;
    PIMAGE_RESOURCE_DATA_ENTRY IRDTE;
    PIMAGE_RESOURCE_DIR_STRING_U IRDS;
    DWORD NumberOfEntries, NumberOfSubEntries, NumberOfSSubEntries, Counter = 0, Tick = 0, lBytes = 0;
    PCHAR UNICODE_STR_PARSED = NULL;
    PCHAR RES_TYPE = NULL;

    Tick = GetTickCount();
    IRD = (PIMAGE_RESOURCE_DIRECTORY) &MappedFile[RVA_TO_OFFSET(ResourceRVA, ish, NumberOfSections)];
    NumberOfEntries = (IRD->NumberOfNamedEntries + IRD->NumberOfIdEntries);
    IRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)IRD + sizeof(IMAGE_RESOURCE_DIRECTORY));
    printf("[Root resource directory entries: %X]\n\n", NumberOfEntries);
    while(NumberOfEntries > 0)
    {
        if (IRDRE->DataIsDirectory == 1)
        {
            SecureZeroMemory(STR_ID3, STATIC_SIZE);
            if (IRDRE->NameIsString == 0)
            {
                RES_TYPE = RESOURCES[(IRDRE->Id)-1];
                printf("  [Resource type: %s]\n", RES_TYPE);
                StringCchCopyA(STR_ID3, STATIC_SIZE, RES_TYPE);
                StringCchCatA(STR_ID3, STATIC_SIZE, "_");
            }
            else
            {
                IRDS = (PIMAGE_RESOURCE_DIR_STRING_U) (IRDRE->NameOffset + (int)IRD);
                UNICODE_STR_PARSED = UNICODE_TO_STRING(IRDS);
                printf("  [Resource type: %s]\n", UNICODE_STR_PARSED);
                StringCchCopyA(STR_ID3, STATIC_SIZE, UNICODE_TO_STRING(IRDS));
                StringCchCatA(STR_ID3, STATIC_SIZE, "_");
                GlobalFree(UNICODE_STR_PARSED);
            }
            SUBIRD = (PIMAGE_RESOURCE_DIRECTORY) ((int)IRD + IRDRE->OffsetToDirectory);
            NumberOfSubEntries = SUBIRD->NumberOfNamedEntries + SUBIRD->NumberOfIdEntries;
            SUBIRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)SUBIRD + sizeof(IMAGE_RESOURCE_DIRECTORY));
            printf("    [Number of sub entries: %x]\n", NumberOfSubEntries);
            while(NumberOfSubEntries > 0)
            {
                if(SUBIRDRE->DataIsDirectory == 1)
                {
                    printf("      [Resource Id: %i]\n", SUBIRDRE->Id);
                    SSUBIRD = (PIMAGE_RESOURCE_DIRECTORY) ((int)IRD + SUBIRDRE->OffsetToDirectory);
                    NumberOfSSubEntries = SSUBIRD->NumberOfNamedEntries + SSUBIRD->NumberOfIdEntries;
                    SSUBIRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)SSUBIRD + sizeof(IMAGE_RESOURCE_DIRECTORY));
                    printf("      [Number of re-sub entries: %x]\n", NumberOfSSubEntries);
                    while(NumberOfSSubEntries > 0)
                    {
                        IRDTE = (PIMAGE_RESOURCE_DATA_ENTRY) ((int)IRD +SSUBIRDRE->OffsetToData);
                        printf("        [RVA: 0x%X Size: 0x%X]\n", IRDTE->OffsetToData, IRDTE->Size);

                        SecureZeroMemory(STR_ID, STATIC_SIZE);
                        SecureZeroMemory(STR_ID2, STATIC_SIZE);
                        SecureZeroMemory(STR_ID4, STATIC_SIZE);

                        StringCchCatA(STR_ID4, STATIC_SIZE, STR_ID3);
                        _itoa(SUBIRDRE->Id, STR_ID, 10);
                        StringCchCatA(STR_ID, STATIC_SIZE, "_");
                        _itoa(SSUBIRDRE->Id, STR_ID2, 10);
                        StringCchCatA(STR_ID4, STATIC_SIZE, STR_ID);
                        StringCchCatA(STR_ID4, STATIC_SIZE, STR_ID2);
                        RESOURCE_TO_FILE(Path, (PBYTE)((int)MappedFile + RVA_TO_OFFSET(IRDTE->OffsetToData, ish, NumberOfSections)), IRDTE->Size);
                        NumberOfSSubEntries = NumberOfSSubEntries - 1;
                        SSUBIRDRE++;
                        Counter++;
                        lBytes += IRDTE->Size;
                    }
                }
                NumberOfSubEntries = NumberOfSubEntries - 1;
                SUBIRDRE++;
            }
        }
        NumberOfEntries = NumberOfEntries - 1;
        IRDRE++;
    }
    printf("\nResources dumped: 0x%X.", Counter);
    printf("\nTime of dumped: %i miliseconds.", (GetTickCount()-Tick));
    printf("\nBytes dumped: 0x%X.", lBytes);
}

int RVA_TO_OFFSET(int RVA, PIMAGE_SECTION_HEADER ISH, int NumberOfSections)
{
    int i, Offset = 0;
    if (ISH != NULL)
    {
        for (i = 0; i < NumberOfSections; i++)
        {
            if ((RVA >= (int)ISH[i].VirtualAddress) && (RVA <= (int)(ISH[i].VirtualAddress + ISH[i].Misc.VirtualSize)))
            {
                    Offset = (RVA - ISH[i].VirtualAddress) + ISH[i].PointerToRawData;
            }
        }
    }
    else
        Offset = 0;

    return Offset;
}

PCHAR UNICODE_TO_STRING(PIMAGE_RESOURCE_DIR_STRING_U String)
{
    PCHAR nStr = (PCHAR) GlobalAlloc(GPTR, String->Length + 1);;
    WideCharToMultiByte(CP_ACP, 0, String->NameString, String->Length * 2, nStr, String->Length, NULL, NULL);
    return nStr;
}

int RESOURCE_TO_FILE(PCHAR Path, PBYTE ResourceRVA, DWORD Size)
{
    PCHAR lFile = (PCHAR)GlobalAlloc(GPTR, lstrlenA(Path) + STATIC_SIZE);
    PCHAR Buffer = (PCHAR)GlobalAlloc(GPTR, Size);
    HANDLE sFile;
    DWORD Bytes = 0, Rest;

    CopyMemory(Buffer, ResourceRVA, Size);
    StringCchCopyA(lFile, lstrlenA(Path) + STATIC_SIZE, Path);
    if ((Path[lstrlenA(Path)-2] == 92) & (Path[lstrlenA(Path)-1] == 92))
        StringCchCopyA(&lFile[lstrlenA(Path)], lstrlenA(Path) + STATIC_SIZE, STR_ID4);
    else
    {
        lFile[lstrlenA(Path)+1] = 92;
        lFile[lstrlenA(Path)] = 92;
        StringCchCopyA(&lFile[lstrlenA(Path)+2], lstrlenA(Path) + STATIC_SIZE, STR_ID4);
    }
    sFile = CreateFileA(lFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
    if (sFile != INVALID_HANDLE_VALUE)
    {
        WriteFile(sFile, Buffer, Size, &Bytes, NULL);
        CloseHandle(sFile);
        Rest = 0;
    }
    else
        Rest = -1;

    GlobalFree(Buffer);
    GlobalFree(lFile);
    return Rest;
}
#10
Buenos días,
Hoy traigo un problema a ver si me pueden colaborar. Tengo mi Notebook de la cual os proporciono los siguientes datos:
- Modelo: Compaq CQ10-800
- Windows 7 Ultimate SP1 32 bits.

Mi problema surge cuando quiero instalar mi máquina virtual con VMWare (Windows 7 64-bits, tampoco sé si no se pued), la cúal me dice lo que tengo deshabilitado la virtualización asistida por hardware.

Comprobé que mi Notebook lo soportara con la herramienta de identificación de procesadores de Intel además del HAV Detection Tool de Microsoft ambos con la misma respuesta.

Os pego la parte importante generada por CPU-Z sobre mi hardware:
CPU-Z TXT Report
-------------------------------------------------------------------------

Binaries
-------------------------------------------------------------------------

CPU-Z version 1.60.1

Processors
-------------------------------------------------------------------------

Number of processors 1
Number of threads 4

APICs
-------------------------------------------------------------------------

Processor 0
-- Core 0
-- Thread 0 0
-- Thread 1 1
-- Core 1
-- Thread 0 2
-- Thread 1 3

Processors Information
-------------------------------------------------------------------------

Processor 1 ID = 0
Number of cores 2 (max 2)
Number of threads 4 (max 4)
Name Intel Atom
Codename
Specification Intel(R) Atom(TM) CPU N570   @ 1.66GHz
Package (platform ID) Socket 437 FCBGA8 (0x4)
CPUID 6.C.A
Extended CPUID 6.1C
Core Stepping B0
Technology 45 nm
Core Speed 997.6 MHz
Multiplier x FSB 6.0 x 166.3 MHz
Rated Bus speed 665.0 MHz
Stock frequency 1666 MHz
Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, EM64T, VT-x
L1 Data cache 2 x 24 KBytes, 6-way set associative, 64-byte line size
L1 Instruction cache 2 x 32 KBytes, 8-way set associative, 64-byte line size
L2 cache 2 x 512 KBytes, 8-way set associative, 64-byte line size
FID/VID Control yes
FID range 6.0x - 10.0x
Max VID 1.088 V


Además he actualizado la BIOS y he seguido el tutorial de Microsoft:
http://www.microsoft.com/windows/virtual-pc/support/configure-bios.aspx

Pero no me dá la opción de activar la tecnología de virtualización.
¿Saben que puede ocurrir?

Un saludo,
Iván Portilla
#11

Un saludo a todos los foreros, hoy les traigo un taller práctico-teórico sobre secciones de archivos ejecubles (PE).
Creo que será conveniente recordar conceptos y estructuras básicas sobre el formato PE, si desean profundizar no duden en leer otro documento que he realizado anteriormente sobre el tema "Formato PE bajo Windows", está en español y lo pueden encontrar en el siguiente enlace:
http://foro.elhacker.net/empty-t332157.0.html

O preferiblemente el documento que muchos llamamos la bíblia del Formato PE, el PECOFF que es la documentación oficial de Microsoft sobre el tema:
http://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx

Herramientas de práctica:
HexWorkShop v6.0.1: Editor hexadecimal.
http://dl.dropbox.com/u/26610132/HexWorkShop%206.rar

OllyDBG 1.10: Depurador.
http://dl.dropbox.com/u/26610132/OllyDGB%201.10.rar

Temas que tratará el taller:

  • Conceptos básicos y repaso sobre la estructura PE.
  • Agregando una sección.
  • El problema de la BOUND_IMPORT_TABLE.
  • Desorden en datos de secciones.
  • Ampliando el tamaño de una sección.
  • Datos entre secciones (no mapeados).
  • Secciones "Dummy".
  • Archivos sin ninguna sección.
  • Lo que realmente hace el TinyPE.
  • Explicación de medios de inyección (RunPE e inyección dependiente de relocaciones). -> A pedido de mi amigo _Enko

Repaso de conceptos y estructuras:
Bueno, nuestro enfoque es hacia los archivos ejecutables y su estructura. Un archivo ejecutable, ahora en adelante lo llamaré PE (Portable Executable) y presenta la siguiente estructura:


Estructuras:
IMAGE_DOS_HEADER:

  • DOS_SIGNATURE = 'MZ' -> WORD
  • [29 WORDS] -> Aquí abreviaremos son campos poco utilizados.
  • l_fanew = Apunta hacia IMAGE_NT_HEADERS -> DWORD

IMAGE_NT_HEADERS:

  • Signature = PEx0x0 -> Firma de validación de archivos PE. DWORD
  • IMAGE_FILE_HEADER 0x20
  • IMAGE_OPTIONAL_HEADER 0xE0

IMAGE_FILE_HEADER:

  • Machine: WORD -> Define la arquitectura del computador o emulador para ejecutar el programa
  • NumberOfSections: WORD -> Este valor numerico define la cantidad de secciones que tendrá el archivo.
  • TimeDateStamp: DWORD -> Fecha de creación del archivo.
  • PointerToSymbolTable: DWORD -> Utilizado solo en archivos COFF (.obj)
  • NumberOfSymbols: DWORD -> -> Utilizado solo en archivos COFF (.obj)
  • SizeOfOptinalHeader: WORD -> "Contiene el tamaño del IMAGE_OPTIONAL_HEADER"
  • Characteristics: DWORD -> Atributos u opciones que puede tener el archivo.

IMAGE_OPTIONAL_HEADER:

  • Magic: WORD -> Determina si el programa es para 32 o 64 bits.
  • MajorLinkerVersion: BYTE Versión más alta del linker.
  • MinorLinkerVersion: BYTE Versión más baja del linker.
  • SizeOfCode: DWORD Tamaño de la sección de código generalmente .text o .code.
  • SizeOfInitializedData: DWORD -> Tamaño de datos inicializados.
  • SizeOfUninitializedData: DWORD -> Tamaño de datos no inicializados.
  • AddressOfEntryPoint: DWORD -> RVA del punto de entrada del programa.
  • BaseOfCode: DWORD -> RVA Base de la sección de código.
  • BaseOfData: DWORD -> RVA Base de la sección de datos.
  • ImageBase: DWORD -> VA Base donde se cargará el PE.
  • SectionAlignment: DWORD -> Tamaño de alineación de datos en memoria.
  • FileAlignment: DWORD -> Tamaño de alineación de datos en disco.
  • MajorOperatingSystemVersion: WORD -> Versión principal del S.O requerido.
  • MinorOperatingSystemVersion: WORD -> Versión mínima del S.O requerido.
  • MajorImageVersion: WORD -> Versión principal del PE.
  • MinorImageVersion: WORD -> Versión mínima del PE.
  • MajorSubsystemVersion: WORD -> Versión principal del subsistema requerido.
  • MinorSubsystemVersion: WORD -> Versión mínima del subsistema requerido.
  • Win32VersionValue: DWORD -> Reservado.
  • SizeOfImage: DWORD -> Tamaño que ocupará el ejecutable en memoria, multiplo del SectionAlignment.
  • SizeOfHeaders: DWORD -> Tamaño de toda la cabecera PE.
  • CheckSum: DWORD -> Valor de comprobación por suma.
  • Subsystem: WORD -> Subsistema (consola, gráfico, etc).
  • DllCharacteristics: WORD -> Atributos u opciones pero en caso de librerías DLL.
  • SizeOfStackReserve: DWORD -> Tamaño de reserva para la pila.
  • SizeOfStackCommit: DWORD -> Tamaño de datos de la pila comprometidos.
  • SizeOfHeapReserve: DWORD -> Tamaño de reserva del montículo.
  • SizeOfHeapCommit: DWORD -> Tamaño de datos comprometidos del montículo.
  • LoaderFlags: DWORD -> Parámetros pasados al Loader.
  • NumberOfRvaAndSizes: DWORD -> Número de directorios en IMAGE_DATA_DIRECTORY.
  • IMAGE_DATA_DIRECTORY[NumberOfRVAAndSizes] -> Directorios de datos, conocidos como Tablas, donde tenemos otras estructuras como las importaciones y demás.

IMAGE_SECTION_HEADER

  • Name: (BYTE*8) -> Nombre de la sección.
  • VirtualSize: DWORD -> Tamaño de la sección en memoria.
  • VirtualAddress: DWORD -> RVA donde se carga la sección en memoria.
  • SizeOfRawData: DWORD -> Tamaño de la sección en disco.
  • PointerToRawData: DWORD -> Ubicación de la sección en disco.
  • PointerToRelocations: DWORD -> Campo ya no utilizado, reemplazado por uno de los directorios de datos.
  • PointerToLineNumbers: DWORD -> Solo usado en COFF (.obj).
  • NumberOfRelocations: WORD -> Campo no utilizado ya reemplazado.
  • NumberOfLineNumbers: WORD -> Solo usado en COFF (.obj).
  • Characteristics: DWORD -> Características de la sección (opciones).

Direcciones físicas, virtuales relativas y virtuales:
Antes de continuar quiero también recordar un poco del tema, ya que será necesario que tengan claro que es cada una de estas direcciones para el desarrollo práctico del taller.

Direcciones físicas:
También podemos llamar posición física y corresponden a los valores del archivo en disco osea físicamente al archivo. Va en rango de (0, Tamaño del archivo).

Direcciones virtuales relativas:
Decimos que son relativas porque son el desplazamiento respecto a una dirección virtual. Como se explicará a continuación cuando el archivo es cargado en memoria cambia mucho respecto a como esta en disco. Las direcciones virtuales relativas funcionan como lo sería una dirección física pero en memoria y además son relativas al ImageBase que recordemos es donde se carga el ejecutable. Si hablamos por ejemplo de un RVA 0x3000 en memoria correspondderá a ImageBase + 0x3000, si os verificáis sería muy distinto en obtener el mismo dato en dicha posición.

Direcciones virtuales:
Son direcciones que directamente se encuentran en el rango ImageBase, (ImageBase + SizeOfImage). En escencia sería eso, por ejemplo 0x401000 teniendo como ImageBase 0x400000 estaríamos dentro de dicho rango. Estas hacen referencia directa a una posición en memoria.

Un archivo cargado en memoria:
Bueno justamente quería hacer énfasis en como se vería un archivo cargado en memoria, podemos saber que será distinto que en disco empezando por el detalle de que en memoria será más "grande". Si miramos el SizeOfImage y comparamos en disco tendremos un valor relativamente más grande. Cabe decir que la carga de un archivo en memoria depende su un factor importante y es el campo "SectionAligment" No lo olvidéis.

Lo primero que hará es reservar el espacio, y justo en el ImageBase empezará a "plasmar" el archivo en memoria.

Lo primero que mapeará será la cabecera, cuyo tamaño está determinado por el campo SizeOfHeaders.
Posteriormente tendrá que cargar el cuerpo del archivo, pero es aquí donde entran las alineaciones. Generalmente el SectionAligment tiene el valor correspondiente al tamaño de una página en memoria (0x1000), entonces el mínimo tamaño que tendrá una sección en memoria será el valor del SectionAlignment asi en disco tenga 1 solo byte. Si es mayor entonces su tamaño corresponderá a (VirtualAddress + VirtualSize) redondeado al múltiplo mayor inmediato del SectionAligment.

Ejemplo:
VirtualAddress = 0x1000
VirtualSize = 0x250

Recueden que vamos en múltiplos del SectionAlignment generalmente 0x1000 entonces 0x1000 + 0x250 = 0x1250 el múltiplo mayor inmediato sería 0x2000. El resto será plasmado con muchos 00 hasta completar el tamaño.

Todo lo de la alineación es con el fin de tener orden y fácilidad de acceso a los datos. Entonces las secciones van cargadas en orden de su VirtualAddres sin importar el orden en que se encuentren en el IMAGE_SECTION_HEADER.

Os ilustro con u pequeño gráfico con el que os aclararéis un poco:


Si comprendiste seguramente se te van vieniendo ideas respecto a las secciones.

Nuestro trabajo con secciones:
Bueno esta será la parte que más agradará seguramente, aquí trataremos teoría y práctica de cosas que podemos hacer con las secciones de un archivo.


Parte teórica:
Espero si si estáis leyendo esto tengas los conceptos anteriores muy claros, serán bastante necesarios para que no te confundas.

¿Que define una sección?
Bueno hablemos sobre los campos involucrados en una sección.

  • NumerOfSections: Este campo contiene el número de secciones del ejecutable. Si agregamos una sección deberemos modificarle.
  • SizeOfImage: Este valor contiene el tamaño del ejecutable en memoria, si añadimos una sección entonces agregaremos datos, necesitamos sumar el valor "físico" de la sección al SizeOfImage.
Ahora hay unos campos que entran de manera opcional de acuerdo al campo "Characteristics" de la sección que agregaremos. Por ejemplo si utilizamos las opciones de InitializedData, deberemos actualizar el valor SizeOfInitializedData perteneciente al IMAGE_OPTIONAL_HEADER.

Parte práctica involucrando teoría:

Creando los datos para nuestra sección:
Ahora necesitaremos armar una sección aplicando la parte conceptual vista más arriba. Miremos los campos de una sección:


  • Name.
  • VirtualSize.
  • VirtualAddress.
  • SizeOfRawData.
  • PointerToRawData.
  • PointerToRelocations.
  • PointerToLineNumbers.
  • NumberOfRelocations.
  • NumberOfLineNumbers.
  • Characteristics.

Hay valores que deberemos calcular y otros que simplemente deberemos utilizarlos. Antes de pasar a como obtener los valores quiero mencionar que el IMAGE_FILE_HEADER tiene la declaración de NumberOfSections secciones. Todas las sección ubicada de manera consecutiva y todas utilizando la estructura standard ya mencionada. Cada sección tiene un tamaño de 0x28 bytes, entonces nuestra sección irá al final de la última sección.

De la sección necesitamos:

  • Su definición.
  • Su contenido.

Su definición es lo que va en IMAGE_SECTION_HEADERS donde proporciona todos los datos para que se cargue con el ejecutable.

Bueno para trabajar lo haremos con un pequeño EXE standard para todos nos podamos ubicar correctamente y puedamos seguir este taller.

Es un ejecutable de 1.5k y solo muestra un mensaje y se cierra, será suficiente por ahora.

Descarga:
http://dl.dropbox.com/u/26610132/Practica%201.exe

Para armar nuestra sección necesitaremos leer información del archivo, donde estan ubicadas las secciones, etc. Vamos!

Utilizaremos un editor hexadecimal y nada más.
Comencemos:

  • Primero deberemos ubicarnos al inicio y comprobar que es un archivo ejecutable válido, para ello comparamos los 2 primeros bytes con 'MZ'. (Está con azul en la imagen).
  • Ahora deberemos proceder a encontrar el campo l_fanew recueden ver la estructura, lo conseguimos así:
    El campo se encuentra despues de justo 30 WORDs y un WORD equivale a 2 bytes. Entonces 30*2 = 60, ahí se encuentra el campo l_fanew. (Está con rojo en la imagen).


Citar¿Ey, se han dado cuenta?
Justo en el offset 60 en decimal, se encuentra este valor "80 00 00 00", recueden que el campo es de tamaño DWORD -> 4 bytes. Pero y este campo ¿no apuntaba a la firma 'PE\x0\x0'?
Bueno si, contiene el valor donde empieza la firma 'PE\x0\x0' y posteriormente las demás estructuras. Pero ese valor ¿no es muy grande? Bueno, en realidad no. En windows se utiliza algo llamado Orden Little Endian, donde los bytes se organizan por decirlo al "reves", esto sucede con valores numericos y no con cadenas. Es cuestión de arquitectura y demás, en memoria este valor "80 00 00 00" será equivalente a "00 00 00 80" Vén como ahora tiene sentido? Ah una cosa, todos los valores de la cabecera PE estarán en formato Hexadecimal, y para que nos entendamos, cuando les menciones 60d = 60 en decimal y si menciono 0x80 = 80 en hexadecimal. Con la calculadora de Windows podréis hacer las conversiones.

Bien, ahora tenemos que PE\x0\x0 estará ubicado en el offset: 0x80 o 128d. ¿Es cierto?, bueno podemos darnos cuenta de que sí!. Ahora posterior a esta firma tendremos el IMAGE_FILE_HEADER, justo 4 bytes más adelante, osea en 0x84 o 132d. Tomemos nota con los valores reales:

  • Machine: 01 4C -> Posición: 0x84 o 132d
  • NumberOfSections: 00 02 -> Posición 0x86 o 134d
  • TimeDateStamp: 4F BD 28 3D -> Posición: 0x88 o 136d
  • PointerToSymbolTable: 00 00 00 00 -> Posición: 0x8C o 140d
  • NumberOfSymbols: 00 00 00 00 -> Posición: 0x90 o 144d
  • SizeOfOptionalHeader: 00 E0 -> Posición: 0x94 o 148d
  • Characteristics: 01 0F -> Posición: 0x96 o 150d

Tenemos el primer directorio, vamos con el segundo (?). Bueno era broma quería que vieran el mecanismo. Tienen que leer muy bien la estructura y sus tamaños recuerden:

  • BYTE = 1 byte
  • WORD = 2 bytes
  • DWORD = 4 bytes
  • BYTE * X = X bytes

Haremos exáctamente lo mismo, nos ubicamos al principio de cada directorio y así podemos obtener los datos que necesitamos. Entonces nos ubicamos en 0x98, porque Characteristics está en 0x96 y su tamaño es WORD, entonces el otro campo empieza en 0x98.
De IMAGE_OPTIONAL_HEADER necesitamos por ahora:

  • SizeOfImage -> Lo encontramos con 0x98 + 0x38 = 0xD0 y tiene un valor de 00 30 00 00 (real: 00 00 30 00)
  • SectionAlignment: -> Lo encontramos con 0x98(base IMAGE_OPTIONAL_HEADER) + 0x20 = 0xB8 y tiene un valor 00 10 00 00 (real: 00 00 10 00).
  • FileAlignment: -> Lo encontramos con 0x98 + 0x24 = 0xBC y tiene un valor 00 02 00 00 (real: 00 00 02 00).

Bien lo tenemos, ahora necesitamos ubicarnos en el inicio de IMAGE_SECTION_HEADER. Para ello utilizaremos el inicio del IMAGE_OPTIONAL_HEADER y sumaremos el valor de SizeOfOptionalHeader = 0xE0. Tenemos como resultado: 0x178, como podéis ver estamos en la primera sección. Pero necesitamos la estar parados justo al final de la última para escribir nuestra sección no? Bueno es fácil conseguirla, les había mencionado que el tamaño de esta estructura es 0x28, lo multiplicamos por el valor de NumberOfSections = 2 y tenemos que el final de la última sección está en: 0x178 + (0x28*2) = 0x1C8.

Pero que cerca estamos ahora deberemos generar los datos de nuestra sección, agregaremos una simple cadena "TALLER DE SECCIONES EHN" cuyo tamaño de 0x17 + :

  • Name: El que ustedes quieran que contenga 8 bytes. Usemos '.EHN' sin comillas.
  • VirtualSize: Corresponderá al tamaño de los datos de la sección, nuestro caso es 0x17 bytes
  • VirtualAddress: Corresponderá a la dirección virtual relativa donde se cargará la sección. Como sabemos nuestra sección esta justo al final, si tomamos el Valor del VirtualSize y el VirtualAddress de la sección anterior a nosotros, los sumamos y lo alineamos al SectionAligment podremos calcular nuestro VirtualAddress. Entonces:
    - Tendremos que ubicarnos en la sección anterior, recuerdan que estamos en el final? si restamox 0x28 a 0x1C8 estaremos parados justo en la sección anterior: 0x1A0. Ahora utilizando el mismo procedimiento obtendremos lo valores VirtualSize: 00 00 00 17 y VirtualAddress: 00 00 20 00, procedemos a sumarlos: 0x2017 y alineamos, recuerden el múltiplo mayor inmediato es 0x3000 y listo, tenemos nuestro VirtualAddress.
  • SizeOfRawData: Corresponderá al tamaño de los datos de la sección en disco, piensan que 0x17? Bueno pues no!, En disco al igual que en memoria todo debe ser alineado, y como en disco no hay nadie que nos alineé los datos deberemos hacerlo. ¿Como? Igual que como hacíamos antes solo que ahora alineamos al múltiplo mayor inmediato del FileAlignment. Ya lo habíamos conseguido entonces sería 0x17 y su múltiplo mayor inmediato es 0x200. Esos será el total de datos que deberemos agregar en disco al final del archivo, correspondientes a los datos de nuestra nueva sección.
  • PointerToRawData: Corresponderá a la ubicación o posición en el archivo físicamente de los datos de nuestra nueva sección. Tenemos 2 formas de conseguir dicho valor, una es con el tamaño exácto del archivo y ya, y la otra es sumando los valores PointerToRawData + SizeOfRawData de la sección anterior. De ambas formas llegamos a que es: 0x600, si se dan cuenta es múltiplo del FileAlignment por lo cúal constatamos que la sección anterior a nosotros está alineada.
  • PointerToRelocations: Como ya habíamos mencionado no se utiliza, lo dejamos a 0.
  • PointerToLineNumbers: Como ya lo habíamos mencionado no se utiliza, lo dejamos a 0.
  • NumberOfRelocations: Tampoco se utiliza, lo dejamos a 0.
  • NumberOfLineNumbers: Tampoco se utiliza lo dejamos a 0.
  • Characteristics: Sabía que este momento llegaría  :¬¬. Bueno habíamos mencionado ya algo de este campo en las secciones y era sobre atributos u opciones. Aquí podremos definir que atributos tendrá nuestra sección. Entre los atributos tenemos: Lectura, Escritura, Ejecución y demas. Para referencia exácta de estos valores consulte en las 2 fuentes mencionadas al principio. Por ahora utilizaremos 0xC0 00 00 00 el cual corresponde a atributos de Lectura y escritura.

Datos concretos y legíbles:

  • Name: .EHN -> Valor a plasmar: 2E 45 48 4E 00 00 00 00
  • VirtualSize: 0x17 -> Valor a plasmar: 17 00 00 00
  • VirtualAddress: 0x3000 -> Valor a plasmar: 00 30 00 00
  • SizeOfRawData: 0x200 -> Valor a plasmar: 00 02 00 00
  • PointerToRawData: 0x600 -> Valor a plasmar: 00 06 00 00
  • PointerToRelocations: 00 00 00 00
  • PointerToLineNumbers: 00 00 00 00
  • NumberOfRelocations: 00 00
  • NumberOfLineNumbers: 00 00
  • Characteristics: C0 00 00 00 -> Valor a plasmar: 00 00 00 C0

Cuando digo plasmar no me refiero a "INSERTAR" bytes sino a sobreescribir los 00 suficientes, si insertamos dañamos el ejecutable.
Quedará así:


Ahora nos restan los siguientes detalles:

  • Actualizar el valor del SizeOfImage.
  • Actualizar el valor del NumberOfSections.
  • Añadir los datos de la sección justo al final.

Nuevos valores:

  • SizeOfImage: SizeOfImage + SizeOfRawData de nuestra sección =  0x3200 y lo alineamos al SectionAlignment dando como resultado: 0x4000. Editarlo como 00 40 00 00 recordad lo del Little Endian.
  • NumberOfSections: NumberOfSections +1 = 3 Editarlo como 03 00
  • Añadimos al final 0x200 bytes, entre esos al principio estará nuestra cadena: "TALLER DE SECCIONES EHN", osea la cadena + 0x1E9 byes en 00.

Nuestro ejecutable ya tiene su sección y debe funcionar correctamente. Podemos constatar que la función se agregó con éxito si al cargarlo en OllyDBG e ir a la ventana Memory (M) ver la ImageBase de nuestro ejecutable y constatar que está cargada la otra sección, veamos:

Sección en memoria:


Datos de la sección mapeados en memoria:


Descarga archivo de práctica con sección agregada:
http://dl.dropbox.com/u/26610132/Practica%201-With%20section.exe

Con esto finalizamos la introducción en las secciones, posteriormente veremos otras situaciones en las que agregar una sección se puede complicar un poco, podéis empezar a seguir el taller con confianza.


Anteriormente había mencionado que se nos vendrían un par de obstáculos, que si no los miramos bien nos pueden dejar algo perdidos. Uno de ellos es el Directorio de datos #12 conocido como BOUND_IMPORT_TABLE.

Descarga archivo de practica #2:
http://dl.dropbox.com/u/26610132/Practica%202.exe

¿Que problema me puede causar este directorio?
Analicemos un poco las secciones, tiene 3 secciones código, datos y recursos. Es un ejecutable normal compilado en Visual Basic. Se preguntarán ¿Por qué lo elegí?, bueno por que la mayoría de los ejecutables Visual Basic tienen la BOUND_IMPORT_TABLE.
Ustedes se preguntarán ¿Que bronca me traigo con esa estructura?, no es solo mi bronca será la suya también  :D, Me interesa que nos ubiquemos en el final de la última sección (ya sabemos como, sino sabes vuelve a leer la parte superior del taller).


Si miramos nuestro anterior archivo de práctica veremos una gran diferencia, y es que hay algo despues de la última sección, bueno es la BOUND_IMPORT_TABLE.

Te cuento..
Te cuento que necesitas ese espacio para agregar la declaración de tu sección, pero alguien más ya lo está ocupando. Si intentamos escribir encima de ello nos toparemos con esto:


En realidad es fácil explicar el porque nuestro programa termina explotando, mirando el error:

  • 0xC0000005 - STATUS_ACCESS_VIOLATION
En realidad corresponde a una violación por acceso a un lugar al cúal no se puede acceder, cómo punteros nulos o valores inaccesibles en nuestro anillo de permisos. Todo se dá cuando se trata de validar el BOUND_IMPORT_DIRECTORY.

¿Hay solución?
Si, te cuento que hay 2 una menos ortodoxa que la otra pero ambas funcionan. Una preservadora y otra no presevadora.

  • Primera solución: Yoda(creador de LordPE) alguna vez mencionó que se puede establecer el RVA del directorio BOUND_IMPORT_DIRECTORY a 00 porque este era poco importante. Mi amigo karmany opinó al respecto y estoy de acuerdo con él, este directorio tiene como utilidad optimizar entonces me parece que importa. El ejecutable no deja de funcionar pero no preserva el estado original del ejecutable.
  • Segunda solución: Personalmente me parece la mejor y consiste en mover de sitio el BOUND_IMPORT_DIRECTORY. Si sabemos que está justo despues de la última sección, tranquilamente lo desplazamos 0x28 bytes y así tenemos espacio para una función. Posteriormente se actualiza el RVA en el Directorio de datos y lo habríamos solucionado.

Manos a la obra!
Bueno, probemos que todo lo que hemos dicho es cierto e intentemos añadir una sección al ejecutable de práctica teniendo en cuenta las 2 soluciones.

Creo que necesito hacer un breve recuerdo sobre el IMAGE_DATA_DIRECTORY asi que nombraré algunas de sus características.

  • Se ubíca justo antes de IMAGE_SECTION_HEADER.
  • Tiene como tamaño (8*IMAGE_OPTIONAL_HEADER.NumberOfRvaAndSizes).
  • Cuenta con un total de 16 directorios generalmente (aunque puede alterarse).
  • Cada directorio tiene 2 entradas, RVA(DWORD) y Size(DWORD).

Ya les había mencionado que el directorio correspondiente al BOUND_IMPORT_TABLE es el número 12, si aplicamos un poco de matemáticas y nos paramos justo al inicio de IMAGE_SECTION_HEADER y restamos (5*8) estaremos justo en la declaración del directorio. 0x1B0 - 0x28 = 0x188 -> BOUND_IMPORT_DIRECTORY, leamos los valores del directorio.

  • RVA: 0x228
  • Size: 0x20

Relizamos los desplazamientos:
Lo unico que deberemos hacer es cambiar el RVA del BOUND_IMPORT_DIRECTORY por RVA + 0x28 y posteriormente desplazar los datos en el archivo (Con desplazar me refiero a correr, nada de insertar.)

Nuevos datos:

  • RVA: 0x250
  • Size: 0x20

Y desplazando los datos tendríamos algo así:


Si miramos quedó desplazado y los bytes que quedaron en color rojo vendrá a ser el espacio para nuestra sección. Aún si no la agregasemos el ejecutable de igual forma quedaría funcionando y se preservaría.

Igual ya teníamos los datos sobre el archivo de práctica original, para aplicar el segundo método cambiamos el RVA por 00 00 00 00 y el Size por 00 00 00 00 y listo.

Descarga práctica con sección y método de desplazamiento de la BOUND_IMPORT_TABLE:
http://dl.dropbox.com/u/26610132/Metodo%20desplazamiento.exe

Descarga práctica con sección y método de eliminación de la BOUND_IMPORT_TABLE:
http://dl.dropbox.com/u/26610132/Metodo%20de%20eliminacion.exe

Con esto habríamos terminado la parte de agregar secciones aunque agregaré lo siguiente:
El otro problema sería para más que un problema un caso de profundización y vendría a ser el siguiente. Primero habría que hablar de un límite de secciones que si mal no recuerdo en Windows XP es de 96 y en >= Windows Vista es de 0xFFFF, todo cuestion de versión del Loader. Ahora si físicamente te quedas sin espacio porque por ejemplo ya tienes enseguida de la última sección la primera sección del ejecutable.

¿No se pueden agregar más?
Claro que se puede y tienes que tener en cuenta el SizeOfHeaders, lo puedes expandir y seguir agregando secciones. Solo que deberás tener un factor en cuenta, si aumentaste el tamaño ahí deberías arreglar nuevamente los datos de todas las secciones, VirtualAddress y PointerToRawData de cada una.

Esto es todo sobre agregar secciones, practiquen y si tienen dudas para eso estamos, disfrutenlo!, hasta el siguiente tema.


Bueno hablaremos sobre el orden de las secciones en el cuerpo del archivo. Si hemos visto determinada cantidad de archivos ejecutables nos daremos cuenta que en el cuerpo del archivo se preserva el orden en el que están declaradas las secciones.

¿Es necesario que se respete este orden?
No, realmente las secciones en disco pueden estar ubicadas en completo desorden mientras cumplan el requisito de estar bien referenciadas en su declaración (IMAGE_SECTION_HEADER). Me refiero a que todos los punteros deben estar correctos.

¿Por que no afecta el orden de las secciones?
En realidad como mencioné las secciones en disco se ven referenciadas o "apuntadas" por su definición en el IMAGE_SECTION_HEADER, el mapeo en memoria no se verá afectado ya que igual esta mapeando datos que provienen de distintias posiciones en el archivo. Si os preguntáis por qué no se puede cambiar el orden de las secciones en su declaración? En realidad por problemas de fragmentación y garantía, no se puede asegurar si no se escriben en orden posicional no se pisen entre sí.

¿No entiendes lo de desorden?
Bueno espero este gráfico te ilustre un poco:


Si lo llevamos a la parte práctica podríamos sacar las siguientes conclusiones:

  • El orden del IMAGE_SECTION_HEADER no se debe alterar.
  • Tendremos que modificar el orden del contenido de las secciones.
  • Tendremos que actualizar los campos PointerToRawData y SizeOfRawdata de las secciones.

Descar archivo de práctica número #3:
http://dl.dropbox.com/u/26610132/Practica%203.exe

Nuestro archivo:

  • Tiene 3 secciones (.text, .idata y .data).
  • Intercambiaremos .text y .data en el cuerpo del archivo.

Manos a la obra!

  • Primero obtendremos datos de las secciones, recordad lo siguiente: los cambios serán en físico con el hecho de que en memoria el archivo se cargará igual siempre.

    • Sección .text: PointerToRawData: 0x200 SizeOfRawData: 0x200
    • Sección .idata: PointerToRawData: 0x400 SizeOfRawData: 0x200
    • Sección .data: PointerToRawData: 0x600 SizeOfRawData: 0x200
  • Todas las secciones tienen el mismo tamaño, lo cual nos facilitará las cosas.
  • Nuevos datos:

    • Sección .text: PointerToRawData: 0x600 SizeOfRawData: 0x200
    • Sección .idata: PointerToRawData: 0x400 SizeOfRawData: 0x200
    • Sección .data: PointerToRawData: 0x200 SizeOfRawData: 0x200

Declaración de IMAGE_SECTION_HEADER antes:


Declaración de IMAGE_SECTION_HEADER después:


En disco debemos cambiar todos los 0x200 bytes de una sección por otra:

Nueva ubicación sección .text:


Nueva ubicación sección .data

Eso es todo, lo considero uno de esos detallitos que son importantes resaltar. Ya podéis prácticar cualquier duda pregunta!, Hasta el siguiente tema.


Hola chicos, en este nuevo capitulo hablaremos sobre como ampliar la sección de un archivo ejecutable. Requiere todo lo visto previamente, algo de cuidado y solo un poquito de imaginación, eso es todo.

¿Por qué podemos querer ampliar una sección?
Podemos verlo desde distintas perspectivas pero siempre llegando a la conclusión de que nos crearemos un espacio en el archivo. Al agregar una sección agregamos datos en un espacio que nosotros mismos previamente creamos, al ampliar una sección con seguridad queremos meter datos y nuevamente nos estamos haciendo un espacio, solo que ahora es "compartido".

¿Que debemos hacer para ampliar una sección?
Debemos tener claro que ampliaremos el rango de los valores de una sección física y virtualmente. Hay que tener especial cuidado si ampliamos una sección que se encuentra en medio de otras 2, puesto que tendremos que modificar los valores de la siguiente sección para no desalinear el ejecutable.

Ilustración de una sección ampliada:


Descargar archivo de práctica #4:
https://dl.dropbox.com/u/26610132/Practica%204.exe

Manos a la obra!
Ampliaremos las sección .idata 0x150 bytes en el archivo de práctica.

Debemos:

  • Obtener los siguientes valores de la sección que ampliaremos:

    • VirtualSize: 0x98
    • PointerToRawData: 0x400
    • SizeOfRawData: 0x200
  • Si hay una sección posterior a la que ampliaremos obtedremos de dicha sección (.data) los siguientes valores:

    • VirtualAddress: 0x3000
    • VirtualSize: 0x4
    • PointerToRawData: 0x600
    • SizeOfRawData: 0x200
  • Debemos alinear la cantidad de bytes que ampliaremos en base al FileAlignmente: 0x150 Alineado 0x200 : 0x200 y será la cantidad que ampliaremos.
  • Nos ubicamos al final de la sección que ampliaremos: PointerToRawData + SizeOfRawData: 0x600.
  • Añadimos la cantidad de bytes ya caculada.
  • Actualizaremos valores de la sección de la siguiente manera:

    • VirtualSize: Teniendo en cuenta que este tamaño corresponde a los bytes que se mapearán en memoria debemos saber cuanto espacio usaremos. Podemos escribir en el nuevo espacio generado y modificar este campo en base hasta donde queremos que mapee. En este caso pongámoslo a 0x400 para que cubra todos los bytes de la sección.
    • SizeOfRawData: Aumentaremos el valor de bytes alineados que agregamos: 0x200 + 0x200 : 0x400.
  • Debemos actualizar de la sección posterior (si la hay) los siguientes valores:

    • VirtualAddress: Se actualizará unicamente si al sumar VirtualAddress + SizeOfRawData de la sección ampliada el resultado es mayor que el VirtualAddress de esta sección. En nuestro caso no se cumple y no modificamos el valor.
    • PointerToRawData: Se actualizará con el valor resultante de la suma de los valores PointerToRawData + SizeOfRawData de la sección ampliada, en nuestro caso 0x400 + 0x400 : 0x800.
  • Debemos actualizar el SizeOfImage con el valor equivalente a: VirtualAddress + (VirtualSize Alineado a SectionAlignment): 0x3000 + (0x400 Alineado 0x1000 = 0x1000) = 0x4000.

Con esto ya debebemos tener nuestro ejecutable funcionando y totalmente alineado.
Nota: Cuando la sección que se amplíe también este referenciada por el directorio de datos, debes actualizar el tamaño en el mismo.


Nuevos bytes en disco:


Nuevos bytes en memoria:


Descarga archivo resultante (con una pequeña modificación):
https://dl.dropbox.com/u/26610132/Practica%204%20Resultado.exe

Con esto terminamos este capitulo, practiquen y no olviden poner sus dudas, Nos vemos en el próximo.


#12
Código (asm) [Seleccionar]
/*----------------------------------------------------
- Small script for undetect IsDebuggerPresent
- The Swash
- WarScriptZone
------------------------------------------------------*/
exec
mov eax, dword ptr fs:[30]
ende
cmp [eax+2], 1, 1
jnz Exit
MSGYN "Debugger detected, want unable detection?"
mov [eax+2], 0, 1
Exit:
ret


Un saludo ;)
#13
Buenas tardes tegáis vosotros,
Vengo a molestarles con un problema que tengo a la hora de la compilación e instalación del WLAN de mi notebook COMPAQ MINI C10-811LA.

He descargado mi driver de realtek cuyo README dice que para instalarlo hay que usar.
make
make install

Lo extraño es que anteriormente con Ubuntu 10.10 había compilado e instalado perfecto pero con Debian cargo el siguiente drama:

root@personal:/home/ivan/drivers/rtl92ce# make
make -C /lib/modules/2.6.32-5-686/build M=/home/ivan/drivers/rtl92ce modules
make[1]: se ingresa al directorio `/usr/src/linux-headers-2.6.32-5-686'
 CC [M]  /home/ivan/drivers/rtl92ce/base.o
/home/ivan/drivers/rtl92ce/base.c: In function '_rtl_init_mac80211':
/home/ivan/drivers/rtl92ce/base.c:320: error: 'IEEE80211_HW_CONNECTION_MONITOR' undeclared (first use in this function)
/home/ivan/drivers/rtl92ce/base.c:320: error: (Each undeclared identifier is reported only once
/home/ivan/drivers/rtl92ce/base.c:320: error: for each function it appears in.)
/home/ivan/drivers/rtl92ce/base.c: In function 'rtl_watchdog_wq_callback':
/home/ivan/drivers/rtl92ce/base.c:1258: error: implicit declaration of function 'ieee80211_connection_loss'
make[4]: *** [/home/ivan/drivers/rtl92ce/base.o] Error 1
make[3]: *** [_module_/home/ivan/drivers/rtl92ce] Error 2
make[2]: *** [sub-make] Error 2
make[1]: *** [all] Error 2
make[1]: se sale del directorio `/usr/src/linux-headers-2.6.32-5-686'
make: *** [all] Error 2


Busque bastante en google y probé hasta el cansancio distintas soluciones sin éxito.
Uso Debian Squeeze 6.0.0:
Linux personal 2.6.32-5-686 #1 SMP Wed Jan 12 04:01:41 UTC 2011 i686 GNU/Linux

y el dispositivo WLAN es:
Network controller: Realtek Semiconductor Co., Ltd. RTL8188CE 802.11b/g/n WiFi Adapter (rev 01)


Un saludo y gracias por vuestra ayuda.

PD: Instalé la 6.0.0 por el problema con el kernel 2.6.38 y superiores con baterias de laptops.
Encontré algo que no supe interpretar bien pero depronto sea de ayuda:
http://www.spinics.net/lists/linux-wireless/msg78220.html

#14
Scripting / [Python] Little Script Codepad
2 Noviembre 2011, 03:35 AM
Código (python) [Seleccionar]
#------------------------------------------------------------------------------
# Pequeño script de escritorio para utilizar Codepad.org
# Programmer: The Swash
# Website: http://h-sec.org
#------------------------------------------------------------------------------

import urllib, urllib2, re

def GetResponse(lang, code):
    code = urllib.urlencode({'lang':lang, 'code':code,'run':'True','submit':'Submit'})
    web = urllib2.urlopen('http://codepad.org',code)
    source = web.read()

    resp = re.findall('<td width="100%" style="vertical-align: top">\n<div class="highlight">\n<pre>\n([^\b]+)</pre>', source)
    temp = resp[0]
    if re.findall('<a href="#line-[\d]">(.+)</a>', temp):
        err = re.findall('<a href="#line-[0-9]">(.+)</a>', temp)
        val = re.sub('<a href="#line-[0-9]">(.+)</a>', err[0], temp)
        return val
    else:
        return temp

langs = ('Python','C','C++','PHP','Perl','Ruby')
lang = 0
print "Bienvenido, lenguajes disponibles: \n"
length = len(langs)
for i in range(length):
    print str(i+1) + '- ' + langs[i]

while not((ord(str(lang)) >= 49) and (ord(str(lang)) <= 54)):
    print "Elige el numero correspondiente: "
    lang = input()
   
try:
    path = raw_input("Ingrese la ubicacion completa del archivo: ")
    lfile = open(path, "r")
    buff = lfile.read()
    lfile.close()

except:
    print "Error al procesar archivo"
    exit()

Resp = GetResponse(langs[lang-1], buff)
print "Output:\n"
print Resp
raw_input("Presione enter para salir..")


Un pequeño script para gestión con Codepad.
Acepto críticas.

Un saludo.
#15
Scripting / [Python] Goo - Acorta tu URL
24 Octubre 2011, 06:37 AM
Código (python) [Seleccionar]
#----------------------------------------------------------
# Obtener URL acortada mediante http://goo.gl
# Programador: The Swash
# Agradecimientos: Psymera, 11Sep, [Zero] y todo h-sec
# Website: http://h-sec.org
#----------------------------------------------------------

import socket, urllib, re
def GetGooURL(url):
    header = ['POST /api/shorten HTTP/1.1\r\n',
              'Host: goo.gl\r\n',
              'Content-Type: application/x-www-form-urlencoded;charset=utf-8\r\n',
              'Content-Length: 41\r\n',
              'Connection: close\r\n\r\n',
              'URLENCODE']
    if re.match('^http://', url):
        url2 = url
    else:
        url2 = 'http://' + url
    address = socket.gethostbyname('goo.gl')
    link = urllib.urlencode({'url':url2})
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    header[5] = link + '&security_token\r\n'
    length = len(header)
    try:
        sock.connect((address,80))
        for i in range(length):
            sock.send(header[i])
        buff = sock.recv(1024)
    except:
        return 'Error de conexion'
   
    sock.close()
    data = re.findall('Location: (.+)\r\n', buff)
    return data[0]

url = GetGooURL('h-sec.org')
print url
raw_input()


Hola amigos, les traigo este pequeño código que me llevó largo rato por los encabezados HTTP. Como dijo 11Sep puede acortarse mucho usando urllib, pero en definitiva no era mi intención.

Cualquier critica constructiva es bien recibida.

Un saludo.
#16
Programación C/C++ / [C] Listas enlazadas.
15 Octubre 2011, 02:09 AM

Información general:
Las listas enlazadas son un recurso dinámico muy potente que nos permite realizar tareas que generalmente podríamos requerir con arrays, pero se impide en objetos estáticos y en dinámicos sería muy complicado.
Una lista enlazada se basa en una estructura, la cual será el esqueleto o prototipo del contenido, y al final requerirá tener un puntero hacia la siguiente estructura del mismo tipo, es decir están enlazadas por su ubicación (dirección de memoria).


Funcionamiento y estructura:
Primero debemos tener la estructura o prototipo en el cual definiremos los datos que emplearemos y como debe ser, un puntero a otra estructura del mismo tipo:

Código (cpp) [Seleccionar]
typedef struct _nodo
{
    int valor;
    struct _nodo * pNext;
}_Nodo;


Utilizamos typedef para evitar estar utilizando struct _nodo para todo, así abreviamos y hacemos el código más legible.
Código (cpp) [Seleccionar]
typedef _Nodo * _pNodo;

Hay unas bases a tener en cuenta para trabajar con listas enlazadas:

  • El final de una lista será determinada por un puntero con valor NULL, es decir el último elemento tendrá como siguiente elemento a NULL.
  • Los elementos se pueden recorrer en un solo sentido (Inicio - Final), debido a que solo tenemos un apuntador al siguiente y no al anterior, las listas que cuentan con esta opción se conocen como doblemente enlazadas. Las trataremos en otro tema.
  • Es muy importante mantener siempre el valor inicial de la lista, en caso de perderle sería muy difícil de recuperar.
  • Es muy importante controlar muy bien los punteros hacia los elementos, un simple número distinto y podríamos causar perdida de control sobre el programa.

Recordemos, cada elemento tiene un apuntador al siguiente, por ello se llaman enlazados:



Para trabajar con listas, deberemos implementar una serie de funciones y procedimientos para el manejo de sus elementos entre ellas:

  • Crear lista nueva.
  • Insertar elemento (Al inicio, al final y posterior al otro elemento).
  • Buscar elemento.
  • Eliminar elementos(El primer elemento, un elemento en base a su dirección).
  • Imprimir contenido de listas (Este uso ya depende del usuario).

Creación de una lista nueva:
Para crear una nueva lista teniendo en cuenta el prototipo lo que utilizaremos son punteros, por lo cual suele ser más cómodo utilizar un typedef para más comodidad. En cuanto a teoría para crear una nueva lista deberíamos:

  • Crear una función cuyo tipo de valor de retorno será el mismo del prototipo.
  • La función creará una estructura dinámica con el tamaño del prototipo (malloc).
  • Se establecerá un valor inicial para los elementos de la estructura.
  • El apuntador al siguiente elemento será NULL, esto identificará la lista como vacía.
  • La función retornará la dirección de la lista creada (valor retornado por malloc).
Código (cpp) [Seleccionar]
_pNodo CrearLista(int valor)
{
    _pNodo Lista;

    Lista = (_pNodo) malloc (sizeof(_Nodo));
    Lista->valor = valor;
    Lista->pNext = NULL;

    return Lista;
}


Inserción de elementos:
Para insertar nuevos elementos deberemos tener una lista previamente creada y contar con su referencia para acceder a ella, además se deberán hacer múltiples comparaciones con fines de prevenir errores, como cuando la lista está vacía, o el lugar donde se va a ingresar el nuevo elemento, etc.

Insertar elemento al final:

  • La función requerirá el valor del elemento a ingresar y el inicio de la lista.
  • Crear un nuevo prototipo de estructura, lo llamaremos Nodo.
  • Comprobar si la lista está vacía, en tal caso simplemente modificar la dirección a la que apunta por el nodo creado (NULL x Dirección nuevo Nodo). En caso de no estar vacía deberemos recorrer todos los elementos hasta reconocer al que apunta al NULL y editar por la dirección del nuevo Nodo.
  • En caso de recorrer la lista no olvidar utilizar una variable auxiliar para no perder la lista principal.
  • Al ser un elemento que va al final, estará obligado a tener su campo de siguiente estructura a NULL.
  • En mi caso bajo utilice la idea de retornar la dirección del nuevo elemento insertado, muchos códigos retornan la misma lista ingresada, cuando en realidad esta no sufre modificaciones y no es útil.
Código (cpp) [Seleccionar]
_pNodo InsertarElementoAlFinal(int valor, _pNodo ListaInicial)
{
    _pNodo NuevoNodo;
    _pNodo Auxiliar = ListaInicial;
    NuevoNodo =  malloc(sizeof(_Nodo));

    NuevoNodo->valor = valor;
    NuevoNodo->pNext = NULL;

    if (ListaInicial->pNext == NULL)
    {
        ListaInicial->pNext = NuevoNodo;
    }
    else
    {
        while(Auxiliar->pNext != NULL)
        {
            Auxiliar =  Auxiliar->pNext;
        }
        Auxiliar->pNext = NuevoNodo;
    }

    return NuevoNodo; /* Retornamos dirección del elemento insertado */
}


Inserción de elementos al principio:

  • La función requerirá el valor del elemento a ingresar y el inicio de la lista.
  • Crear un nuevo Nodo, asignar el valor correspondiente.
  • El valor del campo siguiente elemento del Nodo creado deberá ser correspondiente al valor principal de la lista.
  • Retornamos el nuevo inicio de lista, correspondiente al nuevo Nodo.
Código (cpp) [Seleccionar]
_pNodo InsertarElementoAlInicio(int valor, _pNodo ListaInicial)
{
    _pNodo NuevoNodo;
    NuevoNodo = malloc(sizeof(_Nodo));
    NuevoNodo->valor = valor;
    NuevoNodo->pNext = ListaInicial;

    return NuevoNodo; /* Retornamos nueva lista inicial */
}


Inserción de un elemento posterior a otro:

  • La función requerirá el valor del elemento a ingresar y la dirección del elemento anterior a donde ingresaremos el nuevo.
  • Creamos el nuevo nodo y asignamos los valores correspondientes.
  • El nuevo Nodo creado ahora apuntará al elemento que apuntaba el Nodo anterior a este.
  • El Nodo anterior apuntará al nuevo Nodo insertado.
  • Retornamos la dirección del nuevo Nodo.
Código (cpp) [Seleccionar]
_pNodo InsertarElementoPosterior(int valor, _pNodo ElementoAnterior)
{
    _pNodo NuevoNodo;
    NuevoNodo = malloc(sizeof(_Nodo));

    NuevoNodo->valor = valor;
    NuevoNodo->pNext = ElementoAnterior->pNext;

    ElementoAnterior->pNext = NuevoNodo;

    return NuevoNodo; /* Retornamos dirección del elemento insertado */
}


Eliminación de elementos:
La eliminación de elementos también es una función muy importante a la hora de trabajar con listas, sus implementaciones pueden ser muchas debido a la gran cantidad de casos posibles, como eliminar el primer o último elemento, eliminar un elemento según su dirección, posterior a otro, o buscando por valor (Eliminar primero, último o todos). Yo mostraré 2 casos, eliminando el primer elemento y eliminando por dirección del elemento.

Eliminación del primer elemento:

  • Para esta función únicamente necesitaremos el inicio de lista.
  • Usaremos una variable auxiliar la cual nos ayudará a almacenar datos temporalmente.
  • Comprobamos si la lista está vacía, en tal caso dejamos todo igual.
  • Almacenamos el elemento inicial de lista en la variable auxiliar.
  • Ahora el inicio de lista apuntará tendrá como valor el elemento al cual apuntaba.
  • Liberamos el espacio de memoria que contiene la variable auxiliar con free().
Código (cpp) [Seleccionar]
_pNodo EliminarPrimerElemento(_pNodo Lista)
{
    _pNodo Auxiliar;
    Auxiliar = Lista;

    if (Auxiliar->pNext == NULL)
    {
        return Lista; /* Si no hay más elementos dejamos todo igual */
    }
    Lista = Auxiliar->pNext;
    free(Auxiliar);

    return Lista; /* Retornamos la nueva base de la lista */
}


Eliminar elemento por su dirección:

  • Necesitaremos inicio de lista y dirección del elemento a eliminarla.
  • Utilizamos una variable auxiliar para buscar el elemento anterior al elemento a eliminar recorriendo toda la lista.
  • En caso de no encontrar el elemento comparando su dirección retornamos 0 (FALSE)
  • Comprobamos si el elemento a eliminar es el último, en tal caso el elemento anterior apuntará a NULL, de lo contrario el elemento anterior al que eliminamos apuntará al elemento que apuntaba el elemento que eliminamos.
  • Liberamos la memoria del elemento a eliminar.
  • Retornamos 1(TRUE).
Código (cpp) [Seleccionar]
int EliminarElemento(_pNodo Elemento, _pNodo Lista)
{
    _pNodo Auxiliar;
    Auxiliar = Lista;
    while (Auxiliar != NULL)
    {
        if (Auxiliar->pNext == Elemento)
        {
            break;
        }
        Auxiliar = Auxiliar->pNext;
    }
    if (Auxiliar == NULL)
    {
        return 0;
    }
    else
    {
        if (Elemento->pNext == NULL)
        {
            Auxiliar->pNext = NULL;
        }
        else
        {
            Auxiliar->pNext = Elemento->pNext;
        }

        free(Elemento);
        return 1;
    }
}


Búsqueda de elementos:
La búsqueda de elementos generalmente se realiza para localizar la posición de un objeto comparando su valor, ya que si se tiene su dirección simplemente haciendo referencia podríamos acceder a su contenido.

Búsqueda por valor:

  • Necesitaremos el valor a buscar y el inicio de lista.
  • Utilizaremos una variable auxiliar para no perder el inicio de la lista.
  • Recorremos toda la lista y vamos comparando si cada elemento es igual al buscado.
  • Una vez localizado simplemente retornamos la dirección del elemento.
  • Si no se lo encuentra se retornará NULL.
Código (cpp) [Seleccionar]
_pNodo BuscarElemento(int valor, _pNodo Lista)
{
    _pNodo Auxiliar;

    Auxiliar = Lista;
    while(Auxiliar != NULL)
    {
        if (Auxiliar->valor == valor)
        {
            break;
        }
        Auxiliar = Auxiliar->pNext;
    }
    return Auxiliar; /* Retornamos dirección del elemento encontrado */
}


Bueno, espero hayan comprendido el articulo y prometo trabajar más estructuras de datos.
Hasta la próxima.

Saludos.
#17
Buenas noches,
Creo que a Zero le había comentado de mi idea de darle una pequeña variación al cifrado ROT común.

Idea:

  • Utilizar una contraseña numérica con la cual se hará la rotación.
  • Se operará en bloques igual a la longitud de números de la contraseña.
  • Individualmente actuará cada número a la hora de cifrar.
  • Si el dígito actual es menor que 5 se suma, de lo contrario se resta.
  • El tercer parámetro es para evitar prácticamente replicar la función para descifrar.

Les dejo un pequeño ejemplo, lo pueden adaptar y optimizar. Si quieren adaptarlo a binarios deberán añadir comprobación del límite ASCII y no usar strlen.

Código (cpp) [Seleccionar]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * ROTPassword(char * String, int password,int descifrar);


int main()
{
    printf("%s ", ROTPassword("hsec",152,0));
    printf("%s ", ROTPassword("jnfe",152,1));
    getchar();
    return 0;
}

char * ROTPassword(char * String, int password, int descifrar)
{
    int array[10] = {0};
    int passcopy = password, counter = 0,i,strlength, passlength = 0;
    char * cifrado;

    strlength = strlen(String);
    while(passcopy >= 1)
    {
        array[counter] = (passcopy % 10);
        passcopy /= 10;
        counter++;
    }

    cifrado = (char*) malloc(strlength+1);
    memset(cifrado,0,strlength+1);

    for (i = 0; i < strlength; i++)
    {
        if (array[passlength] < 5)
        {
            (descifrar == 1)?cifrado[i] = String[i] - array[passlength]: (cifrado[i] = String[i] + array[passlength]);
        }
        else
        {
            (descifrar == 1)?cifrado[i] = String[i] + array[passlength]: (cifrado[i] = String[i] - array[passlength]);
        }
        passlength++;
        if (passlength >= counter) passlength = 0;

    }

    return cifrado;
}


Un saludo, Gracias Zero.
#18
Código (asm) [Seleccionar]
.386
.model flat, stdcall
option casemap:none

include C:\masm32\include\windows.inc
include C:\masm32\include\kernel32.inc
includelib C:\masm32\lib\kernel32.lib

.data
ProcessId        dd 0
ProcessProtect   dd 0
hProcess         dd 0
APIAddress       dd 0
SnapshotHandle   dd 0
DistanceFunc     dd 0
fAddress         dd 0
Bytesw           dd 0
_JMP             db 5 dup(?)
Diference        dd 0
Buff             db 0
_PROCESSENTRY32  PROCESSENTRY32 <?>
Process          db "taskmgr.exe",0   ;Process to Hook
API              db "OpenProcess",0
lLibrary         db "kernel32.dll",0
Protect          db "notepad.exe",0   ;Process to Protect

.code
start:
mov dword ptr[_PROCESSENTRY32.dwSize], 0128h

_Begin:
invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
mov dword ptr[SnapshotHandle],eax

_Cmp:
    invoke Process32Next,dword ptr[SnapshotHandle], addr _PROCESSENTRY32
    mov edi, eax
    invoke lstrcmp,addr Process, addr _PROCESSENTRY32.szExeFile
    or eax, eax
    jz _GetPID2
    invoke lstrcmp,addr Protect, addr _PROCESSENTRY32.szExeFile
    or eax, eax
    jz _GetPID

_Continue:   
    or edi, edi
    jz _Exit
    jnz _Cmp
   
_Proc:   
    invoke GetModuleHandle, addr lLibrary
    invoke GetProcAddress, eax, addr API
    mov dword ptr[APIAddress], eax

    mov eax, offset _EndHook
    mov ebx, offset _Hook
    sub eax, ebx
    mov dword ptr[DistanceFunc], eax

    invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dword ptr [ProcessId]
    mov dword ptr [hProcess], eax
    invoke ReadProcessMemory,dword ptr[hProcess], dword ptr [APIAddress], addr Buff, 1, addr Bytesw
    cmp byte ptr [Buff], 0E9h
    jz _Exit
    invoke VirtualAllocEx,dword ptr [hProcess],NULL,dword ptr[DistanceFunc],MEM_RESERVE or             MEM_COMMIT,PAGE_EXECUTE_READWRITE
    mov dword ptr [fAddress], eax
    mov ecx, offset _Hook
    invoke VirtualProtect,ecx,10,PAGE_EXECUTE_READWRITE,addr Bytesw
    mov ebx, dword ptr[APIAddress]
    add ebx, 5
    mov dword ptr[_Hook + 1], ebx
    mov ebx, dword ptr[ProcessProtect]
    mov dword ptr[_Hook + 6], ebx
    mov ecx, offset _Hook
    invoke WriteProcessMemory,dword ptr[hProcess], dword ptr [fAddress], ecx, dword ptr [DistanceFunc], addr Bytesw
    invoke VirtualProtectEx,dword ptr[hProcess],dword ptr [APIAddress], 5, PAGE_EXECUTE_READWRITE, addr Bytesw
    mov byte ptr [_JMP], 0E9h
    mov edx, dword ptr [fAddress]
    add dword ptr [APIAddress],5
    sub edx, dword ptr [APIAddress]
    mov dword ptr [_JMP +1], edx
    sub dword ptr [APIAddress], 5
    invoke WriteProcessMemory,dword ptr [hProcess], dword ptr[APIAddress], addr _JMP, 5, addr Bytesw
    invoke CloseHandle, dword ptr [hProcess]

_Exit:
    invoke ExitProcess,0

_Hook:
    mov eax, 00000000h ; API Address
    mov ecx, 00000000h ; PID
   
    push ebp           ; Stack frame
    mov ebp, esp
   
    pushad
    cmp ecx, dword ptr [ebp + 10h]
    jz _Hooked                     ; If is equal jump to Hooked
    popad                          ; Restaure registers
    jmp eax                        ; Jump to API + 5

_Hooked:
    popad
    mov esp, ebp
    pop ebp
    mov eax, 0
    retn 0Ch
_EndHook:   

_GetPID:
    mov eax, dword ptr [_PROCESSENTRY32.th32ProcessID]
    mov dword ptr[ProcessProtect],eax
    jmp _Found

_GetPID2:
    mov eax, dword ptr [_PROCESSENTRY32.th32ProcessID]
    mov dword ptr[ProcessId],eax
    jmp _Cmp2

_Found:
    cmp [ProcessId],0
    jz _Cmp
    jmp _Cmp2

_Cmp2:
    cmp dword ptr[ProcessProtect],0
    jnz _Proc
    jmp _Cmp

end start


Información:
Este es el pequeño ejemplo de enganchar(Hookear) a la función Kernel32.OpenProcess la cual permite abrir un proceso por muchos motivos (Cerrarlo, obtener información, modificar, etc).

¿Que hace exactamente?
Sencillamente enganchamos esa función y así podemos verificar si quieren abrir el proceso que nosotros designemos a proteger.

Ustedes pueden hacerle su respectiva adaptación a condiciones etc, pero me enfoque en un ejemplo y en aprender.

Mis mayores agradecimientos a Lelouch (Como me soportaste xD) y a [Zero].
Dedicado a todos mis mentores :P (Sobra mencionarlos)
Saludos.

#19

Información:
Este documento trata de explicar la mayor parte de la estructura de los archivos ejecutables de Windows, esta basado en la información oficial de microsoft y su ventaja es que esta en lengua española bien graficado y explicado.

Descarga - Lectura online:
http://www.box.net/shared/4156t5rfv8tr5v4bgo19
#20
Que tal amigos, les traigo un pequeño tutorial que me quedo algo corto porque no me pude extender más en el tema pero traté de explicarlo lo mejor posible.
Espero les guste.

Link:
http://www.box.net/shared/v9pcb3bzzv
#21
Hola amigos, después de exactamente una semana vengo con otro documento que le tenía ganas y lo que más satisfacción me dio fue el código en ensamblador en el cual tardé 2 días pero bueno.
Espero les guste y hasta la próxima.

The Swash

Link:
http://www.box.net/shared/0alan9bock

Un saludo y agradecimientos especiales a [Zero]  ;)
#22
Que tal amigos, he leído un poco acerca del tema y haciendo pruebas logré instalar una rutina en el TLS Callbacks y quise compartirlo, espero sus críticas opiniones y recomendaciones.
Espero me disculpen si hay errores técnicos, Un saludo.

PD: Quiero agradecer a trompetin17evony y apokliptiko por sus recomendaciones.

Link:
http://www.box.net/shared/h0ra1953cn
#23
Código (ASM) [Seleccionar]
.386
.model flat, stdcall
option casemap:none
assume fs:nothing

.data
GPA db "GetProcAddress",0
Cont dd 0

.code
start:
mov eax, fs:[030h]    ; Get pointer of the PEB
mov eax, [eax + 0ch]  ; Get pointer of PPEB_LDR_DATA
mov eax, [eax + 0ch]  ; Get pointer of InLoadOrderModuleList
mov eax, [eax]        ; Get InLoadOrderModuleList of next library "ntdll"
mov eax, [eax]        ; Get InLoadOrderModuleList of next library "kernel32"
mov eax, [eax + 018h] ; Get BaseAddress of "kernel32"

mov ecx, dword ptr[eax + 03ch]   ; Set PE Offset
add ecx, 078h                    ; Set in DirectoryTable[0]
mov edx, dword ptr [eax + ecx]   ; Get Export Table RVA
add edx, eax                     ; Add KernelBase Address
xor ebx, ebx                     ; Clean EBX
add edx, 020h                    ; Set in addressofnames RVA
mov ebx, dword ptr [edx]         ; Get RVA AddressOfNames Table
add ebx, eax                     ; Add KernelBase Address

COMP:                   ; Rutine of compare strings with "GetProcAddress", incrementing Cont
add ebx, 4
inc [Cont]
mov esi, dword ptr [ebx]
add esi, eax
lea edi, [GPA]
mov ecx, 0Eh
repe cmpsb
jnz COMP

;GetAddress
xor ebx, ebx            ; Clean EBX
add edx, 04h            ; Set on Table Ordinal RVA
mov ebx, dword ptr[edx] ; Get first RVA of Ordinal
add ebx, eax            ; Add KernelBase Address
mov edi, eax            ; Save KernelBase Address in EDI
xor eax, eax            ; Clean EAX
mov al, 02h             ; Base of WORD
mov esi, edx            ; Save Address of RVA Ordinal Table
mul word ptr[Cont]      ; Mul Cont for get WORD
mov [Cont], eax         ; Get new value in Cont
xor eax, eax            ; Clean EAX
add ebx, [Cont]         ; Add Cont to Address of Ordinal Table
mov ax,word ptr[ebx]    ; Get Ordinal of GetProcAddress
sub esi, 08h            ; Set in AddressOfFunctions
mov ecx, [esi]          ; Get First pointer to Functions RVA
add ecx, edi            ; Add KernelBase Address
xor ebx, ebx            ; Clean EBX
mov ebx, eax            ; Mov Ordinal to EBX for MUL
mov eax, 04h            ; Base of DWORD
mul ebx                 ; Calcule spaces to Get address bassed in (Address of First Function + Ordinal GetProcAddress
add ecx, eax            ; Add spaces for Set Address in RVA of GetProcAddress
mov ecx, [ecx]          ; Get RVA of GetProcAddress
add ecx, edi            ; Add KernelBase Address
end start


Agradecimientos a Shaddy, [Zero], Lelo, Thor, Psymera & todos los que me han ayudado.
#24
Código (asm) [Seleccionar]
mov eax, fs:[030h]
mov eax, [eax + 0ch]
mov eax, [eax + 0ch]
mov eax, [eax]
mov eax, [eax]
mov eax, [eax + 018h]


Bueno leyendo un poco acerca de la PEB y entendiendo como localizaban el BaseAddress de kernel32, recordé que había un código que hicieron rehicieron y mejor dicho xD, bueno ese código dejo de funcionar en 7 donde se agrego Kernelbase.dll y obligó a cambiar el código. Tras pruebas mi código se baso en buscar el orden de carga de las librerías, y ese orden se respeta desde XP hasta 7 tanto en 64 como 32 bits. ;)

Un agradecimiento a Lord, y ya implementaré un método genérico  :P.
Saludos!
#25
/*
  -----------------------------------------------------------
  - Function: RealignPE v2                                  -
  - Programmer: The Swash                                   -
  - Web: http://www.h-sec.org                               -
  - Dedicated: Thor, Psymera, Steve10120, [Zero], Karcrack  -
  -----------------------------------------------------------
*/
 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define ReadWriteBinary "r+b"

int AlingNum(int num, int aling);
char * BytesAling(int number);

int main(void)
{
    printf("%i ",RealignPE("C:\\hi.exe"));
    getchar();

}

int RealignPE(char * lpFile)
{
    IMAGE_DOS_HEADER IDH;
    IMAGE_FILE_HEADER IFH;
    IMAGE_OPTIONAL_HEADER IOH;
    IMAGE_SECTION_HEADER ISH;

    DWORD PESignature = 0;
    FILE * lFile;
    int OriSize = 0;
    int ActSize = 0;
    int Alingned = 0;

    lFile = fopen(lpFile,ReadWriteBinary);
    if (lFile == NULL) {return -1;}
    else
    {
        fread(&IDH, 64, 1, lFile);
        fseek(lFile, IDH.e_lfanew , SEEK_SET);
        fread(&PESignature, 4, 1, lFile);
        if (IDH.e_magic != IMAGE_DOS_SIGNATURE) {fclose (lFile); return -2;}
        else
        {
            if(PESignature != IMAGE_NT_SIGNATURE) {fclose (lFile); return -3;}
            else
            {

                fseek(lFile, IDH.e_lfanew + 4, SEEK_SET);
                fread(&IFH, sizeof(IFH), 1, lFile);
                fseek(lFile, IDH.e_lfanew + 4 + sizeof(IFH), SEEK_SET);
                fread(&IOH, IFH.SizeOfOptionalHeader, 1, lFile);
                fseek(lFile, IDH.e_lfanew + 4 + sizeof(IFH) + IFH.SizeOfOptionalHeader + (sizeof(ISH)*(IFH.NumberOfSections-1)),SEEK_SET);
                fread(&ISH, sizeof(ISH), 1, lFile);
                fseek(lFile, 0, SEEK_END);
                ActSize = ftell(lFile);
                OriSize = ISH.PointerToRawData + ISH.SizeOfRawData;
                if (ActSize - OriSize > 0)
                {
                    Alingned = AlingNum(ActSize - OriSize, IOH.FileAlignment);
                    ISH.SizeOfRawData += Alingned;
                    ISH.Misc.VirtualSize += Alingned;
                    IOH.SizeOfImage = ISH.Misc.VirtualSize + ISH.VirtualAddress;
                    IOH.SizeOfInitializedData += Alingned;
                    if (ISH.VirtualAddress == IOH.DataDirectory[2].VirtualAddress)
                    {
                        IOH.DataDirectory[2].Size += Alingned;
                    }
                    fseek(lFile, IDH.e_lfanew + 4 + sizeof(IFH), SEEK_SET);
                    fwrite(&IOH, 1, IFH.SizeOfOptionalHeader, lFile);
                    fseek(lFile, IDH.e_lfanew + 4 + sizeof(IFH) + IFH.SizeOfOptionalHeader + (sizeof(ISH)*(IFH.NumberOfSections-1)),SEEK_SET);
                    fwrite(&ISH, 1, sizeof(ISH), lFile);
                    if (Alingned - (ActSize - OriSize) > 0)
                    {
                       fseek(lFile, ActSize, SEEK_SET);
                       fwrite(BytesAling(Alingned-(ActSize - OriSize)), 1, Alingned-(ActSize - OriSize), lFile);
                    }
                    return 0;
                }
                else {return 1;}
            }
        }
    }
}


int AlingNum(int num, int aling)
{
    if(num % aling == 0)
    { return num; }
    else if(num < aling)
    { return aling; }
    else { return (num / aling) * aling + aling; }
}

char * BytesAling(int number)
{
     char * sTemp = (char *) malloc(number + 1);
     int i;
     for (i=0; i<number; i++)
     {
         sTemp[i] = '\0';
     }
     return sTemp;
}


Bueno amigos, ya había trabajado en la versión 1 de esta funcion, la mejore mucho en cuanto al código y lo mejor que corregí los fallos que tenía!
Saludos
#26
Programación C/C++ / [C] PEFileSize function
25 Enero 2011, 05:58 AM
/*
   [Get size of file to base of PE]
   - Programmer: The Swash
   - Dedicated: Zero, Thor Psymera, Steve10120
*/

#include <windows.h>
#include <stdio.h>
#define RB "rb"

int PEFileSize(char * fPath);


int main(void)
{
    printf("File size: %i", PEFileSize("C:\\test.exe"));
    getchar();
}

int PEFileSize(char * fPath)
{
    IMAGE_DOS_HEADER IDH;
    IMAGE_NT_HEADERS INH;
    IMAGE_SECTION_HEADER ISH;
    FILE * lpFile;
    int sTemp = 0, i;
   
    lpFile = fopen(fPath,RB);
    if (lpFile != NULL)
    {
               fseek(lpFile, 0, SEEK_SET); // Seek to begin of file
               fread(&IDH, sizeof(IDH), 1, lpFile); // Read 64 bytes to IDH struct
               if (IDH.e_magic == IMAGE_DOS_SIGNATURE) // If IDH.e_magic = (MZ)
               {
                               fseek(lpFile, IDH.e_lfanew, SEEK_SET); // Seek in file in begin of NT Headers (PE)
                               fread(&INH, sizeof(INH), 1, lpFile); // Read in structure 248 bytes
                               if (INH.Signature == IMAGE_NT_SIGNATURE) // If INH.Signature = (PE)
                               {
                                                 for (i = 0; i < INH.FileHeader.NumberOfSections; i++) // go for all sections
                                                 {
                                                     fseek(lpFile, IDH.e_lfanew + sizeof(INH) + sizeof(ISH)*i, SEEK_SET); // Seek in actual section
                                                     fread(&ISH, sizeof(ISH), 1, lpFile); // Read section
                                                     sTemp += ISH.SizeOfRawData; // Save sizeofrawdata of section
                                                 }
                                                 sTemp += INH.OptionalHeader.SizeOfHeaders;
                                                 fclose(lpFile);
                                                 return sTemp;
                               }
               }
               else
               {
                   return -1;
               }
    }
    else
    {
        return -1;
    }
}


Que tál mis amigos, bueno estudiando el formato PE digamos que se me paso esta idea por la cabeza y no era tan dificil, lo que hace el código es obtener el tamaño original del archivo generado por el tamaño de las secciones del ejecutable + su cabecera.

Espero les sea de utilidad!
#27
#include <stdio.h>

int main()
{

    int D = 0;

    if (D == 0)
    {

        printf("etapa 1");
        if (D == 0)
        {
                     
                     printf("etapa 2");

                     if (D == 0)
                     {
                           printf("etapa 3");

                           while (D <= 6);
                           {
                              D++;
                                                         
                           }
                           printf("etapa 5");
                                                   
                     }
                               
         }

    }
}


Hola que tal a todos los usuarios, me tope con algo muy estraño haciendo un PE Reader, Lord y yo nos quedamos sin saber causa..
No es compilador mío.
http://codepad.org/bNsMr5Z7

Juzguen y cuentenos, BUG de C?
Este mismo código probado en delphi no falla.

Saludos
#28
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* @autor:     The Swash
   @function:  IntToStr - StrToInt
   @language:  ANSI C
*/
   
int StrToInt(char * string);
char * IntToStr(int number);

int main()
{
    printf("char: %s \n",IntToStr(123));
    printf("int: %i",StrToInt("123"));
    return 0;
}



int StrToInt(char * string)
{
    int i, n, temp = 0;
    for (i = 0; i < strlen(string); i++)
    {
        if (  ( (int)string[i]< 48 ) || ( (int)string[i]>57 )  ) // Si el caracter es distinto a un numero
        {
            return -1; //Salimos y retornamos -1
        }
        else
        {
            for (n = 48; n <= 57; n++) // Hacemos un bucle desde el numero 0 al 9 basandonos en su valor ASCII
            {
                if (string[i] == n) // Si el valor ASCII del caracter actual correspondi al valor ASCII de un numero
                {
                    temp += (string[i] - 48); // Obtiene y suma el número actual al buffer
                    temp *= 10; // Aumenta una cifra al resultado
                }
            }
        }
    }
    return temp / 10; // Retorna el buffer, quitandole la última cifra que sobra
}



char * IntToStr(int number)
{
    int num, len = 0, i = 0, altnumber = number;
    char * buffer;
    if (number == 0)
    {
        return "0";
    }
    else
    {
        while (number > 0)
        {
           num = number%10;
           number = number / 10;
           len++;
        }
        buffer = (char *) malloc (len);
        memset(buffer,0,strlen(buffer));
        num = 0;
        i = len -1;
        while (altnumber> 0)
        {
           num = altnumber%10;
           altnumber = altnumber / 10;
           buffer[i] = (num + 48);
           i--;
        }
        return buffer;
    }


}


Bueno chicos, estaba aprendiendo ejecucion de una aplicacion con parametros por consola, y me surgió la necesidad de convertir tipos, me sirvió itoa y atoi pero no son standares, así que decidí hacer mis propias funciones a pura cabeza.
Linkgl dedicado para vos =).
Espero les sea de utilidad.

PD: Gracias osnaraus por explicarme el pequeño detalle

Saludos.
#29
Programación C/C++ / [C] StrReverse - Pos
6 Enero 2011, 00:57 AM
Hola, que tal.. Algunas necesidades me han llevado a hacer unas pequeñas funciones que quizás les lleguen a ser de utilidad.

Pos [Sirve para buscar una subcadena en una cadena y retornar el punto donde empieza]

/*  @autor : The Swash
    @EOF Writer
    @purpose: Find string in other string
*/
int Pos(char * str, int lenstr, char * substr, int lensubstr)
{
    int i=0;
    for (i = 0; i < lenstr ; i++)
    {
        if (memcmp(str + i, substr,lensubstr)==0)
        {
            return i;
        }
    }
    return 0;
}


La particularidad de esta función y misma diferencia con strcspn es que funciona sin ignorar caracteres nulos, muy util para el trabajo con archivos.

StrReverse [Regresa una cadena en orden inverso al original]
char * StrReverse(char * string, int size){
     int j , n=0;
     char * temporal;
     
     temporal = (char *) malloc(size);
     for (j = size-1 ; j >= 0 ; j--) {
         temporal[n] = (char) (int) string[j];
         n++;
         }
     return temporal;
}


Se pide como parametro la longitud de la cadena, especialmente cuando se trabaja con archivos binarios. Si no pasar como parametros strlen(string).

Saludos, espero a alguien le sea de utilidad!
#30
Option Explicit
'----------------------------------------------------------------------------------------
' Module     : TerminateProcessByName
' Purpose    : Finalize a process by name
' Author     : The Swash
' References : API-Guide and MSDN
' DateTime   : 10/04/2010
' Dedicated  : Karcrack, Cobein And Hacker_Zero
'----------------------------------------------------------------------------------------
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
Private Declare Function Process32First Lib "kernel32" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function OpenProcess Lib "Kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

'Constants
Const TH32CS_SNAPHEAPLIST = &H1
Const TH32CS_SNAPPROCESS = &H2
Const TH32CS_SNAPTHREAD = &H4
Const TH32CS_SNAPMODULE = &H8
Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
Const TH32CS_INHERIT = &H80000000
Const MAX_PATH As Integer = 260
Const PROCESS_ALL_ACCESS = &H1F0FFF
Const STILL_ACTIVE = &H103

'Type PROCESSENTRY32
Private Type PROCESSENTRY32
    dwSize As Long
    cntUsage As Long
    th32ProcessID As Long
    th32DefaultHeapID As Long
    th32ModuleID As Long
    cntThreads As Long
    th32ParentProcessID As Long
    pcPriClassBase As Long
    dwFlags As Long
    szExeFile As String * MAX_PATH
End Type

Public Function TerminateProcessByName(ByVal sProcess As String) As Long
Dim hCTHS As Long
Dim hProc As PROCESSENTRY32
Dim hBase As Long
Dim sBuff As String
Dim hPID As Long
Dim hOpen As Long
Dim hGECP As Long
Dim hTerminate As Long

hCTHS = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0&)
hProc.dwSize = Len(hProc)
hBase = Process32First(hCTHS, hProc)

Do While hBase
   sBuff = Left(hProc.szExeFile, GetLongString(hProc.szExeFile))
   If InStr(1, sBuff, sProcess, vbTextCompare) > 0 Then hPID = hProc.th32ProcessID
   hBase = Process32Next(hCTHS, hProc)
Loop

Call CloseHandle(hCTHS)

If hPID > 0 Then
   hOpen = OpenProcess(PROCESS_ALL_ACCESS, 0, hPID)
   hGECP = GetExitCodeProcess(hOpen, 0&)
   hTerminate = TerminateProcess(hOpen, hGECP)
   If hTerminate <> 0 Then
     TerminateProcessByName = 1
     Else
     TerminateProcessByName = 0
   End If
End If

Call CloseHandle(hOpen)
 
End Function

'Get Long of string
Public Function GetLongString(ByVal sData As String) As Long
If InStr(1, sData, Chr(0)) > 0 Then
   GetLongString = InStr(1, sData, Chr(0)) - 1
   Else
   GetLongString = Len(sData)
End If
End Function


Call:
Call TerminateProcessByName("msnmsgr.exe")

Con este modulo podemos finalizar procesos solo con su nombre =D de manera sencilla.
Provado en Windows XP Service Pack 3

Agradecimientos a Hacker_Zero por ayudarme a solucionar un error logico =P
#31
Option Explicit
'--------------------------------------------------------------------------------------------
' Function : FiletoString
' Coder     : The Swash
' References And Constans : API-Guide
' DateTime : 08/04/2010
'--------------------------------------------------------------------------------------------

'Shlwapi.dll
Private Declare Function PathFileExistsA Lib "shlwapi.dll" (ByVal pszPath As String) As Long

'Kernel32.dll
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CreateFileA Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long

'Constants
Const FILE_SHARE_READ = &H1
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const FILE_SHARE_WRITE = &H2

Public Function FiletoString(sFile As String) As String
Dim hFile    As Long
Dim hFSize   As Long
Dim bvBuff() As Byte
Dim hBytes   As Long
Dim hRead    As Long

If PathFileExistsA(sFile) > 0 Then
 hFile = CreateFileA(sFile, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0, 0)
 If hFile > 0 Then
  hFSize = GetFileSize(hFile, 0)
  ReDim bvBuff(1 To hFSize)
  hRead = ReadFile(hFile, bvBuff(1), UBound(bvBuff), hBytes, 0&)
  If hRead > 0 Then
   FiletoString = StrConv(bvBuff, vbUnicode)
  End If
 End If
End If

Call CloseHandle(hFile)

End Function


Call:
Dim sFile As String
sFile = FiletoString(File path)


Disculpen por la descripcion xD, esta funcion permite obtener las strings de un ejecutable, usado mucho en el mundo del malware pero tambien se puede usar para muchas otras cosas :D

#32
'-----------------------------------------------------------
' Function : [GetTitleActiveApp]
' Type     : [SNIPPET]
' Autor    : [The Swash]
' DateTime : [31/03/2010]
'-----------------------------------------------------------
Option Explicit

'User32 Lib Apis
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long

'SendMessage Constants
Const WM_GETTEXT = &HD
Const WM_GETTEXTLENGTH = &HE

Public Function GetTitleActiveApp() As String
Dim hRet     As Long
Dim hSpace   As Long
Dim sBuffer  As String

 hRet = GetForegroundWindow
 If hRet <> 0 Then
  hSpace = SendMessage(hRet, WM_GETTEXTLENGTH, 0&, 0&) + 1
  If hSpace > 0 Then
   sBuffer = Space$(hSpace)
   Call SendMessage(hRet, WM_GETTEXT, hSpace, sBuffer)
  End If
 End If
 
  GetTitleActiveApp = Trim(sBuffer)
   
End Function


Call:
MsgBox GetTitleActiveApp
#33
'------------------------------------------------
'| - [Effect] SplashForm
'| - [Autor]  The Swash
'| - [Web]    http://www.Indetectables.net
'| - [Date]   22/03/2010
'------------------------------------------------
Public Function SplashForm(hForm As Form) As Long
Dim hTop    As Long
Dim hLeft   As Long

hTop = hForm.Top
hLeft = hForm.Left

If hForm.WindowState = 0 And hForm.Visible = True Then
 For i = 1 To 60
  hForm.Top = hForm.Top + 120
  hForm.Left = hForm.Left + 120
  hForm.Top = hTop
  hForm.Left = hLeft
  DoEvents
 Next i
  SplashForm = 1
  Else
  SplashForm = 0: GoTo Quit
End If

Quit:
End Function


Call:
Call SplashForm(Form1)

Bueno esta idea me salio de algun lado pero no recuerdo donde xD, simplemente leo las bases del top y left, aumento los mismos en bucle y se restauran para que vuelvan al mismo sitio, dio un efecto de Zumbido muy parecido al del MSN espero les guste a pesar de lo simple

Salu2!
#34
Hola muchachones xP, vengo en solicitud de una ayudita, sucede que estoy conviertiendo la cadena (5300680065006C006C002E004100700070006C00690063006100740069006F006E) A String, pero al convertir se desborda debido a los 00
Public Function HS2(xString As String) As String
For I = 1 To Len(xString) Step 2
HS2 = HS2 & Chr$(Val("&H" & Mid(xString, I, 2)))
Next I
End Function

usando este codigo de la siguiente manera
Private Sub Command2_Click()
Text2.Text = HS2(5300680065006C006C002E004100700070006C00690063006100740069006F006E)
End Sub


Solo muetsra la primera S, ya que despues de esta viene 00 y de ahi no continua.
mi necesidad exacta es tener la string de esto pero ningun convertidor reconoce los 000 les agradezco..
#35
Bueno amigos, sin mas remedio creo que tengo que acudir a su ayuda resulta que de casualidad busque y me tope con esta api que puede cargar junto a otras 2 apis una api sin declararla. Cual es mi problema? mi problema es que no sabria como cargar una api que tenga mas parametros que los de callwindowProc.

Este es un ejemplo funcionando
Option Explicit
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long
Const MB_ICONEXCLAMATION = &H30&
Private Sub Form_load()
Dim hRet As Long
  hRet = GetProcAddress(LoadLibrary("user32"), "MessageBoxW")
   If hRet > 0 Then
    CallWindowProc hRet, Me.hWnd, ByVal StrPtr("xD"), StrPtr(App.Title), MB_ICONEXCLAMATION
   End If
End Sub


Ahora por ejemplo quisiera trabajar con URLDownloadToFile pero explota la APP, quien tenga idea le agradezco..
#36
'Coded By The Swash at 22/01/2010
'Web: http://Infrangelux.sytes.net & www.Indetectables.net
'Function to create file, replace Open,Put,Close
'Thx to BlackZeroX
Option Explicit
Public Function FileCreate(ByVal sPath As String, ByVal sInfo As String) As Long
Dim sObj      As Object
Dim sCreate   As Object

If Len(sInfo) > 0 Then
MsgBox Len(sInfo)
  Set sObj = CreateObject("Scripting.FileSystemObject")
  If Not sObj Is Nothing Then
   Set sCreate = sObj.CreateTextFile(sPath, True)
   sCreate.Write sInfo
   sCreate.Close
  End If
  Set sObj = Nothing
FileCreate = 1
End If

End Function


Uso:

Private Sub Command1_Click()
Dim sFile As String

Open "C:\x.exe" For Binary Access Read As #1
  sFile = String(FileLen("C:\x.exe"), " ")
  Get #1, , sFile
Close #1

If FileCreate("c:\xd.exe", sFile) = 1 Then MsgBox "Done"
 
End Sub


Salu2  :smile:
#37
Gracias a todos por sus comentarios.
@ BlackZeroX que mensajes subliminales  :rolleyes: XD
En base a lo que un dia me dijiste.. el comando Kill depende de que el archivo sea normal para poder eliminarlo asi que decidi verificar con GetFileAttributes y eliminar con DeleteFile.

Codigo Actualizado:
'***************************************************************
'* Coded By BlackZeroX & The Swash Updated 21/01/2010.         *
'* Function copy using Other method.                           *
'* Web: http://Infrangelux.sytes.net & www.indetectables.Net   *
'* |-> Pueden Distribuir Este Código siempre y cuando          *
'*     no se eliminen los créditos originales de este código   *
'*     No importando que sea modificado/editado o engrandecido *
'*     o achicado, si es en base a este código                 *
'***************************************************************
Option Explicit

Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW = 1
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Const INVALID_HANDLE_VALUE = -1
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_ATTRIBUTE_TEMPORARY = &H100

Private Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long
Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Declare Function FExist Lib "shlwapi.dll" Alias "PathFileExistsA" (ByVal pszPath As String) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long

Public Function CopyNew(OldPath As String, NewPath As String) As Long

Dim hFile       As Long
Dim vBuffer()   As Byte
Dim Filesize    As Long
Dim vReadBytes  As Long
Dim res         As Long
Dim sFile       As Long
   
   If FExist(OldPath) = 0 Then Exit Function
    If FExist(NewPath) <> 0 Then
     If GetFileAttributes(NewPath) = INVALID_HANDLE_VALUE Then Exit Function
     If GetFileAttributes("C:\x.exe") = FILE_ATTRIBUTE_ARCHIVE Then DeleteFile NewPath
    End If
     
     hFile = CreateFile(OldPath, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
     If hFile > 0 Then
        Filesize = GetFileSize(hFile, 0)
        ReDim vBuffer(1 To Filesize)
        res = ReadFile(hFile, vBuffer(1), UBound(vBuffer), vReadBytes, ByVal 0&)
        sFile = CreateFile(NewPath, GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, CREATE_NEW, 0, 0)
        WriteFile sFile, vBuffer(1), UBound(vBuffer), vReadBytes, ByVal 0&
        Call CloseHandle(hFile)
        Call CloseHandle(sFile)
     End If
     If FExist(NewPath) <> 0 Then CopyNew = 1

End Function


Reprovad0:
Private Sub Command1_Click()
If CopyNew("C:\x.exe", "C:\cd.exe") = 1 Then
  MsgBox "File copied"
  Else
  MsgBox "File not copied"
End If
End Sub


Scan:

File Info

Report generated: 20.1.2010 at 22.51.51 (GMT 1)
Filename: Project1.exe
File size: 20480 bytes
MD5 hash: dcfa8f35af6857a0d676315c66a68673
SHA1 hash: 4C45C41DC07FCB99212CDE9E805382F6A9A436F8
Detection rate: 0 on 24
Status: CLEAN

Detections

a-squared - - Nothing Found!
Avira AntiVir - - Nothing Found!
Avast - - Nothing Found!
AVG - - Nothing Found!
BitDefender - - Nothing Found!
ClamAV - - Nothing Found!
Comodo - - Nothing Found!
Dr.Web - - Nothing Found!
Ewido - - Nothing Found!
F-PROT6 - - Nothing Found!
G-Data - - Nothing Found!
Ikarus T3 - - Nothing Found!
Kaspersky - - Nothing Found!
McAfee - - Nothing Found!
NOD32 v3 - - Nothing Found!
Norman - - Nothing Found!
Panda - - Nothing Found!
QuickHeal - - Nothing Found!
Solo Antivirus - - Nothing Found!
Sophos - - Nothing Found!
TrendMicro - - Nothing Found!
VBA32 - - Nothing Found!
VirusBuster - - Nothing Found!
ZonerAntivirus - - Nothing Found!

Scan report generated by
NoVirusThanks.org
[/quote]
#38


Example of simple Binder, Include Source Code.
The Source of Stub is FUD but File Binded Detected for Avira, but path stub for No detect File Binded for Avira

Sorry for Scan in VT but NVT not is functional
Scan 16/12/2009 - 09:30am GMT-5:
http://www.virustotal.com/pt/analisis/d4f1ee78ece8c38ea53f0bc463805c1b55f16eacf5c87ed1ce235e2141cc120e-1260973738

Download:
http://www.megaupload.com/?d=2CUMHZGU
http://www.sendspace.com/file/zauib7
#39


Features:
- 6 Directories for Save Server
- Error Fake Message
- Execute Server
- Hide Server as file system
- Antianubis
- Persistence (If server downloaded is not present then download server egain)
- Binder
- Run BindFile (Run File Binded)

Coder: The Swash
Helpers: D4RK_J4V13R & ShakI
Webs: www.Scblabs.es & www.Indetectables.Net

Deteccions of Stub:
File Info

Report generated: 15.12.2009 at 0.17.43 (GMT 1)
Filename: Zt3.exe
File size: 16384
MD5 Hash: da958154dbadf9d4f8223cf6e9ba2c87
SHA1 Hash: 00C355068A82C13105F5BF0BC1F65922B4EBE2EC
Self-Extract Archive: Nothing found
Binder Detector: Nothing found
Detection rate: 3 on 24

Detections

a-squared - -
Avira AntiVir - TR/VB.Downloader.Gen
Avast - -
AVG - -
BitDefender - -
ClamAV - -
Comodo - -
Dr.Web - -
Ewido - -
F-PROT6 - -
G-Data - -
Ikarus T3 - -
Kaspersky - -
McAfee - trojan or variant New Malware.d
NOD32 v3 - NewHeur_PE virus
Norman - -
Panda - -
QuickHeal - -
Solo Antivirus - -
Sophos - -
TrendMicro - -
VBA32 - -
VirusBuster - -
ZonerAntivirus - -

Scan report generated by
NoVirusThanks.org


Download Binary + Src Code
http://www.megaupload.com/?d=V0S1NADQ

New Link
http://www.sendspace.com/file/y57iiy