.NET Tutorial 18. Cómo crear propiedades personalizadas para cualquier control de Windows

En la entrada anterior vimos como cambiar el aspecto "visual" de un control de Windows. Hoy vamos a ir un paso más allá. Vamos a ver lo fácil que resulta crear propiedades "personalizadas" para cualquier control de Windows desde .NET.

Cuando añades un control de Windows en tu formulario, se nos muestran una serie de propiedades asociadas a dicho control, por ejemplo para una caja de texto:

Estas propiedades alteran el comportamiento de dicho control. Puede darse el caso en que por comodidad, necesitemos que un control haga algo "especial", lo típico, que por ejemplo una caja de texto sólo acepte números.

Para ello nos crearemos un nuevo control, al que llamaremos OllyTextBOX.vb:


(Haz click  para ampliar la imagen)

Tal y cómo mostramos en el tutorial anterior modificaremos el código de <nombre_del_control>.Designer.vb:


(Haz click para ampliar la imagen)

En este caso, modificaremos el código que genera Visual Studio y lo cambiaremos por el código que está resaltado.

Nota: Al hacer un Inherits System.Windows.Forms.TextBox, nuestro control va a heredar TODOS los eventos, propiedades y métodos del control TextBox.

Bien, una vez realizado este cambio y compilado el programa, veremos que tenemos disponible nuestro nuevo control en el "Cuadro de herramientas":

Ahora toca modificar la clase del control, que por defecto estará en blanco:

Añadiremos el siguiente código:

Si compilamos el programa e insertamos el nuevo control en el formulario, veremos que ahora tenemos una nueva propiedad, que se llama PropiedadNueva:

Obviamente, tal y como está el código, esta "propiedad" no hace nada. Más que nada la he puesto para que veais (esa gente de poca fé 😉 que dicha propiedad es "nueva"

Ahora bien, si añadimos el siguiente código a la clase:


(Haz click para agrandar la imagen)

Aquí véis que hemos añadido otra propiedad nueva, en este caso la hemos llamado OnlyNumbres y es de tipo booleano.

Si os fijáis, hemos "overraideado" el procedimiento OnKeyPress de tal forma que cuando la propiedad OnlyNumbers sea "True" solo se puedan introducir números en la caja de texto.

Si volvemos a compilar y metemos el nuevo control en nuestro formulario, vemos que efectivamente, tenemos una propiedad que se llama OnlyNumbers: (OMG, WTF, PQC!!!) :

Pero vamos a ir un paso más allá, vamos a definir dos nuevas propiedades. Una propiedad la llamaremos ActivarProteccion y otra la llamaremos MsgNoCopiar, donde la primera es de tipo booleano y la segunda es de tipo cadena (string)


(Haz click para agrandar la imagen)

Al mismo tiempo, lo que vamos a hacer es "Overraidear" el procedimiento WndProc de esta forma:


(Haz click para agrandar la imagen)

Los programadores de C / C++ estarán mas acostumbrados a ver el procedimiento WndProc que los programadores de Visual Basic. Básicamente, el procedimiento WndProc nos informa de los mensajes de Windows, existen un mogollón de mensajes, tal y como se puede ver en este link.

Pues bien, básicamente lo que hemos hecho es que cuando se detecte el mensaje "copiar texto", "pegar texto" o "botón derecho del ratón pulsado" (normalmente los pop-ups para copiar/pegar se sacan con el botón derecho del ratón) y además la propiedad ActivarProteccion sea verdadera, se impedira copiar o pegar texto en nuestro control. Si esto sucede, se muestra un Mensaje con el contenido de la nueva propiedad MsgNoCopiar.

Bien, aprovecharemos para declarar unos valores por defecto de esta forma:


(Haz click para agrandar la imagen)

Y dentro del InitializeComponent (que está dentro del <nombre_control>.Designer.vb) definiremos estos valores:


(Haz click para agrandar la imagen)

Bien, ahora compilaremos de nuevo el código e iremos a nuestro formulario en vista diseño y efectivamente, al añadir nuestro nuevo control al formulario vemos que éste tiene las propiedades ActivarProteccion:

Y MsgNoCopiar:

Como podéis apreciar, cuando hacemos click sobre esas propiedades nuevas que hemos definido no se muestra la descripción, únicamente el nombre de la propiedad.

Para solucionarlo, tendremos que añadir el NameSpace System.ComponetModel a nuestra clase y usar los /tags para documentar cada propiedad:


(Haz click para agrandar la imagen)

(Nota: Hay abundante información en la MSDN de cómo utilizar este NameSpace)

Una vez realizado dicho cambio, como podéis ver, ahora si que se muestra una "descripción" de lo que hace la propiedad "personalizada":

El código completo de la clase OllyTextBOX.

Bien, compilaremos de nuevo el programa y en nuestro formulario lo diseñaremos con dos "CheckBox" y un OllyTextBOX:

El "increible" código de nuestro formulario es este:


(Haz click para agrandar la imagen)

Prueba de hacer un CTRL+C, un CTRL+V dentro del OllyTextBOX cuando la propiedad ActivarProteccion sea True, o prueba de introducir letras cuando la propiedad OnlyNumbres está a True.

Como habrás podido ver, NO HEMOS ESCRITO ni una linea de código en nuestro formulario para impedir que la caja de texto solo acepte números o se pueda copiar y pegar texto.

Esta misma técnica se puede usar para lo que quieras, el límite lo pones tú 😉

Espero vuestros comentarios.

 

Saludos.
mov eax,ollydbg; Int 13h

 

Descargar proyecto .NET Tutorial 18
(41 KB. Visual Studio 2008) 

.NET Tutorial 17. Cómo cambiar la apariencia de cualquier control de Windows

Hoy vamos a ver lo simple que puede resultar cambiar el aspecto visual de prácticamente cuanlquier control de Windows.

En este ejemplo en particular vamos a cambiar la apariencia del control "TAB Control" y le daremos este nuevo aspecto:

Una de las ventajas de cambiar el aspecto de los controles, es que dicho aspecto se mantendrá en todos los sistemas operativos, por lo tanto, el aspecto de ese TAB Control "modificado" se verá igual en Windows XP, en Windows Vista o incluso en Windows Seven.

Los pasos a realizar son los siguientes:

1) Añadir un nuevo "Control de usuario" a nuestro proyecto:


(Haz click para agrandar la imagen)

una vez añadido el control, mostraremos todos los archivos en el explorador de soluciones:

Al mostrarse todos los archivos, veremos que el nuevo control que hemos añadido también dispone de otro arachivo, llamado <nombre_del_control>.Designer.vb:

2) Hacer click en el archivo <nombre_del_control>.Designer.vb para mostrar la pantalla de código.
Por defecto se mostrará el siguiente código, que ha generado Visual Studio de forma automática:


(Haz click para agrandar la imagen)

3) Cambiar el código por el código resaltado en la siguiente imagen:


(Haz click para agrandar la imagen)

Al hacer este cambio, veremos que el "icono" del explorador de soluciones de nuestro nuevo control ha cambiado:

4) Entrar en la pantalla de código del control:

Al entrar en la pantalla de código del nuevo control, veremos una clase totalmente en blanco.

5) Lo que haremos es "cambiar" los métodos OnPaint y OnPaintBackground para "dibujar" nuestro control con un aspecto "distinto".

El códio completo lo podéis ver AQUÍ.

Una vez que se han cambiado la clase compilaremos el programa. Al hacerlo debería aparecer un "nuevo" control en el "Cuadro de herramientas":

Si ahora arrastramos ese nuevo control a nuestro formulario:

Si además, añadimos el control "TAB Control" original, podremos apreciar la diferencia:

Y tal y como habiamos dicho, nos dá igual el sistema operativo donde se está ejecutando el programa. Aqui podéis ver el mismo control ejecutándose en Windows XP:

 

¿Complicado?. Creo que en absoluto.

En este caso hemos elegido un TAB Control, pero esta misma técnica se puede utilizar para cualquier control de Windows que uséis en vuestros proyectos (Labels, TextBox, ListBox, ComboBox, ListViews, ProgressBar, etc)

 

Espero vuestros comentarios.

 

Saludos.
mov eax,ollydbg; Int 13h  


Ollydbg ProSignature

.NET Tutorial 16. Colisiones 2D

Vamos a ver lo sencillo que resulta realizar "colisiones" en 2D bajo .NET

Para este ejemplo controlaremos un "caza de combate" que tendrá que destruir al típico "final boss" de casi cualquier juego de "naves". Hete aquí una foto del resultado de este tutorial:


(Haz click para agrandar la imagen)

