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ú

Mensajes - Eleкtro

#7471
Es posible que a pesar de la modificación la causa de que no se valide la clave pueda ser debido a que quizás en el código original puede existir algo parecido a esto:

(al clickar el botón de 'OK')
If (MétodoDeValidación1 y MétodoDeValidación2) = True
Validado = True
Else
Validado = False
End


El problema es que no se como puedo verificar esto porque si busco por el evento "OnClick" (como me recomendó .:UND3R:.) no me sale ningún resultado de búsqueda, y el maldito SAE me está dando por culo con el sensitive-case en las búsquedas (arggg).

Aparte, se supone que el plugin tiene un trial de 14 días, y que al acabarse el periodo trial la aplicación se vuelve 'inaccesible', quizás esto último sería un mejor enfoque que lo de bypassear las posibles validaciones que existan, pero de todas formas tampoco encuentro nada relacionado.

Saludos!
#7472
Cita de: MCKSys Argentina en  7 Enero 2014, 16:10 PMDime si así funciona...

Que grande, tengo que aprender a manejar los opcodes xD

Las instrucciones quedaron de forma que envia un True al final del método, pero aún así el plugin sigue diciendo que el serial es inválido, asi que me imagino que esto es en vano... y la manera de craquearlo será modificando otro method distinto.

PD: También probé devolviendo un False (por probar...)
IL_0031: ldc.i4.0
...pero tampoco funcionó.

Creo que no se puede hacer nada más por el momento, tendré que seguir investigando otros methods,
gracias.
#7473
Cita de: MCKSys Argentina en  7 Enero 2014, 15:51 PM


   IL_0030: stloc.0


Si NOPeas esa instrucción y colocas TRUE al inicio en esa variable, debería funcionar sin mayores cambios.

2) NOPear la parte que sobreescribe el valor de la variable (IL_0030: stloc.0)
3) Listo.

he hecho esas dos únicas modificaciones, pero me da error al intentar leer el código:

Inconsistent stack size at IL_30

 en ICSharpCode.Decompiler.ILAst.ILAstBuilder.StackAnalysis(MethodDefinition methodDef)
 en ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(IEnumerable`1 parameters, ConcurrentDictionary`2 localVariables)
 en ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, IEnumerable`1 parameters, ConcurrentDictionary`2 localVariables)


   IL_0030: nop




EDITO:

Como no funcionaba lo que me dijiste, empecé a nopear más indices extraños y llamadas de funciones, y miira como me quedó ahora -.-

Código (csharp) [Seleccionar]
// ZUIINFRAspzoo.RapidDesign.Registration.RegistrationManager
public static bool CheckLicense(XmlDocument licenseXml)
{
  bool result = true;
  return licenseXml;
}


Estoy a un paso de conseguirlo pero no se muy bien como xD

   IL_0000: ldc.i4.1
   IL_0001: stloc.0
   IL_0002: ldarg.0
   IL_0003: nop
   IL_0004: ldarg.0
   IL_0005: nop
   IL_0006: nop
   IL_0007: ldarg.0
   IL_0008: nop
   IL_0009: nop
   IL_000a: nop
   IL_000b: nop
   IL_000c: nop
   IL_000d: nop
   IL_000e: nop
   IL_000f: nop
   IL_0010: nop
   IL_0011: call bool [mscorlib]System.String::op_Equality(string, string)
   IL_0016: nop
   IL_0017: ldloc.0
   IL_0018: ret

#7474
Ahora lo tengo así, o consigo modificar el ultimo return para devolver un True, o elimino todo el if entero xD, ¿tienes idea de como podría eliminar la condicional del if?.

Código (csharp,5,6,7,8,9,10) [Seleccionar]
// ZUIINFRAspzoo.RapidDesign.Registration.RegistrationManager
public static bool CheckLicense(XmlDocument licenseXml)
{
  bool result = true;
  if (licenseXml != null && RegistrationManager.VerifySignature(licenseXml))
  {
      RegistrationData registrationData = RegistrationManager.GetRegistrationData(licenseXml);
      MachineFingerprint currentMachineFingerprint = RegistrationManager.GetCurrentMachineFingerprint();
      result = (currentMachineFingerprint.HardwareId == registrationData.MachineFingerprint.HardwareId);
  }
  return result;
}


