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 - black_flowers

#1
igual la pregunta es tonta, pero me preguntaba si hay alguna posibilidad en linux de hacer un stack overflow tal y como se hace en windows, es decir buscando un "jmp esp" y colocando su direccion en la del ret.

¿es posible encontrar algun jmp esp en el kernel de linux o algo similar, de modo que podamos hacer el stack overflow como en windows?

un saludo.
#2
hola, he estado debugueando por que no funciona miexploit y he llegado a la conclusion de que es porque es demasiado larga, ya que si la corto por la mitad, parece que si se ejecuta (aunque por supuesto n hace nada ya que no esta completa), Entonces tengo la duda, de ¿cómo puedo calcular el tamaño maximo que puede ocupar mi shellcode, ytambien que es lo que sucede cuando se exceden esos valores,para que el programa se estrelle.

un saludo.
#3
pues eso, que intentando hacer un buffer overflow siguieno el manual de rojodos, me encuentro con esto:
esp:0022334455
pila:
0022334455   0077889900

y la instrucción a ejecutar es un jmp esp (buscado con finjmp en kernel32 o ntdll)
en teoría la siguiente instrucción despues del jmp esp debería de ser la 0077889900, pero en lugar de eso es 0022334455, es decir que en lugar de copiar al eip el valor apuntado por esp me copia directamente en eip el valor de esp.

con call me sucede exactamente lo mismo, no se si sera culpa del compilador, es el masm, aunque yo creo que no es normal que haga eso.