Tal y como ya hemos visto en tutoriales anteriores, en cualquier sprite 2D tendremos lo siguiente:

  • Un sprite, independientemente de la "forma" que tenga, será siempre un "rectángulo".
  • Siempre deberemos tener en cuenta la coordenada superior izquierda, que tomaremos como "origen" del sprite.
  • También tendremos que tener en cuenta el "ancho" y el "alto" del sprite.

Teniendo en cuenta estos 3 puntos, la "región" o contorno de nuestros sprites serán los siguientes:


(Haz click para agrandar la imagen)

Como podéis ver, los rectangulos rojo y naranja representan toda el "área" que ocupan nuestros sprites en la pantalla de juego.

A bote pronto (y sobre todo depende de la "forma" de los sprites) con estas dos "áreas" (o regiones) podríamos llegar a calcular la colisión. Para ello, lo único que tendríamos que ver es si cualquiera de las dos "áreas" está dentro de la otra.

¿Y esto cómo se hace?

Pues fácil, con la función Rectangle.Intersect

Rectangle.Intersect devuelve un objeto de tipo "Rect" si existe una "intersección" entre dos "áreas"

El uso es tremendamente simple:

Dim isectRect As Rectangle = Rectangle.Intersect(rectBoss, rectPlayer)

Si hay "intersección", el alto y ancho de isectRect serán distintos de 0. En caso contrario no hay intersección entre rectBoss y rectPlayer.

Recordar que un objeto de tipo "Rect" se define como:

  1. Origen coordenada X
  2. Origen coordenada Y
  3. Ancho
  4. Alto

De ahí lo de "recordar" la coordenada superior izquierda (X,Y) y el ancho y alto del sprite.

Bien, como hemos dicho, este método nos serviría si los sprites fuesen "más o menos" de forma rectangular.

Como esto no será siempre así podríamos llegar a situaciones como la de esta foto:


(Haz click para agrandar la imagen)

En esta imagen, si que hay "intersección" entre el "área" del sprite de nuestra nave (rectángulo rojo) y el área del sprite del boss (rectángulo naranja)

Obviamente ahí vemos claramente que la nave (o el boss) realmente no se están tocando entre si, por lo tanto, esa situación no debería considerarse como "colisión".

La solución para este "problema" es "parametrizar" una seríe de regiones que actuarán como las regiones de colisión, utilizando para ello también la función Rectangle.Intersect

En nuestro ejemplo hemos definido las siguientes regiones (tanto para el boss como para nuestra nave):


(Haz click para agrandar la imagen)

Cuando dos de estás "regiones" tienen intersección es cuando consideramos que hay colisión:


(haz click para agrandar la imagen)

Como habréis comprobado esta técnica es tremendamente simple a la par que efectiva.

Existen más métodos de colisión, por ejemplo lo que se conoce como "Pixel Perfect Collisión", dónde aquí la colisión si que se realiza al "milímetro" o mejor dicho "al pixel".

 

PD: Antes de que nadie diga nada, este ejemplo se usa para mostraros la colisión por regiones, YA SÉ que la nave se mueve "lenta" y el boss también. El tema de velocidad lo solucionaremos en las próximas entregas utilizando para ello hilos (Threads).

PD 2: Sigo recordando que el botón de comentarios no muerde 😉

 

Saludos.
mov eax,ollydbg; Int 13h  

Descargar proyecto .NET Tutorial 16
(129 KB. Visual Studio 2008)

Controles:

  • Cursores para mover la nave
  • "C" para mostrar/ocultar el contorno de los sprites
  • "R" para mostrar/ocultar la regiones de colisión
  • "M" para que el boss se mueva automáticamente o se pare de mover
  • "H" para mostrar/ocultar el bitmap de fondo

 

.NET Tutorial 15. Jugando a ser James Bond: cifrando y descifrando textos

A lo largo de la historia, el ser humano siempre ha tenido la necesidad de esconder sus más profundos secretros. Ya lo dijo en su dia Robert Reford, encarnando a Martin Bishop en la excepcional película Los fisgones (Sneakers, 1992): "Too many secrets"

Hoy vamos a ver lo simple que es realizar una tarea de "cifrado" y "descifrado" desde .NET:

.NET dispone de un namespace totalmente orientado a trabajar con algoritmos de clave simétrica. El namespace es System.Security.Cryptography

Ahi disponemos de unos cuantos metodos de cifrado y descifrado.

El que hemos usado para este ejemplo es el conocido como Rijnadael y es posiblemente el más seguro (por lo menos, públicamente, a saber lo que tienen montado los chicos de la NSA) hasta la fecha.