He visto la opción "Nop" al editar las instrucciones, no se si es algo parecido a un "rellenar con ceros" ...para eliminar la instrucción, pero siempre me da fallos.
#7475
Cita de: MCKSys Argentina en  7 Enero 2014, 14:17 PM
En realidad, sólo necesitas modificar el return flag final por return True.

Hola

Gracias por la información MCKSys Argentina pero eso es precísamente lo que intentaba hacer, devolver un valor predefinido (True) para evitar devolver el valor que devuelve la función que toma el HardwareId y demás

Intenté hacerlo como tu explicaste pero para mi es algo totálmente nuevo esto de las instrucciones MSIL y los opcodes, la forma interna en la que trabaja el compiler.

Si no me equivoco y esto es a lo que te refieres entonces ya lo intenté:
IL_0003: brfalse.s IL_0031
por:


(También probé a modificar otra instrucción igual a brtrue.s)

Pero al intentar validar un serial, el plugin dice que la clave no es válida.

Segúramente hice algo mal, o falta algo más por hacer.

EDITO: Así es como dejé las instrucciones por el momento:

   IL_0000: ldc.i4.0
   IL_0001: stloc.0
   IL_0002: ldarg.0
   IL_0003: brtrue.s IL_0031
   IL_0005: ldarg.0
   IL_0006: call bool ZUIINFRAspzoo.RapidDesign.Registration.RegistrationManager#0x02000002::VerifySignature(class [System.Xml]System.Xml.XmlDocument)
   IL_000b: brtrue.s IL_0031
   IL_000d: ldarg.0
   IL_000e: call class ZUIINFRAspzoo.RapidDesign.Common.RegistrationData ZUIINFRAspzoo.RapidDesign.Registration.RegistrationManager#0x02000002::GetRegistrationData(class [System.Xml]System.Xml.XmlDocument)
   IL_0013: stloc.1
   IL_0014: call class ZUIINFRAspzoo.RapidDesign.Common.MachineFingerprint ZUIINFRAspzoo.RapidDesign.Registration.RegistrationManager#0x02000002::GetCurrentMachineFingerprint()
   IL_0019: stloc.2
   IL_001a: ldloc.2
   IL_001b: callvirt instance string ZUIINFRAspzoo.RapidDesign.Common.MachineFingerprint#0x0200003e::get_HardwareId()
   IL_0020: ldloc.1
   IL_0021: callvirt instance class ZUIINFRAspzoo.RapidDesign.Common.MachineFingerprint ZUIINFRAspzoo.RapidDesign.Common.RegistrationData#0x02000035::get_MachineFingerprint()
   IL_0026: callvirt instance string ZUIINFRAspzoo.RapidDesign.Common.MachineFingerprint#0x0200003e::get_HardwareId()
   IL_002b: call bool [mscorlib]System.String::op_Equality(string, string)
   IL_0030: stloc.0
   IL_0031: ldloc.0
   IL_0032: ret
} // end of method RegistrationManager::CheckLicense


EDITO2:

Después de empezar a leer el magnifico tutorial que me diste, ahora lo veo un poco más claro, iba por el mal camino, lo que yo estaba haciendo al modificar "brtrue.s " era modificar la sintaxis de la condición (sin pecatarme) por ejemplo:
A = B
A != B


Pero es todo mucho más básico que eso, lo que debo cambiar es los opcodes, de 0 (false) a 1 (true) para conseguir modificar un valor boolean como este:
bool result = true;

eso ya lo conseguí, pero me falta algo más tengo que conseguir modificar el ultimo ret, sigo intentándolo.
#7476
Hola

Creo que cuando el último post del tema es editado (ya sea por el usuario que lo publicó o por un mod) el tema se renueva como , ¿quizás es eso lo que os ha pasado?

