Ir al contenido



Foto

Como controlar los videos que se ejecuten en la PC?


  • Por favor identifícate para responder
27 respuestas en este tema

#1 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 27 junio 2011 - 10:00

Hola a todos
Lo que sucede es que en mi empresa el Jefe decidio que prohibiera la ejecución de videos (musicales, peliculas, novelas, etc) en las PC de toda la red local
Esto lo hice bloqueando la ejecución de todos los reproductores de video, pero resultó que hay videos didacticos y educativos que si necesitan verse, pero con la restriccion puesta tampoco se ven estos

Lo que necesito es la forma de que solo se puedan ejecutare este grupo de videos, que estaran en una carpeta compartida en un servidor

La idea que se me ocurre es:
1- Hacer un reproductor en Delphi que solo reproduzca el contenido de la carpeta especificada
2- Monitorear la ruta de lo que va a reproducir el Reproductor de Video y cancelarlo si no es la autorizada (lo veo mas dificil de hacer)
3- Diganme uds otra idea  *-)


Probe haciendo un reproductor con el componente que incorpora Delphi pero no pone el video al tamaño de la ventana ni tampoco a pantalla completa, o al menos no supe como hacerlo

Se que hay una forma de hacer que una aplicación se ejecute dentro de la mia, que pudiera probar con eso, pero no recuerdo como es ni donde lo vi (me parece que fue en ClubDelphi)

Diganme que puedo hacer con esto :|

  • 0

#2 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 27 junio 2011 - 05:52

Realizar un Reproductor es posible con DirectX, pero ¿quien te garantiza que es el que van a usar para ver vídeos no permitidos?. El problema va a ser que usen un reproductor portable incluso hecho en delphi...

Monitorizar la ruta de lo que va a reproducir el Reproductor de Vídeo y cancelarlo también puede intentarse con un Hook global aunque si el S.O. es Win 7 de 64 bits no creo que funcione. El Hook puede ser a nivel Kernel, esto le hará mucho mas efectivo pero tiene un gran inconveniente, es muy dependiente del S.O. y puede molestar al A.V.

Saludos.
  • 0

#3 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 28 junio 2011 - 10:03

Para garantizar que sea mi reproductor, lo que tengo pensado es copiarlo en la misma carpeta que los videos admitidos, y solo se ejecutará si está en esa carpeta, fuera de ella no abrira
Cualquier otro reproductor estará bloqueado

Probé haciendolo con el tmediaplayer pero no funciona bien con los avi y no reproduce los VOB
Con que otro componente se podria hacer?

Para lo del Hook, no tengo PC con Win7 pero si podria haber problemas con al AV
  • 0

#4 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 28 junio 2011 - 10:54

El problema es tener la herramienta capaz de bloquear cualquier reproductor local de video...

He estado jugando un poco, y he tirado por la calle de "en medio". He realizado un prototipo de DLL que se inyecta de forma global y realiza un Hook a las APIs CreateFileW y OpenFile, probablemente ésta última no sea preciso engancharla, pero lo he hecho.

El Hook funciona de la siguiente forma: Cualquier llamada a esas APIs pasa por mi filtro y si tiene la extensión ".avi", comprueba que la ruta comienza por '\', si es así permite abrir el archivo (está en el servidor) de lo contrario devuelve -1.

La DLL la he escrito en C por varias razones, la primera porque para estas tareas me resulta mucho mas cómodo. La segunda porque para realizar con seguridad un Hook a la API con un trampolín, se precisa desensamblar en tiempo de ejecución las primeras instrucciones (Opcodes) y ese código lo tengo escrito en C, siendo tediosa su traducción a delphi.

Pongo el código de las APIs enganchadas:
 

cpp
  1.            
  2. HANDLE WINAPI HCreateFileW(
  3.             LPCWSTR lpFileName,
  4.             DWORD dwDesiredAccess,
  5.             DWORD dwShareMode,
  6.             LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  7.             DWORD dwCreationDisposition,
  8.             DWORD dwFlagsAndAttributes,
  9.             HANDLE hTemplateFile)
  10. {
  11.  
  12.   if(wcsstr(lpFileName, L".avi")){
  13.     if(*lpFileName != L'\\'){
  14.       //Beep(100, 500);
  15.       return (HANDLE)-1;
  16.     } 
  17.   }
  18.   return OriginCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  19.                             dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  20. }
  21.  
  22. HFILE WINAPI HOpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
  23. {
  24.   if(strstr(lpFileName, ".avi")){
  25.     if(*lpFileName != '\\'){
  26.       //Beep(100, 500);
  27.       return -1;
  28.     }
  29.   }
  30.   return OriginOpenFile(lpFileName, lpReOpenBuff, uStyle);
  31. }