Al contrario de lo que pueda parecer a priori, realizar un cifrado / descifrado utilizando las clases y métodos que están en System.Security.Cryptography es tremendamente simple.

Para ello nos hemos creado una clase, a la que hemos llamado Crypto.

Dicha clase tiene dos funciones:

EncriptacionRijndael ( )
DesencriptacionRijndael ( )

La función EncriptacionRijndael se le pasará como argumento el texto que se quiere cifrar y nos devolverá un texto "cifrado" con el algoritmo Rijndael.

Por el contrario, la función DesencriptarcionRijndael se le pasará como argumento un texto cifrado y nos devolverá el texto "descifrado".

Obviamente, deberéis cambiar las contraseñas por las vuestras propias, en este caso los valores de las variables _key y _iv.

Para finalizar he incluido una "encriptación" basada en XORs, que es posiblemente el método más viejo y rápido para cifrar y descifrar un texto, aunque claro está, también es el menos seguro.

 

Cualquier comentario será bienvenido. 😉
 

Saludos.
mov eax,ollydbg; Int 13h  

Descargar proyecto .NET Tutorial 15
(42 KB. Visual Studio 2008)

.NET Tutorial 14. Gráficos 2.5D

En el mundillo videojuegil se conoce como gráficos 2.5D a la proyección isométrica. En esta entrega realizaremos lo siguiente:

Existen grandes exponentes en este género. Quizás el más popular sea Diablo. Aunque existen muchísimos y muy antiguos: La abadía del crimen, Knight Lore, Head Over Heels, Alien 8, Ultima Online, etc, etc.

Quien no se acuerda el mítico Head Over Heels:


(Versión para Amiga)

O no el menos mítico Abadía del Crimen:


(Remake Abadía del Crimen en Informativos Tele5)

O el mítico Knight Lore:


(Knight Lore en su versión para Spectrum 48K)

Hay que recordar que el Knight Lore es del siglo pasado, sí, concretamente del 1984 y para su época supuso un antes y un después en la historia de los videojuegos. Algo así como lo que ocurriría con la aparición de DOOM, casi 10 años después, que también supuso otro hito en la programación de los videojuegos.

Cito de la wikipedia:

El entorno de juego, que utiliza perspectiva isométrica permite no sólo moverse en tres dimensiones sino también interaccionar con objetos mediante una física sencilla pero efectiva. El motor utilizado llevó el nombre de Filmation y se convertiría en la marca de la casa.

Esta técnica Filmation era impresionante para la época ya que introdujo grandes innovaciones a todos los niveles: marcó un antes y después de la historia de los juegos, siendo aún hoy en día una referencia a tener en cuenta. Los autores, que fueron elevados instantáneamente a la categoría de genios (fama alimentada por su notoria reticencia a ser entrevistados o fotografiados) eran conscientes de la revolución que iba a suponer el lanzamiento de este juego y de hecho retrasaron su salida hasta después del Underwurlde, a pesar de que Knight Lore había sido desarrollado con anterioridad.

Con esta técnica de dibujado se intenta dar una "pseudo" sensación de tridimensionalidad, ya que el juego no deja de ser un juego 2D pero "visto" de una forma en "perspectiva"

En nuestro caso, tomaremos como base el siguiente gráfico:

Se supone que dicho gráfico es de 64 x 32 pixels.

A priori, el orden para dibujar estos gráficos sería el siguiente:

En los juego isométricos se introduce una nueva coordenada "ficticia" (recordad, que sigue siendo 2D): La coordenada Z o también llamada produndidad.

En un juego 3D la coordenada Z ya no es ficticia, sino real, donde tendremos las coordenadas X, Y y Z

En un típico juego 2D solo tendremos la coordenada X e Y.

En la siguiente figura vemos la sensación de "profundidad" que conseguimos con la perspectiva isométrica:

Vemos claramente que el bloque amarillo está "detrás" de los bloques verdes.
Si comparamos la imagen anterior con el orden de dibujado que hemos visto antes, podríamos llegar a la erronea conclusión que el orden de dibujado es correcto.

Todo funcióna "bien" mientras no tengamos bloques que están "en mitad de dos o más bloques adyacentes":

o también:

Como véis, si utilizamos el orden de dibujado que habiamos previsto, existen determinadas posiciones donde se "solapan" varios bloques.

El orden correcto de dibujado para impedir este solapamiento es el siguiente:

De esta forma se consigue el efecto deseado.
Para ello, cada uno de los bloques de nuestro juego dispone de una propiedad, a la que llamamos Depth (o en castellano: Profundidad).

Como estamos en un entorno que no deja de ser un entorno 2D, nuestros gráficos solo tienen 2 dimensiones: X e Y o tambien, Filas y Columnas.

De tal forma, que para cada Fila, Columna se calcula su "profundidad" con la siguiente fórmula:

Profundidad = (51 * (Fila + 1) + 50 * (Columna + 1)) * 4 

Cada vez que el personaje se mueve se se calcula su profundiad en función de la (fila,columna) que ocupa asi cómo la profundidad del bloque que está justo a la derecha y abajo:

La profundidad de dicho bloque (del que está marcado con una flecha) siempre será: (Profundidad del jugador – 1). De esta forma, dicho bloque se dibujará antes que el jugador y no se producirá el solapamiento.

Por último, se ordenan todos los bloques y se dibujan primero los que tienen una profundidad menor.

En el ejemplo que os muestro hay muchas cosas por pulir, pero eso ya lo iremos viendo en sucesivas entregas. De todos modos, imagidad lo que se podría llegar a conseguir con unos gráficos un "poco currados".

 

Saludos.
mov eax,ollydbg; Int 13h 

 

Descargar proyecto .NET Tutorial 14
(55 KB. Visual Studio 2008)

Anexo Tutorial 13: Recompilando un ensamblado ofuscado

Os presento un anexo a lo explicado en el Tutorial 13.

No he querido hacer una entrada "al uso" por los motivos que explico dentro del anexo.

En este anexo se podrá comprobar que efectivamente, es posible "recompilar" un ejecutable ofuscado, cosa que a priori parecía imposible.

Os recuerdo lo comentado al principio del Tutorial 11: Esta serie de tutoriales no pretenden en absoluto ser unos tutoriales de "cracking".

Con este anexo doy por concluida de momento esta parte del tutoriales sobre la seguridad.

En breve espero escribir articulos más interesantes sobre todo mas orientados a la programación. Aunque eso será despues de unas merecidiiiisimas vacaciones.

PD: Desde aquí aprovecho para agradecer a todos aquellos usuarios, anónimos o no, que dejan sus comentarios es este humilde blog. Gracias!!!. 😉 

 

Saludos.
mov eax,ollydbg; Int 13h  

 

Descargar Anexo Tutorial 13
(1.126 KB. Documento PDF)

.NET Tutorial 13. Como »Juankear» aplicaciones .NET y estrategias para evitarlo (Parte II)

Tal y como vimos en la anterior entrega, es "relativamente fácil" fisgonear en el código de una aplicación .NET. A continuación veremos varias formas de impedir esto:

Evitando el desensamblado

La forma más simple de evitar el desensamblado es añadir la siguiente directiva en cualquier módulo / clase de nuestro proyecto:

Imports System.Runtime.CompilerServices
<Assembly: SuppressIldasmAttribute()>
 

Si hacemos esto, al cargar nuestro exe dentro del ildasm obtendremos este "bonito" mensaje:

Añadir esta directiva puede persuadir a un "juanker casual". Eludir este "trick" es relativamente fácil para un cracker experimentado. Aunque como ya expliqué en la entrega anterior nuestra intención es eludir a esos "aprendices" de juankers, ya que contra los pr00s poco o nada hay que hacer ¬¬

 

Ofuscando el código

Esta es sin duda la parte más interesante del "asunto". El termino ofuscar tal y como indica sirve para como yo digo "marear la perdiz". El EXE se podrá seguir abriendo con el .NET Reflector u otras herramientas similares (algunos ofuscadores incluso impiden que el exe pueda abrirse con el .NET Reflector).

Lo que ocurre es que una vez ofuscado el código, éste ya no será tan "comprensible" para nuestros amigos "juankers"

A continuación puedes ver el "Tutorial11" después de pasarlo por un "Ofuscador"


(Haz click para agrandar la imagen)

Este es el Evento "Click" del Formulario de Login:


(Haz click para agrandar la imagen)

Compáralo con el mismo código sin ofuscar que vimos en la entrega anterior:

Y esta es la función "VerificarLogin" una vez ofuscada:

Que nada o poco tiene que ver con la función "VerificarLogin" que vimos en la entrega anterior:

 

Existen ofuscadores y "ofuscadores". Visual Studio (creo que solo en versiones "Professional" o superiores) dispone de un ofuscador "gratuito" llamado Dotfuscator Community Edition.