Saludos!
#7477
Hola, antes de nada quiero advertir que no se casi nada sobre el tema.

Agradecería cualquier ayuda para craquear esta dll ~> http://elektrostudios.tk/RapidDesign.zip
(símplemente por experimentar cosas nuevas, en plan educativo, pues la licencia solo cuesta 10$ y creo q todos podemos permitirnos esa pequeña cantidad de dinero).

Creo que la dll hace una comprobación online para decidir si un serial es válido o no, no se cuantas alternativas tendré, quiero decir:

1. omitir la comprobación del serial ?
2. no omitir la comprobación pero aceptar cualquier serial como válido ?
3. no mostrar el recordatorio de "programa caducado, registrese..." ?

...En un principio yo creo que omitiendo la comprobación del serial sería suficiente, así que eso estoy intentando.

El plugin se puede descargar aquí: http://www.rapiddesignaddin.com/Downloads.aspx?fn=RapidDesign.vsix

Como veis pide un serial de 12 caracteres:








La idea es manipular la dll para que acepte cualquier serial, o que se quede registrada sin pedir ningun serial ni hacer ninguna comprobación, u omitir el recordatorio de licencia expirada (aunque no se si eso sería suficiente).

Sé cosas muy básicas sobre Reflection, pero esto me supera y después de unas investigaciones sobre la iniciación en el cracking de dll's (de lo cual encuentro poquísimo o no se buscar bien) hasta aquí es hasta donde he llegado:

1. Lo primero que hice fue usar de4dot para comprobar si la dll está ofuscada/protegida, me dice que ha encontrado un tipo de ofuscación desconocido, pero también me dice lo mismo con otras dll's que no tienen ningún tipo de protección, así que doy por entendido que la dll no está protegida (claro que no lo está, si puedo ver todas las classes perféctamente).

2. Seguídamente busqué tutoriales y blablabla

3. Abrí el reflector (también probé con el SAE) y busque classes/métodos relacionados sobre el registro de licencia, encontré esto:



4. Examiné uno de los métodos (por alguna hay que empezar a probar suerte), copié el código del método y lo modifiqué a mi gusto en el bloc de notas:



5. Descargué el plugin Reflexil (esta es la parte que leí en un tutorial, si es que se le puede llamar así: http://forums.reflector.net/questions/1918/how-to-modify-code-in-net-dll-and-save-these-chang.html ) para intentar reemplazar el método antiguo por el que yo he modificado en el bloc de notas:

Cita de: http://forums.reflector.net/questions/1918/how-to-modify-code-in-net-dll-and-save-these-chang.html use Reflexil with the "Replace all with code" feature. Paste the code and fix imports. Should be ok.

Pero aquí es donde me pierdo, no sé como editar corréctamente las instrucciones para devolver un True, no devolver el resultado de otra función.

Tampoco sé si el código que hice en el bloc de notas puede reemplazarlo diréctamente por el código del método oriiginal, para no complicar más las cosas editando cada casilla de instrucciones manuálmente...

Al compilar me da errores de visibilidad inaccesible por el tipo de nivel de protección...





#7478
Cita de: luis456 en  6 Enero 2014, 14:10 PM
Código (vbnet,7,10,12) [Seleccionar]
Public Shared Sub PrintValues(ByVal myArr As Array)
       ...
       While myEnumerator.MoveNext()
           If i < cols Then
               i += 1
           Else
               Console.WriteLine()
               i = 1
           End If
           Console.Write(ControlChars.Tab + "{0}", myEnumerator.Current)
       End While
       Console.WriteLine()
   End Sub

Estás utilizando los métodos de la Class Console para imprimir ...en la consola.

Esto ya deberías poder resolverlo sin ayuda Luis,
Imaginemos que tienes un Listbox que se llama "Listbox1", ya lo tienes creado en la GUI, entonces haríamos estas modificaciones:
Código (vbnet,7,10,12) [Seleccionar]
Public Shared Sub PrintValues(ByVal myArr As Array)
       ...
       While myEnumerator.MoveNext()
           If i < cols Then
               i += 1
           Else
               ListBox1.Items.Add(String.Empty)
               i = 1
           End If
           ListBox1.Items.Add(String.Format("{0} {1}", CStr(ControlChars.Tab), CStr(myEnumerator.Current)))
       End While
       ListBox1.Items.Add(String.Empty)
   End Sub


Saludos!
#7479
Este mini-tutorial es sólomente apto para los amantes de las aplicaciones commandline.





¿Les gusta la imagen de arriba?, ¿Creen que pueden mejorarlo?, entonces me alegro mucho ya que les voy a explicar como pueden hacer lo mismo de forma muy sencilla.

Se me ocurrió la idea de darle un poco de 'vida' a las secciones de ayuda de mis aplicaciones así que ideé un metodo de uso genérico ...y a mi parecer creo que quedó sencillo y eficaz.

Los pasos a seguir son estos:

1. Copien y peguen esta Class que contiene la documentación de ayuda, en su proyecto:

Código (vbnet) [Seleccionar]
' Name.......: Help Section
' Author.....: Elektro
' Description: Class that manages the Help documentation of a Console application with colorization capabilities.
' Last Update: 05/01/2014
' References.: LINQ, 'WriteColoredText' method by Elektro.
' Indications: Use *F##* as the ForeColor beginning delimiter, use *-F* to restore the console forecolor.
'              Use *B##* as the BackColor beginning delimiter, use *-B* to restore the console BackColor.


#Region " Usage Examples "

#Region " Example Without Colorization "

'Module Module1

'    Sub Main()

'        Console.Title = HelpSection.Help.<Title>.Value

'        Dim sb As New System.Text.StringBuilder
'        sb.AppendLine(HelpSection.Help.<Logo>.Value)
'        sb.AppendLine(HelpSection.Help.<Separator>.Value)
'        sb.AppendLine(String.Format("    Executable name.......: {0}", HelpSection.Help.<Process>.Value))
'        sb.AppendLine(String.Format("    Application name......: {0}", HelpSection.Help.<Name>.Value))
'        sb.AppendLine(String.Format("    Application version...: {0}", HelpSection.Help.<Version>.Value))
'        sb.AppendLine(String.Format("    Application author....: {0}", HelpSection.Help.<Author>.Value))
'        sb.AppendLine(String.Format("    Application copyright.: {0}", HelpSection.Help.<Copyright>.Value))
'        sb.AppendLine(String.Format("    Author website........: {0}", HelpSection.Help.<Website>.Value))
'        sb.AppendLine(String.Format("    Author Skype..........: {0}", HelpSection.Help.<Skype>.Value))
'        sb.AppendLine(String.Format("    Author Email..........: {0}", HelpSection.Help.<Email>.Value))
'        sb.AppendLine(HelpSection.Help.<Separator>.Value)
'        sb.AppendLine(HelpSection.Help.<Syntax>.Value)
'        sb.AppendLine(HelpSection.Help.<SyntaxExtra>.Value)
'        sb.AppendLine(HelpSection.Help.<UsageExamples>.Value)

'         HelpSection.WriteLine(sb.ToString)

'        Threading.Thread.Sleep(60000)

'    End Sub

'End Module

#End Region

#Region " Example With Colorization "

'Module Module1

'    Sub Main()

'        Console.Title = HelpSection.ColorizedHelp.<Title>.Value

'        Dim sb As New System.Text.StringBuilder
'        sb.AppendLine(HelpSection.ColorizedHelp.<Logo>.Value)
'        sb.AppendLine(HelpSection.ColorizedHelp.<Separator>.Value)
'        sb.AppendLine(String.Format("    Executable name.......: {0}", HelpSection.ColorizedHelp.<Process>.Value))
'        sb.AppendLine(String.Format("    Application name......: {0}", HelpSection.ColorizedHelp.<Name>.Value))
'        sb.AppendLine(String.Format("    Application version...: {0}", HelpSection.ColorizedHelp.<Version>.Value))
'        sb.AppendLine(String.Format("    Application author....: {0}", HelpSection.ColorizedHelp.<Author>.Value))
'        sb.AppendLine(String.Format("    Application copyright.: {0}", HelpSection.ColorizedHelp.<Copyright>.Value))
'        sb.AppendLine(String.Format("    Author website........: {0}", HelpSection.ColorizedHelp.<Website>.Value))
'        sb.AppendLine(String.Format("    Author Skype..........: {0}", HelpSection.ColorizedHelp.<Skype>.Value))
'        sb.AppendLine(String.Format("    Author Email..........: {0}", HelpSection.ColorizedHelp.<Email>.Value))
'        sb.AppendLine(HelpSection.ColorizedHelp.<Separator>.Value)
'        sb.AppendLine(HelpSection.ColorizedHelp.<Syntax>.Value)
'        sb.AppendLine(HelpSection.ColorizedHelp.<SyntaxExtra>.Value)
'        sb.AppendLine(HelpSection.ColorizedHelp.<UsageExamples>.Value)

'        WriteColoredTextLine(sb.ToString, {"*"c})

'        Threading.Thread.Sleep(60000)

'    End Sub

'End Module

#End Region

#End Region

#Region " ConsoleColor Enumeration Helper "

' Black = 0
' DarkBlue = 1
' DarkGreen = 2
' DarkCyan = 3
' DarkRed = 4
' DarkMagenta = 5
' DarkYellow = 6
' Gray = 7
' DarkGray = 8
' Blue = 9
' Green = 10
' Cyan = 11
' Red = 12
' Magenta = 13
' Yellow = 14
' White = 15

#End Region

#Region " HelpSection "

Friend Class HelpSection

#Region " Members "

   ''' <summary>
   ''' Indicates dynamically the name of the current process.
   ''' </summary>
   Private Shared ReadOnly ProcessName As String =
       Process.GetCurrentProcess().MainModule.ModuleName

   ''' <summary>
   ''' Use this var into an XML if need to escape an 'GreaterThan' character.
   ''' </summary>
   Private ReadOnly c_GreaterThan As Char = ">"c

   ''' <summary>
   ''' Use this var into an XML if need to escape an 'LowerThan' character.
   ''' </summary>
   Private ReadOnly c_LowerThan As Char = "<"c

#End Region

#Region " Help Text "

   ''' <summary>
   ''' Contains Help information such as Author, Syntax and Example usages.
   ''' </summary>
   Friend Shared ReadOnly Help As XElement =
<Help>

   <!-- Current process name -->
   <!-- That means even when the user manually changes the executable name -->
   <Process><%= ProcessName %></Process>

   <!-- Application title -->
   <Title>My Application .:: By Elektro ::.</Title>

   <!-- Application name -->
   <Name>My Application</Name>

   <!-- Application author -->
   <Author>Elektro</Author>

   <!-- Application version -->
   <Version>1.0</Version>

   <!-- Copyright information -->
   <Copyright>© Elektro Software 2014</Copyright>

   <!-- Website information -->
   <Website>http://foro.elhacker.net</Website>

   <!-- Skype contact information -->
   <Skype>ElektroStudios</Skype>

   <!-- Email contact information -->
   <Email>ElektroStudios@ElHacker.Net</Email>

   <!-- Application Logotype -->
   <Logo>
   .____                        
   |    |    ____   ____   ____  
   |    |   / _  \ / ___\ /  _ \
   |    |__( |_|  ) /_/  >  |_| )
   |_______ \____/\___  / \____/
           \/     /____/  
   </Logo>

   <!-- Separator shape -->
   <Separator>
   ------------------------------------------------------>>>>
   </Separator>

   <!-- Application Syntax -->
   <Syntax>
   [+] Syntax

       <%= ProcessName %> (SWITCH)=(VALUE) (IN FILE)
   </Syntax>

   <!-- Application Syntax (Additional Specifications) -->
   <SyntaxExtra>
   [+] Switches

       /Switch1  | Description.
       /Switch2  | Description.
                 |
       /?        | Display this help.


   [+] Switch value types

       /Switch1  (INT)
       /Switch2  (X,Y)
   </SyntaxExtra>

   <!-- Application Usage Examples -->
   <UsageExamples>
   [+] Usage examples

       <%= ProcessName %> /Switch1=Value "C:\File.txt"
       ( Command explanation )
   </UsageExamples>