La Dll exporta dos funciones accesibles desde delphi: Hook y UnHook. Pongo un ejemplo en delphi y lo subo junto con la dll.


delphi
  1. procedure Hook; stdcall external 'HookDll';
  2. procedure UnHook; stdcall external 'HookDll';
  3.  
  4. ...........................................................
  5.  
  6.  
  7. procedure TForm1.HookButtonClick(Sender: TObject);
  8. begin
  9.   Hook;
  10. end;
  11.  
  12. procedure TForm1.UnHookButtonClick(Sender: TObject);
  13. begin
  14.   UnHook;
  15. end;

Se trata de una prueba de concepto pero es funcional, sólo falta añadir todas las extensiones posibles para archivos de vídeo... Pero aún así cabe la posibilidad de que un usuario quite la extensión a un archivo de vídeo y lo cargue en el reproductor, así que en ese caso el filtro debería comprobar las cabeceras de los archivos.

Creo que como idea inicial no está mal.  :) ;) 


Saludos.

Archivos adjuntos


  • 0

#5 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 29 junio 2011 - 08:30

Vaya que de verdad te tiraste por la calle de "en medio", me parece que con eso se resuelve el problema

Pero tengo una "pequeña" dificultad, no domino mucho el C y tampoco lo tengo
Podrias ayudarme compilandome la dll?

Para el caso de las extenciones de video serian:
avi, wmv, mpg, flv, vob
Con los .dat como se haria?, pues hay otros archivos .dat que son complementos de otras aplicaciones y no de videos

Entonces, lo que tendria que hacer es:
Copiar la dll con mi aplicacion monitor en las PC, y hacer que la aplicaciion se ejecute al inicio?


  • 0

#6 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 29 junio 2011 - 09:53

En informática casi todo se puede. Si te parece vamos a hacer una cosa. Realizo cambios en la dll para que llame a otra dll que contendrá el filtro. Esta segunda la realizas tu en delphi y así tienes el control del sistema y cambios futuros. Si te gusta la idea me lo dices.  ;)


Por otro lado, para resolver tu duda acerca de los reproductores, visita este enlace.




Saludos.
  • 0

#7 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 29 junio 2011 - 10:59

Esta muy buena la idea
Entonces mi DLL solo tendra la funcion de aplicar el filtro y la tuya la llamaria, es así?

Muchas gracias por la cooperación, veremos como nos sale  *-) (y)
  • 0

#8 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 29 junio 2011 - 11:26

Vaya que muy interesante el vinculo que me diste  (y)
  • 0

#9 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 29 junio 2011 - 03:45

Esta muy buena la idea
Entonces mi DLL solo tendra la funcion de aplicar el filtro y la tuya la llamaria, es así?

Muchas gracias por la cooperación, veremos como nos sale 


Si, esa es la idea. Tu dll realizará el filtro con una función que será consultada por HookDLLl.

Esa función puede tener el prototipo:



delphi
  1. function Filter(FileName: String): boolean;



Dado que el APIHook fundamental es a CreateFileW que trabaja en unicode, podemos usar este formato de cadenas o las clásicas, como prefieras.

El método no va a ser infalible al 100% pero si para la mayoría de los usuarios. Sólo me preocupa el detalle de que un usuario renombre un archivo de vídeo con otra extensión. En ese caso no sería bloqueado, a no ser que se analice la cabecera de dicho archivo en el filtro. Eso supone el análisis y conocimiento de dichas cabeceras o tratar de usar DirectX o funciones de alto nivel similares.

En fin, es cuestión de darle vueltas para encontrar el filtro mas adecuado y eficaz.


Saludos.
  • 0

#10 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 30 junio 2011 - 07:37

Bien, he modificado HookDLL.

Ahora el filtro debe estar en otra dll denominada "FilterDLL.dll"