Uno de los inconvenientes de la versión del Dotfuscator Community Edition es que no permite ofuscar cadenas. Y claro, esto es un grave "inconveniente", ya que de poco o nada me sirve que "ofusque" el procedimiento VerificarLogin y lo llame $123klÑ342_p23sd# si luego se sigue viendo Return (Password = "1234") no sé si me entendéis.

Otro problema que le he encontrado al Dotfuscator Community Edition es que hay veces que al ofuscar y crear el nuevo ejecutable, dicho ejecutable es "inservible" y siempre genera un error al iniciarse. Posiblemente esto no ocurra con programas pequeños. Yo tengo aplicaciones que tienen más de 200.000 líneas de código (como veis de "pequeño" tiene poco) y el Dotfuscator se atraganta con dichas aplicaciones.

Buscando por internet encontré un ofuscador gratuito y que de momento no me ha dado ningún problema.

Se trata del Eazfuscator.

Es tremendamente simple de usar, ofusca cadenas, se traga perfectamente mis aplicaciones tochas. La última versión incluso permite ofuscar ensamblados para XNA 3.0.

Funciona incluso en las versiones "Express" de Visual Studio. Además no podrás usar el ilasm para volver a ensamblar un exe "modificado" ya que Eazfuscator añade un "resource" con una firma "digital" del exe original, que impide que se vuelva a "recompilar". (Actualización 05/08/2009: Esto no es del todo cierto, tal y como se puede ver en el Anexo Tutorial 13)

El único "pero" es que no permite especificar que clases o procedimientos quieres ofuscar. Te ofusca todo. Pero "joer" es gratuito!!! 🙂

Si estas dispuesto a pagar te recomiento {smartAssembly}.  En mi opinión es simplemente genial. Puedes decidir que clases, procedimientos o funciones quieres ofuscar. Además, no podrás abrir los EXEs con .NET Reflector, ni desemsamblarlos ni nada. El uso es también muy simple y la atención al cliente 10/10.

 

Un quebradero de cabeza más: Managed Spy 

Ante todo decir que esta "utilidad" está en la propia MSDN, en concreto en este artículo:
http://msdn.microsoft.com/en-us/magazine/cc163617.aspx

Como habéis adivinado (y si no ya os lo digo yo) es la versión "tuneada" del Spy++ que se instala en la carpeta Visual Studio Tools pero para aplicaciones ".NET" (de ahí lo de Managed)

¿Y digo "tuneada" por qué? La utilidad Spy++ se utiliza para obtener los identificadores de "ventana" de cualquier control de cualquier aplicación que se está ejecutando. Con dichos identificadores es posible llamar a determinadas APIs de Windows para "alterar" las propiedades de dicho control.

Managed Spy ya hace esto por nosotros y la verdad, a mi me ha dejado bastante "descolocado" y ahora veréis el por que:

Ejecutamos nuestro Tutorial11 y ponemos un password "incorrecto".

Si recordáis al poner un password "incorrecto" había cieras opciones desabilitadas.

Pues bien…ejecutamos ahora el Managed Spy:


(Haz click para agrandar la imagen)

Vemos que hay un "objeto" que se llama "GrpBoxPremium" y al que podemos acceder a sus propiedades como si estuviesemos en el IDE de programación (LOL!!!!):


(Haz click para agrandar la imagen)

Si cambias la propiedad Enabled a su valor True: sorpresa!!!!:


(haz click para agrandar la imagen)

Pero es que eso no es todo. Puedes CAMBIAR ABSOLUTAMENTE CUALQUIER PROPIEDAD de CUALQUIER CONTROL. Simplemente "O-EME-GE"! ¬¬


(Haz click para agrandar la imagen)

Por lo tanto, visto lo visto, no creo que sea una buena opción poner "cosas invisibles" o "deshabilitadas". Y si lo haces, asegúrate que cuando hagan click en dichas opciones, realmente tengan acceso a dichas opciones, es decir, en el evento Click o en el que sea, deberías añadir algún tipo de comprobación de si el usuario tiene o no permiso para ejecutar aquella opción, no vaya a ser que este ejecutando el Managed Spy (u otra cosa similar).

Estoy investigando si esto del Managed Spy se puede evitar de algún modo. Os comentaré algo si encuentro el cómo hacerlo.

PD: por cierto, el botón "Comentar" no muerde 🙂

 

Saludos.
mov eax,ollydbg; Int 13h