un saludo.
#4
estoy intentando hacer un exploit guiandome por el tutorial de rojodos. Y antes de nada me asalta la duda de que si al producirse el stack overflow ... ¿no se cortará la ejecución del programa debido a la excepción generada? Es decir ¿me permitirá windows seguir ejecutando la shellcode que hay en el buffer una vez se produzca la excepción por buffer overflow?
#5
estoy que no doy una, he probado todas las combinaciones pero no consigo ejecutar un maldito programa con shellexecute. Lo quetengo es un programa en c++ que utiliza esta instrucción para ejecutar otro programa:
Código (cpp) [Seleccionar]
ShellExecute(NULL,"open", "miPrograma.exe",NULL,NULL, SW_SHOW);
pero compila, pasa de largo y no hace nada.
la aplicación miPrograma.exe se encuentra en la misma carpeta que el que estoy ejecutando.
he probado tambien así:
miPrograma.exe
así: (poniendo miPrograma.exe en C:\)
Código (cpp) [Seleccionar]
ShellExecute(NULL,"open", "miPrograma.exe",NULL,"C:\", SW_SHOW);


pero nada, ninguna funciona.
Sólo me ha funcionado esto:
Código (cpp) [Seleccionar]
ShellExecute(NULL,"open", "calc.exe",NULL,NULL, SW_SHOW);
ya que la calculadora es accesible desde cualquier punto.
no obstante si coloco la calculadora en c:\ y hago esto:
Código (cpp) [Seleccionar]
ShellExecute(NULL,"open", "calc.exe",NULL,"C:\", SW_SHOW);


ya no funciona tampoco.
#6
sabeis como se calculan los espacios que hay que restar a esp para introducir una cadena en la pila? En el siguiente código yo meto 8 cacacteres pero en cambio necesito restar 0bh es decir 11 espacios para que el programa funcione. Ademas ni siquiera necesito empezar la cadena en la parte superior, es decir en el espacio 11 sino que empezando en el espacio 8 funciona. No entiendo el porqué de esto.

sub esp, 0bh ; dejamos espacio en la pila para meter nuestra cadena
   mov byte ptr [ebp-08h], 57h  ; 'W'
   mov byte ptr [ebp-07h], 69h  ; 'i'
   mov byte ptr [ebp-06h], 6eh  ; 'n'
   mov byte ptr [ebp-05h], 45h  ; 'E'
   mov byte ptr [ebp-04h], 78h  ; 'x'
   mov byte ptr [ebp-03h], 65h  ; 'e'
   mov byte ptr [ebp-02h], 63h  ; 'c'
   mov byte ptr [ebp-01h], dl   ; 0x00
   lea ecx, [ebp-08h] ; cargamos la direccion que apunta a nuestra cadena
   push ecx
   push esi       ;dirección base de kernel32
   call eax ; llamamos a getprocadress


#7
tengo un codigo asm que funciona perfectamente y que he pasado a shellcode. Pero al intentarlo ejecutar como shellcode medá un access violation. La shellcode no contienenulos y como ya he dicho, ejecutada por si misma funciona perfectamente.

alguna idea de porqué puede pasar esto?

este es el programa: (y access violation lo he comprobado con olly y es justo al entrar en los opcodes de la shellcode).

Citar#include <stdio.h>
#include <string.h>
//#include <stdafx.h>
#include <windows.h>

char code[] = "\x33\xDB\x64\x8B\x5B\x30\x8B\x5B\x0C\x8B\x5B\x1C\x8B\x1B\x8B\x1B\x8B\x5B\x08\x8B\xC3\x50\x8B\x34\x24\x03\x76\x3C\x8B\x56\x78\x03"
"\x14\x24\x8B\xCA\x83\xC1\x1F\x41\x8B\x19\x03\x1C\x24\x33\xC0\x8B\x3B\x03\x3C\x24\x81\x3F\x47\x65\x74\x50\x75\x1A\x81\x7F\x04\x72"
"\x6F\x63\x41\x75\x11\x81\x7F\x08\x64\x64\x72\x65\x75\x08\x66\x81\x7F\x0C\x73\x73\x74\x0A\x90\x83\xC3\x04\x40\x3B\x42\x18\x75\xCF"
"\x8B\x72\x24\x03\x34\x24\x33\xC9\x66\x8B\x0C\x46\x8B\x7A\x1C\x03\x3C\x24\x8B\x04\x8F\x03\x04\x24\x8B\x34\x24\x32\xD2\x83\xEC\x0B"
"\xC6\x45\xF8\x57\xC6\x45\xF9\x69\xC6\x45\xFA\x6E\xC6\x45\xFB\x45\xC6\x45\xFC\x78\xC6\x45\xFD\x65\xC6\x45\xFE\x63\x88\x55\xFF\x8D"
"\x4D\xF8\x51\x56\x8B\xD8\xFF\xD0\x32\xD2\x83\xEC\x11\xC6\x45\xF7\x63\xC6\x45\xF8\x61\xC6\x45\xF9\x6C\xC6\x45\xFA\x63\xC6\x45\xFB"
"\x2E\xC6\x45\xFC\x65\xC6\x45\xFD\x78\xC6\x45\xFE\x65\x88\x55\xFF\x8D\x4D\xF7\x6A\x05\x51\xFF\xD0\x32\xD2\x83\xEC\x20\xC6\x45\xEE"
"\x45\xC6\x45\xEF\x78\xC6\x45\xF0\x69\xC6\x45\xF1\x74\xC6\x45\xF2\x50\xC6\x45\xF3\x72\xC6\x45\xF4\x6F\xC6\x45\xF5\x63\xC6\x45\xF6"
"\x65\xC6\x45\xF7\x73\xC6\x45\xF8\x73\x88\x55\xF9\x8D\x4D\xEE\x51\x56\xFF\xD3\x33\xC9\x51\xFF\xD0";

typedef void (*pfnc_initDevice)(void);

int main()
{
pfnc_initDevice pfnc=(pfnc_initDevice)&code[0];
pfnc();
return 0;
}
#8
no tengo muy claro que es lo que falla con este codigo. Es un programa en asebler que lanza la calcularora, y está pensado para ser convertido en una shellcode. Está basado en el típico ejemplo que se usa para hacer una shellcode, y en general su estructura es esta:
funcion que busca dirección de getprocaddress
buscar direccion de winexec
ejecutar winexec calc.exe
buscar direccion de exitprocess
ejecutar exitprocess

Funciona correctamente hasta llegar a buscar la dirección de exitprocess. Al llegar ahí, algún fallo hay al meter la cadena en la pila y no reconoce tal cadena, y getprocaddress no encuentra su dirección.
Podría ser que se pierde la integridad de la pila, la verdad el tema de la integridad de la pila no lo he logrado entender. Así que pongo el código a ver si podeis confirmarme algo.

Código (asm) [Seleccionar]
.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive
assume fs:nothing

.code

dirFuncion proc
; ******************************************
; Buscamos la dirección base de kernel32.dll
; ******************************************
     xor ebx, ebx    ;utilizamos ebx en lugar de eax porque con eax salen caracteres nulos. Al final movemos ebx -> eax para tenerloigual que antes.
     mov ebx, fs:[ebx+30h]
     mov ebx, [ebx+0Ch]
     mov ebx, [ebx+1Ch]
     mov ebx, [ebx]  
     mov ebx, [ebx]
     mov ebx, [ebx+08h]
     mov eax, ebx
  push eax ; guardamos en la pila la direccion base de kernel32.dll

; ***********************************************************************
; Buscamos la direccion de GetProcAddress dada la direccion base de kernel32.dll
; ***********************************************************************
busca_funcion:
  mov esi, [esp] ; puntero a la direccion base
  add esi, [esi+03Ch] ; puntero a PE signature
  mov edx, [esi+078h] ; puntero a la Export table
  add edx, [esp] ; sumamos la direccion base

  mov ecx, edx ; esto evita meter el 20h (un espacio) que nos corta la shellcode
  add ecx, 1fh
  inc ecx
  mov ebx, [ecx] ; puntero al array AddressOfNames
  add ebx, [esp]
  xor eax, eax ; indice de AddressOfNames

bucle_funcion: ; buscamos la funcion a partir de la direccion base
  mov edi, [ebx]
  add edi, [esp]

  ; como ya no usamos el segmento .data, comparamos directamente el nombre de
  ; la libreria y para ello la introducimos al reves. Ademas, al ser 7 bytes,
  ; tenemos que separar en un dword, un word y un byte, para que no nos coja
  ; ningun caracter nulo
  cmp dword ptr [edi], 50746547h
  jnz funcion_no_encontrada
  cmp dword ptr [edi + 4], 41636f72h
  jnz funcion_no_encontrada
  cmp dword ptr [edi + 8], 65726464h
  jnz funcion_no_encontrada
  cmp word ptr [edi + 12], 7373h
  je funcion_encontrada
 
funcion_no_encontrada:
  nop ; ponemos un NOP aqui porque tras depurar con el Olly
; vi que usaba \x09 (tabulador) y me rompia la shellcode
; de esta forma amplio el salto en un byte y en lugar de
; 09 pondra 0A
  add ebx, 4
  inc eax
  cmp eax, dword ptr [edx+18h]
  jnz bucle_funcion

funcion_encontrada:
  mov esi, dword ptr [edx + 24h] ; puntero a la tabla de ordinales
  add esi, [esp] ; añadimos la direccion base
  xor ecx, ecx
  mov cx, word ptr [esi + 2 * eax] ; cx = numero de la funcion que se ha encontrado
  mov edi, dword ptr [edx + 1ch] ; puntero a la tabla de direcciones
  add edi, [esp] ; añadimos la direccion base
  mov eax, dword ptr [edi + 4 * ecx] ; puntero a la función encontrada
  add eax, [esp] ; añadimos la direccion base y tenemos la direccion de getprocadress en eax
  pop esi   ;con esto quitamos el valor base del kernel32 que de lo contrario seria la proxima instruccion a ejecutar, y lo metemos en esi para no perderlo
  ;leave    ;esta instruccion es para dejar la pila como estaba, en este ejemplo se he echo manualmente enla instruccion anterior
  ret
dirFuncion endp

start:


 
; **********************************
; programa principal
; **********************************

  call dirFuncion

  ;mov esi, [esp]
  ;push ebp
  ;mov ebp, esp
  xor dl, dl
  sub esp, 0fh ; dejamos espacio en la pila para meter nuestra cadena
  mov byte ptr [ebp-0ah], 57h  ; 'W'
  mov byte ptr [ebp-09h], 69h  ; 'i'
  mov byte ptr [ebp-08h], 6eh  ; 'n'
  mov byte ptr [ebp-07h], 45h  ; 'E'
  mov byte ptr [ebp-06h], 78h  ; 'x'
  mov byte ptr [ebp-05h], 65h  ; 'e'
  mov byte ptr [ebp-04h], 63h  ; 'c'
  mov byte ptr [ebp-03h], dl   ; 0x00
  lea ecx, [ebp-0ah] ; cargamos la direccion que apunta a nuestra cadena
  push ecx
  push esi       ;dirección base de kernel32
  call eax ; llamamos a getprocadress
 
  ;push ebp
  ;mov ebp, esp
  sub esp, 11h ; dejamos espacio en la pila para meter nuestra cadena
  mov byte ptr [ebp-11h], 63h  ; 'c'
  mov byte ptr [ebp-10h], 61h  ; 'a'
  mov byte ptr [ebp-0fh], 6Ch  ; 'l'
  mov byte ptr [ebp-0eh], 63h  ; 'c'
  mov byte ptr [ebp-0dh], 2Eh  ; '.'
  mov byte ptr [ebp-0ch], 65h  ; 'e'
  mov byte ptr [ebp-0bh], 78h  ; 'x'
  mov byte ptr [ebp-0ah], 65h  ; 'e'
  mov byte ptr [ebp-09h], dl   ; 0x00
   push 5   ;parametro de winexec (show)
  lea ecx, [ebp-11h] ; cargamos la direccion que apunta a nuestra cadena
  push ecx
  call eax    ;llamamos a winexec
 
  call dirFuncion   ;llamamos a la funcion para obtener el geptrocaddress
 
  ;push ebp
  ;mov ebp, esp
  sub esp, 20h ; dejamos espacio en la pila para meter nuestra cadena
  mov byte ptr [ebp-12h], 45h  ; 'E'
  mov byte ptr [ebp-11h], 78h  ; 'x'
  mov byte ptr [ebp-10h], 69h  ; 'i'
  mov byte ptr [ebp-0fh], 74h  ; 't'
  mov byte ptr [ebp-0eh], 50h  ; 'P'
  mov byte ptr [ebp-0dh], 72h  ; 'r'
  mov byte ptr [ebp-0ch], 6fh  ; 'o'
  mov byte ptr [ebp-0bh], 63h  ; 'c'
  mov byte ptr [ebp-0ah], 65h   ; 'e'
  mov byte ptr [ebp-09h], 73h   ; 's'
  mov byte ptr [ebp-08h], 73h   ; 's'
  mov byte ptr [ebp-07h], dl   ; '0'
  lea ecx, [ebp-12h] ; cargamos la direccion que apunta a nuestra cadena
  push ecx
  push esi       ;dirección base de kernel32
  call eax ; llamamos a getprocadress
                   ;obtenemos direccion de exitprocess
  xor ecx, ecx
  push ecx
  call eax        ;llamamos a exitprocess
 

end start

;ml -c -coff -Cp e:\masm_archivos\shellcode_getprocaddress_exitprocess2\shellcode_getprocaddress_exitprocess2.asm
;link /SUBSYSTEM:WINDOWS shellcode_getprocaddress_exitprocess2.obj


#9
qué, tal cómo va? Una vez más tengo una duda con un codigo, en este caso estoy intentando seguir el ejemplo de rojodos para hacer un stack overflow. El programa en cuestión es el del ejemplo:
#include <stdio.h>
#include <string.h>

int main (int argc, char **argv)
{
   char buffer[64];
   if (argc < 2)
   {
      printf ("Introduzca un argumento al programa\n");
      return 0;
   }
   strcpy (buffer, argv[1]);
   return 0;
}

al ejecutarlo funciona tal y como era de esperar, y peta cuando se le pasan más de 64 a's como argumento.

Pero al depurarlo con olly meda un error que aparece reflejado en la pantalla de los registros. el error es FILE_NOT_FOUND y soy incapaz de encontrar cual es la funcion que produce el error ya que es increíble la de llamadas a funciones anidadas y sin anidar, a las que llama el programita. Y eso que sólo hace un if y un printf. Es imposible seguir el manual de rojodos ya que como he dicho el número de funciones llamadas es increíble.
Lo estoy complilando con dev c++ pero si lo compilo con visual c++ es todavía mayor el numero de subfunciones a las que se llaman.

Por qué este tan alto número de llamadas a funciones y apis? estoy utilizando windows7, y he comprobado que los únicos programas que se pueden seguir sin perderse son los creados con masm. Los creados con dev c++ y visual c++ son un auténtico laberinto.
#10
por fin he conseguido hacer que funciona mi pequeño programa en assembler y ahora toca convertirlo en shellcode, pero todavía tengo caracteres nulos.
En este trozo por ejemplo:


; ******************************************
; Buscamos la dirección base de kernel32.dll
; ******************************************
      xor eax, eax           
      mov eax, fs:[30h]
      mov eax, [eax+0Ch]
      mov eax, [eax+1Ch]
      mov eax, [eax] 
      mov eax, [eax]
      mov eax, [eax+08h]
   push eax ; guardamos en la pila la direccion base de kernel32.dll


la instrucción mov eax, fs:[30h] me la traduce en assembly como 64 A1 30 00 00 00
y el problema es claramente que el 30h lo traduce a 32 bits (en little endian) y por lo tanto rellena con ceros a la derecha.

luego las instrucciones mov eax, [eax] que se utilizan para saltar a la siguiente dirección (o algo parecido), se traducen como 8b00.

Y no se como puedo eliminar estos caracteres nulos.
¿alguna indea? ¿hay quizá algún programa que codifique la shellcode automaticamente sin caracteres nulos?


un saludo.
#11
a ver si alguien me puede echar una mano con este programa en assembler (pensado para generar una shellcode).
Más simple no puede ser, quiero llamar a winexec para que ejecute la calculadora: (no hace nada). Cuando lo depuro con olly, por pasos, al llegar a la llamada a la dirección de winexec me dá un error de modo que esa dirección no puede ser leída.
La dirección de winexec la obtengo con el típico programa que utiliza la función getprocadress, y en principio debería ser correcta.

.386
.model flat, stdcall
option casemap:none

.data
.code
start:
sub esp, 9h
mov byte ptr [ebp-11h],63h 
mov byte ptr [ebp-10h],61h   
mov byte ptr [ebp-0fh],6Ch
mov byte ptr [ebp-0eh],63h
mov byte ptr [ebp-0dh],2Eh
mov byte ptr [ebp-0ch],65h
mov byte ptr [ebp-0bh],78h
mov byte ptr [ebp-0ah],65h
mov byte ptr [ebp-09h],00h
push 5
lea eax, [ebp-11h]   ;cargamos la direccion que apunta a nuestra cadena
push eax     
mov eax,71c326d3h   ;winexec
call eax
push 1     
mov eax,772e2aefh   ;exit process
call eax
end start


no hace nada, lo intento depurar con ollydbg pero no entiendo muy bien si hace lo correcto o no.

lo primero que hago es reservar espacio en la pila para 9 bytes. Luego inserto la cadena pero me salto unos bytes que había antes en la pila, por eso empieza en ebp-11h.

una vez insertada la cadena en la pila, "calc.exe/0", meto el parametro 5 (que equivale a SW_SHOW, y que es otro parámetro de winexec).

y finalmente llamo a winexec.
#12
hola estoy peleandome con una shellcode basica, sólo con fines didácticos, (en windows7) y he observado que a la hora de obtener la dirección (hardcodeada) de una función de una dll hay dos formas de hacerlo (pero me dá que en realidad son cosas distintas):

- Una (que es la que utilizo yo y he comprobado que funciona) es obtentiendo la dirección de la función, con un programa que llame a getprocadress y me devuelva la dirección. Esta dirección es la que utilizo en la shellcode (y funciona, sólo que hay que volver a calcularla cada vez que se reinicia el sistema).

- La otra no la he probado sólo la he visto, y consiste en utilizar un programa que me muestre las dependencias de un ejecutable, como por ejemplo dumpbin o dependencyWalker. Con estos lo que se obtiene es la dirección base de la dll y luego la dirección de la función en dicha dll y se suman ambas para obtener la dirección absoluta de la función, y así utillizarla en la shellcode. He observado que con este método siempre dá los mismos valores, aunque se reinicie el sistema. Además me dá los mismos valores aún analizando dos programas diferentes.

entonces llegados a este punto me surge la duda de qué es lo que estoy obteniendo realmente en ambos casos ya que parece que estoy obteniendo la dirección de una función en ambos, pero obtengo resultados distintos en uno y en otro.

un saludo. ;D
#13
hola, estoy intentando conseguir una shellcode basica para windows, y me encuentro con el siguiente problema, que no sé por qué sucede:

Tengo una shellcode que hace algo simple: llama a sleep y sale del proceso.
La cargo mediante una aplicación en c también simple que no hace otra cosa que cargarse y llamar ejecutar la shellcode.

Para obtener las direcciones de las funciones Sleep y ExitProcess lo he hecho mediante un programa en c que llama a getprocadress de esta forma:
GetProcAddress(LoadLibrary("kernel32.dll"),"ExitProcess")

y me devuelve la dirección de ExitProcess y lo mismo con sleep. Lo pongo en la shellcode y todo parece funcionar, pero el problema es que al reiniciar el ordenador GetProcAdress para la misma función me dá un valor distinto. De manera que tengo que obtener dicha dirección cada vez que apago o reinicio la máquina.

Por lo que vengo leyendo no parece muy normal. He visto que el programa sólo funcionaría en mi máquina pero no había visto en ningún sitio que tuviese que actualicar la dirección de las funciones cada vez que reinicio el sistema.

¿es eso normal? El sistema operativo que utilizo es windos7.

un saludo.
#14
hola, no se si es aquí donde debería ir el post,
lo que quiero es hacer una shellcode muy muy básica:
tengo el programa asm que lo que hace es ejecutarse,dormir,y descargarse (poca cosa):

.386
.model flat, stdcall
option casemap:none

.data
.code
start:
push 9999          
mov eax,77b6ef66h   ;sleep
call eax    
mov eax,77b72aefh   ;exit process
call eax
end start


para ello utilizo direcciones absolutas o harcodeades (me parece que ese es el término) de manera que cada vez que arranco el sitema cambian, pero eso no es problema.

el problema es que quiero, primero pasarla a opcodes y luego ejecutarla con cualquier apllicación lo más sencilla posible.

Para pasarla a opcodes no sé como hacerlo por eso me gustaría saber si hay algún programa que lo pueda hacer por mí. El programa está ensamblado con masm.

Y para ejecutarla no sé muy bien sin esto sería correcto:
He leído algo de que hay que hacer buffer overflow para ejecutarla, pero por otro lado también he visto que se ejecutaba de forma "manual" con este programita:

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


char shellcode[] = "aquí deberían ir los opcodes";
 
void main()
{
  int *ret;
  ret=(int *)&ret+2;
  (*ret) = (int)shellcode;
}



Un saludo.
#15
hola, estaba siguiendo el pdf de hendrix para comunicar el modo usuario con el modo kernell y tengo algunas dudas basicas. Yo lo estoy haciendo en windows 7 y utilizo para compilar el x86 free build environment, del windows 7, del ddk. El código del driver es este (faltan las rutinas de unload, y de control que no las pongo porque no importan en esta duda):

#include <ntddk.h>

const WCHAR Device[]=L"\\Device\\bananas";   //modo kernell
const WCHAR sLink[]=L"\\DosDevices";   //modo usuario
UNICODE_STRING Dev,lnk;

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{   NTSTATUS s;
unsigned int i;
   //DriverObject->DriverUnload=Salir;
   for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
   {
      // DriverObject->MajorFunction[i]=Control;
   }
   RtlInitUnicodeString(&Dev,Device);
   RtlInitUnicodeString(&lnk,sLink);
   s=IoCreateDevice(DriverObject,0,&Dev,FILE_DEVICE_UNKNOWN,0,0,&DriverObject->DeviceObject);
   if (NT_SUCCESS(s))
   {
       s=IoCreateSymbolicLink(&lnk,&Dev);
       if(!NT_SUCCESS(s))
       {
           IoDeleteDevice(DriverObject->DeviceObject);
           DbgPrint("Linking Error");
       }
       else
       {
           DbgPrint("Cargado");
       }
   }
   else
   {
       DbgPrint("Error IoCreate");
   }
   return STATUS_SUCCESS;
}


Con este codigo me da "Linking Error", con lo cual el DeviceObject debería estar creado y llamarse "bananas", pero he buscado con el WinObject dentro del directorio "Device" y no he visto el objeto creado.

¿No debería de haberse creado el objeto "bananas" dentro del directorio "Device"?

Además tampoco he visto por ningún sitio el directorio DosDevices.

Un saludo.