El prototipo de la función filtro es el siguiente:
 


delphi
  1. function Filter(
  2.             lpFileName: PCHAR;
  3.             dwDesiredAccess: DWORD;
  4.             dwShareMode: DWORD;
  5.             lpSecurityAttributes: PSECURITY_ATTRIBUTES;
  6.             dwCreationDisposition: DWORD;
  7.             dwFlagsAndAttributes: DWORD;
  8.             hTemplateFile: THANDLE): boolean; stdcall;

Recibe todos los parámetros de CreateFileW con una diferencia. El Nombre del fichero lo recibe como cadena clásica, no como unicode. De esta manera se controla totalmente la API enganchada.

El Hook queda establecido sólo para la API CreateFileW de la siguiente forma:
 
 


cpp
  1. HANDLE WINAPI HCreateFileW(
  2.             LPCWSTR lpFileNameW,
  3.             DWORD dwDesiredAccess,
  4.             DWORD dwShareMode,
  5.             LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  6.             DWORD dwCreationDisposition,
  7.             DWORD dwFlagsAndAttributes,
  8.             HANDLE hTemplateFile
  9. )
  10. {
  11.   static Hooking = false;
  12.   if(!Hooking){
  13.     Hooking = true;
  14.     CHAR lpFileName[MAX_PATH + 1];
  15.     WideCharToChar(lpFileNameW, lpFileName);
  16.     if(Filter){
  17.       if(!Filter(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  18.                       dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)){
  19.  
  20.           Hooking = false;
  21.           return (HANDLE)-1;
  22.       }
  23.     }
  24.     Hooking = false;
  25.   }
  26.  
  27.   return OriginCreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  28.                             dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  29. }

 

Un ejemplo simple del filtro en el contexto de su dll:


delphi
  1. library FilterDLL;
  2.  
  3. uses
  4.   SysUtils,
  5.   Windows;
  6.  
  7. {$R *.res}
  8. type
  9. PSECURITY_ATTRIBUTES = ^SECURITY_ATTRIBUTES;
  10.  
  11.  
  12. function Filter(
  13.             lpFileName: PCHAR;
  14.             dwDesiredAccess: DWORD;
  15.             dwShareMode: DWORD;
  16.             lpSecurityAttributes: PSECURITY_ATTRIBUTES;
  17.             dwCreationDisposition: DWORD;
  18.             dwFlagsAndAttributes: DWORD;
  19.             hTemplateFile: THANDLE): boolean; stdcall;
  20. begin
  21.   Result:= true;
  22.   if Pos('.avi', lpFileName)<>0 then
  23.   begin
  24.     if lpFileName^ <> '\' then
  25.     begin
  26.       Beep(100, 200);
  27.       Result:= false;
  28.     end;
  29.   end;
  30. end;
  31.  
  32. exports Filter;
  33.  
  34. begin
  35. end.

Lo mejor será que el filtro no analize extensiones sino que trate de abrir el archivo con cadenas MCI o mediante DirectX, si es un archivo multimedia no obtendremos un error y en ese caso no le dejamos pasar (devolvemos false) a no ser que esté en el servidor.

Espero que te sea de utilidad.


Saludos.


  • 0

#11 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 30 junio 2011 - 09:20

¡Que cabeza la mia! :grin:

Se me pasó subir los archivos.
Ahora mismo los subo. :cheesy:


Saludos.

Archivos adjuntos


  • 0

#12 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 30 junio 2011 - 09:50

Muchas Gracias  (y)
Comenzare a trabajar con esto a ver como sale
Pero lo tendre que hacer a partir de la semana que viene pues el lunes tengo que defender mi tesis de Ing en Informatica, y estoy preparandome para eso  :s
  • 0

#13 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 01 julio 2011 - 09:25

Muchas Gracias 
Comenzare a trabajar con esto a ver como sale
Pero lo tendre que hacer a partir de la semana que viene pues el lunes tengo que defender mi tesis de Ing en Informatica, y estoy preparandome para eso 


Que tengas mucha suerte con la defensa de tu tesis, ya nos contarás. (y)

Por otro lado he realizado unas pruebas y ha habido cosas que no me han convencido. He hecho algunos cambios. Ahora no es necesario que las dll estén en la carpeta del sistema, pueden estar en cualquier parte, junto con la aplicación inyectora, a no ser que ésta pase la ruta de las dll, en cuyo caso la ubicación puede ser cualquiera.