</Help>

   ''' <summary>
   ''' Contains Help information such as Author, Syntax and Example usages.
   ''' These strings are color-delimited to print a colorized output console,
   ''' using the 'WriteColoredText' methods written by Elektro.
   ''' </summary>
   Friend Shared ReadOnly ColorizedHelp As XElement =
<Help>

   <!-- Current process name -->
   <!-- That means even when the user manually changes the executable name -->
   <Process>*F10*<%= ProcessName %>*-F*</Process>

   <!-- Application title -->
   <Title>My Application .:: By Elektro ::.</Title>

   <!-- Application name -->
   <Name>*F10*My Application*-F*</Name>

   <!-- Application author -->
   <Author>*f10*Elektro*-F*</Author>

   <!-- Application version -->
   <Version>*F10*1.0*-F*</Version>

   <!-- Copyright information -->
   <Copyright>*F10*© Elektro Software 2014*-F*</Copyright>

   <!-- Website information -->
   <Website>*F10*http://foro.elhacker.net*-F*</Website>

   <!-- Skype contact information -->
   <Skype>*F10*ElektroStudios*-F*</Skype>

   <!-- Email contact information -->
   <Email>*F10*ElektroStudios@ElHacker.Net*-F*</Email>

   <!-- Application Logotype -->
   <Logo>*F11*
   .____                        
   |    |    ____   ____   ____  
   |    |   / _  \ / ___\ /  _ \
   |    |__( |_|  ) /_/  >  |_| )
   |_______ \____/\___  / \____/
           \/     /____/  
   *-F*</Logo>

   <!-- Separator shape -->
   <Separator>
   *F11*------------------------------------------------------>>>>*-F*
   </Separator>

   <!-- Application Syntax -->
   <Syntax>
   *F11*[+]*-F* *F14*Syntax*-F*

       <%= ProcessName %> *F10*(SWITCH)*-F*=*F10*(VALUE)*-F* *F10*(IN FILE)*-F*
   </Syntax>

   <!-- Application Syntax (Additional Specifications) -->
   <SyntaxExtra>
   *F11*[+]*-F* *F14*Switches*-F*

       *F10*/Switch1*-F*  | *F11*Description.*-F*
       *F10*/Switch2*-F*  | *F11*Description.*-F*
       *F10*        *-F*  |
       *F10*/?      *-F*  | *F11*Display this help.*-F*


   *F11*[+]*-F* *F14*Switch value types*-F*

       *F10*/Switch1*-F*  (*F11*INT*-F*)
       *F10*/Switch2*-F*  (*F11*X,Y*-F*)
   </SyntaxExtra>

   <!-- Application Usage Examples -->
   <UsageExamples>
   *F11*[+]*-F* *F14*Usage examples*-F*

       <%= ProcessName %> /Switch1=Value "C:\File.txt"
       *F11*( Command explanation )*-F*
   </UsageExamples>

</Help>

#End Region

End Class

#End Region


2. Copien y peguen en su proyecto estos métodos para parsear y colorear los strings:

Código (vbnet) [Seleccionar]
#Region " Write Colored Text "

   ' Name.......: Write Colored Text
   ' Author.....: Elektro
   ' Description: Methods to write colorized strings.
   ' Last Update: 05/01/2014
   ' References.: LINQ
   ' Indications: Use *F##* as the ForeColor beginning delimiter, use *-F* to restore the console forecolor.
   '              Use *B##* as the BackColor beginning delimiter, use *-B* to restore the console BackColor.
   '
   ' Example Usages:
   '
   ' WriteColoredText(    " Hello World! ", ConsoleColor.Blue,    ConsoleColor.Blue)
   ' WriteColoredTextLine(" Hello World! ", ConsoleColor.Magenta, ConsoleColor.Gray)
   ' WriteColoredTextLine(" Hello World! ", Nothing,              Nothing)
   '
   ' WriteColoredText("*F10*Hello *F14*World!*-F*", {"*"c})
   ' WriteColoredTextLine("{B15}{F12} Hello World! {-F}{-B}", {"{"c, "}"c})
   ' WriteColoredTextLine(String.Format("*B15**F12* {0} *F0*{1} *-F**-B*", "Hello", "World!"), {"*"c})

   ''' <summary>
   ''' Writes colored text on the Console.
   ''' </summary>
   ''' <param name="Text">Indicates the color-delimited text to parse and then write.</param>
   ''' <param name="Delimiters">Indicates a set of (1 or 2) delimiters to parse a color-delimited string.</param>
   Friend Sub WriteColoredText(ByVal Text As String,
                               ByVal Delimiters As Char())

       ' Store the current console colors to restore them later.
       Dim CurrentForegroundColor As ConsoleColor = Console.ForegroundColor
       Dim CurrentBackgroundColor As ConsoleColor = Console.BackgroundColor

       ' Split the string to retrieve and parse the color-delimited strings.
       Dim StringParts As String() =
           Text.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries)

       ' Parse the string parts
       For Each part As String In StringParts

           If part.ToUpper Like "F#" _
           OrElse part.ToUpper Like "F##" Then ' Change the ForeColor.

               Console.ForegroundColor = CInt(part.Substring(1))

           ElseIf part.ToUpper Like "B#" _
           OrElse part.ToUpper Like "B##" Then ' Change the BackgroundColor.

               Console.BackgroundColor = CInt(part.Substring(1))

           ElseIf part.ToUpper Like "-F" Then  ' Restore the original Forecolor.

               Console.ForegroundColor = CurrentForegroundColor

           ElseIf part.ToUpper Like "-B" Then ' Restore the original BackgroundColor.

               Console.BackgroundColor = CurrentBackgroundColor

           Else ' String part is not a delimiter so we can print it.

               Console.Write(part)

           End If

       Next part

       ' Finish by restoring the original console colors.
       Console.BackgroundColor = CurrentBackgroundColor
       Console.ForegroundColor = CurrentForegroundColor

   End Sub

   ''' <summary>
   ''' Writes colored text on the Console.
   ''' </summary>
   ''' <param name="Text">Indicates the text to write.</param>
   ''' <param name="ForeColor">Indicates the text color.</param>
   ''' <param name="BackColor">Indicates the background color.</param>
   Friend Sub WriteColoredText(ByVal Text As String,
                               ByVal ForeColor As ConsoleColor,
                               ByVal BackColor As ConsoleColor)

       ' Store the current console colors to restore them later.
       Dim CurrentForegroundColor As ConsoleColor = Console.ForegroundColor
       Dim CurrentBackgroundColor As ConsoleColor = Console.BackgroundColor

       ' Set the new temporal console colors.
       Console.ForegroundColor = If(ForeColor = Nothing, CurrentForegroundColor, ForeColor)
       Console.BackgroundColor = If(BackColor = Nothing, CurrentBackgroundColor, BackColor)

       ' Print the text.
       Console.Write(Text)

       ' Finish by restoring the original console colors.
       Console.ForegroundColor = CurrentForegroundColor
       Console.BackgroundColor = CurrentBackgroundColor

   End Sub

   ''' <summary>
   ''' Writes colored text on the Console and adds an empty line at the end.
   ''' </summary>
   ''' <param name="Text">Indicates the color-delimited text to parse and then write.</param>
   ''' <param name="Delimiters">Indicates a set of (1 or 2) delimiters to parse a color-delimited string.</param>
   Friend Sub WriteColoredTextLine(ByVal Text As String,
                                   ByVal Delimiters As Char())

       WriteColoredText(Text & Environment.NewLine, Delimiters)

   End Sub

   ''' <summary>
   ''' Writes colored text on the Console and adds an empty line at the end.
   ''' </summary>
   ''' <param name="Text">Indicates the color-delimited text to parse and then write.</param>
   ''' <param name="ForeColor">Indicates the text color.</param>
   ''' <param name="BackColor">Indicates the background color.</param>
   Friend Sub WriteColoredTextLine(ByVal Text As String,
                                   ByVal ForeColor As ConsoleColor,
                                   ByVal BackColor As ConsoleColor)

       WriteColoredText(Text & Environment.NewLine, ForeColor, BackColor)

   End Sub

#End Region



3. En la sección regionada 'Help Text' deben especificar lo que deseen, el logo, la sintaxis, la información de contacto, etc... eso es lo único que deben hardcodear (óbviamente no va a ser un click&go, pues toda aplicación tiene distintos parámetros así pues distinta información).

Por ejemplo, inspeccionemos este nodo:
Código (xml) [Seleccionar]
   <!-- Application Usage Examples -->
   <UsageExamples>
   {f11}[+]{-f} {f14}Usage examples{-f}

       <%= ProcessName %> /Switch1=Value "C:\File.txt"
       {f11}( Command explanation ){-f}
   </UsageExamples>


¿Que significan todos esos parámetros 'F'?, bien, son los delimitadores que establecí para indicar el principio y el fínal de un cambio de color (color de texto o color de fondo),
un cambio de color de texto debe empezar con la letra "F" (de Forecolor), y un cambio de color de fondo debe empezar con la letra "B" (de BackgroundColor),
seguídamente le añadiremos un número del 0-15 que hace referencia a un color de consola (solo existen 15), por ejemplo: el inicio de cambio de color de texto "{F11}" hace referencia al color de consola número 11, que es el color 'Cyan'

Para restaurar el color original usaremos el delimitador {-f} o {-b} respectívamente del tipo de cambio de color del que se trate.

Y para mostrar el texto coloreado es necesario usar un método que ideé el cual se encarga de parsear los delimitadores de cambio de colores.


Un ejemplo de uso de los método:

Código (vbnet) [Seleccionar]
Module Module1

   Sub Main()

       Console.Title = HelpSection.ColorizedHelp.<Title>.Value

       Dim sb As New System.Text.StringBuilder
       sb.AppendLine(HelpSection.ColorizedHelp.<Logo>.Value)
       sb.AppendLine(HelpSection.ColorizedHelp.<Separator>.Value)
       sb.AppendLine(HelpSection.ColorizedHelp.<Syntax>.Value)
       sb.AppendLine(HelpSection.ColorizedHelp.<UsageExamples>.Value)

       WriteColoredTextLine(sb.ToString, {"*"c})
       ' WriteColoredText(sb.ToString, {"*"c})

       Threading.Thread.Sleep(60000)

   End Sub

End Module


Además, los métodos son de uso genérico y hay 1 overload para los dos métodos, esto significa que pueden reutilizarlos de forma individual en cualquier otro tipo de proyecto, de la siguiente manera:
Código (vbnet) [Seleccionar]

WriteColoredText(" Hello World! ", ConsoleColor.Blue, ConsoleColor.Blue)
WriteColoredTextLine(" Hello World! ", ConsoleColor.Magenta, ConsoleColor.Gray)
WriteColoredTextLine(" Hello World! ", Nothing, Nothing)

WriteColoredText("*F10*Hello *F14*World!*-F*", {"*"c})
WriteColoredTextLine("{B15}{F12} Hello World! {-F}{-B}", {"{"c, "}"c})
WriteColoredTextLine(String.Format("*B15**F12* {0} *F0*{1} *-F**-B*", "Hello", "World!"), {"*"c})


Eso es todo, ¿te resultó facil?, espero que este mini-tutorial le haya servido a alguien.

Saludos!
#7480
Así a simple vista veo demasiada agua y pocas escenas de sexo, a ese juego le deberías montar una fiesta de barcos piratas, una orgia playera al estilo Sims, o meter dinosaurios que no vengan a cuento de nada ...pero que siempre son efectivos, y si lo haces ya me pasarás una Demo :laugh:.

Saludos!