Subo los nuevos archivos.


Saludos.




  • 0

#14 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.073 mensajes
  • LocationMéxico

Escrito 01 julio 2011 - 09:48

Suerte amigo JoAnCa.

A la defensa de esa Tesis, dales con todo :D

Salud OS
  • 0

#15 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 04 julio 2011 - 12:24

:shocked:

Algo ha pasado. Había publicado una actualización de los archivos del sistema VideoLock y el mensaje a desaparecido...

¿Alguien sabe algo?  :undecided:

Tendré que rebuscar los archivos, afortunadamente tengo copia.



Saludos.
  • 0

#16 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 04 julio 2011 - 04:37

Una vez en casa, puedo republicar los archivos.

Comentaba que había cosas que no me gustaban de la versión anterior. En la nueva versión se mejoran algunas cosas y no es necesario que las dlls estén en la carpeta del sistema, pueden estar en cualquier ubicación.

El filtro de ejemplo lo asemejo mas a delphi:

delphi
  1. function Filter(
  2.             lpFileName: PCHAR;
  3.             dwDesiredAccess: DWORD;
  4.             dwShareMode: DWORD;
  5.             lpSecurityAttributes: PSECURITY_ATTRIBUTES;
  6.             dwCreationDisposition: DWORD;
  7.             dwFlagsAndAttributes: DWORD;
  8.             hTemplateFile: THANDLE): boolean; stdcall;
  9. var
  10.   FileName: String;
  11. begin
  12.   Result:= true;
  13.   FileName:= String(lpFileName);
  14.   if ExtractFileExt(FileName)='.avi' then
  15.   begin
  16.     if FileName[1] <> '\' then
  17.     begin
  18.       //Beep(100, 50);
  19.       //OutputDebugString(PCHAR('bloqueado: '+ FileName));
  20.       Result:= false;
  21.     end;
  22.   end;
  23. //  if Result then OutputDebugString(PCHAR('NO bloqueado: ' + FileName));
  24. end;

El Código de HookDll.dll es básicamente este:
 
 

cpp
  1. #include <windows.h>
  2. #include "APIHook.h"
  3. #include "APIHook.cpp"
  4.  
  5. typedef HFILE  (WINAPI *POPENFILE)(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle);
  6. typedef HANDLE (WINAPI *PCREATEFILEW)(
  7.             LPCWSTR lpFileName,
  8.             DWORD dwDesiredAccess,
  9.             DWORD dwShareMode,
  10.             LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  11.             DWORD dwCreationDisposition,
  12.             DWORD dwFlagsAndAttributes,
  13.             HANDLE hTemplateFile);
  14.  
  15. typedef BOOL (WINAPI *PFILTER)(
  16.             LPCSTR lpFileName,
  17.             DWORD dwDesiredAccess,
  18.             DWORD dwShareMode,
  19.             LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  20.             DWORD dwCreationDisposition,
  21.             DWORD dwFlagsAndAttributes,
  22.             HANDLE hTemplateFile);
  23.  
  24. HHOOK hHook;
  25. HINSTANCE HInst;
  26. HMODULE hFilter;
  27. POPENFILE OriginOpenFile = 0;
  28. PCREATEFILEW OriginCreateFileW = 0;
  29. PFILTER Filter = 0;
  30.  
  31. //------------------------------------------------------------------------------
  32. // Convierte cadenas Unicode y clásicas entre si
  33. char* WideCharToChar(const wchar_t* Entrada, char* Salida, unsigned int Size=-1)
  34. {
  35.   int size = Size;
  36.   if(Size==-1) size = wcslen(Entrada)+1;
  37.   WideCharToMultiByte(CP_ACP, 0, Entrada, -1, Salida, size, NULL, NULL);
  38.   return Salida;
  39. }
  40.  
  41. // Provocamos el Hook Global. La dll se inyectará en todo el sistema de ventanas
  42. LRESULT CALLBACK HookPorc(int nCode,WPARAM wParam,LPARAM lParam)
  43. {
  44.   return CallNextHookEx(hHook, nCode, wParam, lParam);
  45. }
  46.  
  47. extern "C" __declspec(dllexport)
  48. __stdcall void Hook()
  49. {
  50.   hHook = SetWindowsHookEx(WH_CALLWNDPROC /*WH_CBT*/, (HOOKPROC)HookPorc, HInst, 0);
  51. }
  52.  
  53. extern "C" __declspec(dllexport)
  54. __stdcall void UnHook()
  55. {
  56.   UnhookWindowsHookEx(hHook);
  57. }
  58.  
  59. HANDLE WINAPI HCreateFileW(
  60.             LPCWSTR lpFileNameW,
  61.             DWORD dwDesiredAccess,
  62.             DWORD dwShareMode,
  63.             LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  64.             DWORD dwCreationDisposition,
  65.             DWORD dwFlagsAndAttributes,
  66.             HANDLE hTemplateFile
  67. )
  68. {
  69.   static Hooking = false;
  70.   if(!Hooking){
  71.     Hooking = true;
  72.     CHAR lpFileName[MAX_PATH + 1];
  73.     WideCharToChar(lpFileNameW, lpFileName);
  74.     bool Filtro = Filter(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  75.                 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  76.     if(!Filtro){
  77.         Hooking = false;
  78.         return (HANDLE)-1;
  79.     }
  80.     Hooking = false;
  81.   }
  82.  
  83.   return OriginCreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  84.                             dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  85. }
  86.  
  87. void InstallHook()
  88. {
  89.   char FilterDLL[MAX_PATH+1];
  90.   GetModuleFileName(HInst, FilterDLL, sizeof(FilterDLL));
  91.   char *F = strrchr(FilterDLL, '\\'); *F = 0;
  92.   strcat(FilterDLL,  "\\FilterDLL.dll");
  93.   hFilter = LoadLibrary(FilterDLL);
  94.   Filter = (PFILTER)GetProcAddress(hFilter, "Filter");
  95.   InstallHook(HCreateFileW, (void**)&OriginCreateFileW, "Kernel32.dll", "CreateFileW");
  96. }
  97.  
  98. void UnInstallHook()
  99. {
  100.   UnInstallHook((void**)&OriginCreateFileW, "Kernel32.dll", "CreateFileW");
  101.   FreeLibrary(hFilter);
  102. }
  103.  
  104. #pragma argsused
  105. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
  106. {
  107.   HInst = hinstDLL;
  108.   switch (fwdreason) {
  109.       case DLL_PROCESS_ATTACH:
  110.           InstallHook();
  111.           break;
  112.       case DLL_PROCESS_DETACH:
  113.           UnInstallHook();
  114.           break;
  115.   }
  116.  
  117.  
  118.   return 1;
  119. }

 


Saludos.
  • 0

#17 JoAnCa

JoAnCa

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 744 mensajes
  • LocationPinar del Río, Cuba

Escrito 05 julio 2011 - 12:22

Muchas gracias escafandra,
Ya probe y me sale bien lo que quiero, ahora que tengo un poco mas de tiempo voy a terminar y refinar un poco mas nuestro "guardian de videos(y)

Pues ya me gradue con la calificación maxima  *-) (y) :)
y tengo mas tiempo disponible
  • 0

#18 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 05 julio 2011 - 02:45

Muchas gracias escafandra,
Ya probe y me sale bien lo que quiero, ahora que tengo un poco mas de tiempo voy a terminar y refinar un poco mas nuestro "guardian de videos

Pues ya me gradue con la calificación maxima   
y tengo mas tiempo disponible



Me alegran dos cosas, que el proyecto se ajuste a tu necesidad y que consiguieras la máxima calificación.
  :) (y) (y) (b) (b)


Saludos.
  • 0

#19 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 05 julio 2011 - 03:45

Pues ya me gradue con la calificación maxima   
y tengo mas tiempo disponible

Felicitaciones amigo JoAnCa.  (b) (b)
  • 0

#20 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.073 mensajes
  • LocationMéxico

Escrito 05 julio 2011 - 03:49

Hola

Felicidades JoAnCa y muchas gracias a escafandra, realmente son éstas las cosas que hacen que valga la pena seguir adelante con una comunidad.

¡¡¡ Vamos DelphiAccess !!!  o lo que es lo mismo Go DA !!!  :)

Salud OS
  • 0