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

#91
Ingeniería Inversa / Re: Licencia xml
18 Marzo 2020, 15:34 PM
FileActivation.xml es un XML con el contenido de la peticion y la respuesta de activacion para dicha peticion. Dicho XML usa XML encryption para mantener privado el paso de informacion.
En el caso del segundo FileActivation.xml que muestras, se puede observar una estructura como la siguiente una vez se decodifica

Request
Código (xml) [Seleccionar]
<EncryptedData Id="ActivationRequest" Type="http://www.w3.org/2001/04/xmlenc#Element"
    xmlns="http://www.w3.org/2001/04/xmlenc#">
    <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
    <KeyInfo
        xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey
            xmlns="http://www.w3.org/2001/04/xmlenc#">
            <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
            <KeyInfo
                xmlns="http://www.w3.org/2000/09/xmldsig#">
                <KeyName>SessionKey</KeyName>
            </KeyInfo>
            <CipherData>
                <CipherValue>srYzp3rl3Tf5qwr+XBlUhPr+i5rTIYbDMP8BkHeZfa0jMOVuhCsSDgniKlea7Zjyc7lSifnKzklmx440aXM+EOYwybMnau7OcfVXyc0ko6Syq3zRAMLVF5MQYQ3txRwc1OFz3EkKvjRnXYZ7p2NTK2VvD1JznPI0NJlGTTByjZY=</CipherValue>
            </CipherData>
            <ReferenceList>
                <DataReference URI="#ActivationRequest" />
            </ReferenceList>
        </EncryptedKey>
    </KeyInfo>
    <CipherData>
        <CipherValue>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</CipherValue>
    </CipherData>
</EncryptedData>


Response
Código (xml) [Seleccionar]
<EncryptedData Id="ac" Type="http://www.w3.org/2001/04/xmlenc#Element"
    xmlns="http://www.w3.org/2001/04/xmlenc#">
    <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
    <KeyInfo
        xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey
            xmlns="http://www.w3.org/2001/04/xmlenc#">
            <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
            <KeyInfo
                xmlns="http://www.w3.org/2000/09/xmldsig#">
                <KeyName>sessionKey</KeyName>
            </KeyInfo>
            <CipherData>
                <CipherValue>HANAB4Ly8oiAktwrzhE7dZMzi9+/HBiQCkqrzXNkcqITf0ZFMHyFOC+rFXImyEOIAv+kkJ19NcM5aEtZ2V/y7TXYq/sEXIVoUU19640owsQWL6BZsi4AEbcCjIcx/jBL4asVVvgHaJBMMX4VUAOlV0KU8QKSfJOzEAXCLMPcBa7vs80/9mWSk464oRbvjsfXKIRRoFGM6y/IEQKi9ZyqqVRrM+34tOmanFb/OAIw8qkyrWZVCt5luWELx6BoSY1H0clw8FfOLNZvKGHWXU8vtGoMDHusTCmAB9H7nH3hdSn9Evlui9t5TkG0fTClNIoqEWwh8nMNkZE1mmQN9tntTg2TRtETo58aeBi7PgJp2C0qyHHcImNUIXjCLJ5Phy75TOpgGjRtJXxAJ2jROMjTJs70ia55FN+597cIedZXWEiQrWbGDUljSfq7c2zmA10/o11Se+JGhC4LAkwwDIEL24q6wR9zsYj7G8G/CJa6ChDe/gfRz+hhCUbk3+MKj15+hsAffqecKpSLectDIZiUfo3m14xshAebH2x3zi2HBDVcjRuOYEasu/0UsT4sZ+RFsbMD+lEcW2VazxcBc4Iz7TvzABWESYQDgZ7nLjdC0OqSGyNPDVmajov3peZvVb5mL/G3Cv3KvaOBD2dT5ePoIR48YPqAT22FUCV4Ry5cxac=</CipherValue>
            </CipherData>
            <ReferenceList>
                <DataReference URI="#ac" />
            </ReferenceList>
        </EncryptedKey>
    </KeyInfo>
    <CipherData>
        <CipherValue>AjM1SPBWuA7jRkfiMNqsoh8HoZpgGa5aEikspgwKLgZdLc3Q4hsYyguUPjzxAxTZW8VrC+bwDuHjZM+T2fJpIvcEZwAKoMSXFbKYbwuknD4xWIoDFjFmJCoevUZ/ieVpWF9YnCnaZBb6no10bLmyk6+RWxfYAayKttUkHGHLdvxDWhstG2SkEwClabtFtJ5zhVd2ukMKzReKmebm9onRt+Eh+s5Z531iSUlqTo2CVew9tAQTJgzvUO7V9DYodngaWeg7rp/ibvvR4yJSQTfogg4fUs1eqzHeSXZB6R57TUv0If74zvqONz85TxkghKKaYSHTKgeggVygjEYoot9J4V3LujuBORCvNRGea01/GR+JoT5dhU6qEBgAXlQe6lvGcO9hQu1x+jKzKCO7nU3Ew065+3RtmzWtel9RVoix18IyulfxZyDgU3zDsRCHDMWo2Gn3k3kf3dbW7o9q3xQbayYI2AszvvjXv9xcGGxhwV/1KsHklj6SpkxrIVVMYEvjc8EDQjCNxwiXAbonkleLTkY115VvZEZ9q41MGHNzj7ZCC6YJAAPsJMgH7/dHZP7GgUoWdeOjBQgYU7wkOJXjTUuYZsnuoqtv2nt0c7lJsMs8Xt+fIE1FIzB0ixKhfpF0DSWUpMiLfQDo9J94SnzkrC9rKyIKjI08bcEkncP4avtYI/Mor/T1gMBmUmPlmehaDyojkA/RF2q8/ITQgia8JS6FglyOL7uiRDGXRqQBKr2JrzdXFug0aOf4ojtWD4AkVEZ8dkUwyrxCk1PE/nZHxhJNZQjdj4K8pWhcWHjzGVp4WZQiZ0XK+SoOJTgWAdiEZDt5mmkBreBwKpt8LgUVXmjlUeP+jfuWlLtaRGSSmYsKQ0LqZWCpWmpojYz1qS7NixzkA3/pBetOCUNOHcRbIj+PeI2cnNUOvqavsrT9zngi90CKHSDgrWF1vLuqGNWFo5RE6vcdGk6z0QGP0kctBTkxp6iHWJN72fvydNx/lQ6+7Bap7YGcNbZbcK2Bc6W99KkFQ6Zq1szZqZBm4Pl7SjOwqGQt5ZCMdSN5kakuZEmkYTO1u9BLsOUz0kG41ZZSkOrnHcHKre5X2xqKvpnoKExTPYPYHFNaNhqkcLfAaowpw3hjGrU9YPIo/31uOEnsIDJbSQc9gXEzDAo+fLA7n5jR7S3r4QSAtHOBfI8GWs0YOVi3uge4XTXGIpvBC2tRWWwJFBuFvyRYd3SXc1OTEQkvKskpjQVFfgYlEIOWpCMd+i3awtdsSxnGe+coCPtT++MVOtTT6zcILl1cDcxfER0R15fpTkyLyjOdjgn80reyBNzk0Vq5cr7jYNiTXRiNs0KB61nuzdYcWxQ2YQtGuRSQIa2YVIzwgfBmrZksqFxnBb6BVRhPSf2Qzy1C9j6iHpXpaWGGvliTYtq2YSVhRJtRGQtu2qFCvcM0d9R4KMe+HXipODh7+m+uH0PIGjexJd4x1+o585pXpbM/OtnlkARKKmU+ufnNX2JPb92W9mjXvFHo+VsOynTByqY9jLkFo/5MfcNsyeJYkkDBzTnFIi9yif5luckSf1wVds3VIbaXuobjsJuXq+OBjaD6rGP4XJO0hm2AVo8RCEfHneIue/OXLU1A1/ci5R+Ex+1y/SWPuP+98pjdjTqPlrqFFpbM3Ut1JsqWuA63kDfI1W3sFDAPup97Bk8pLoLE9FR17U3pftuSLMEdGAEWh1A/+KOaYs5ftgJirWhlOYcu20eFy3tt1nUf3ilUqZsu0jHHcPgAGJayJ3xhBskz/E8oAR8doSm8WGLhWDMVezrj6uLAjjc6NTY7RhbWz70m+8mTDzo=</CipherValue>
    </CipherData>
</EncryptedData>


Como se puede apreciar se esta usando una combinacion de RSA/AES-256 para cifrar llave/contenido, por lo que habiendo llegado hasta aqui y dicho todo lo anterior, te doy un par de consejos:
1- Realizar ingenieria inversa en un binario no es como seguir un tutorial paso a paso de como lograr un buen efecto en photoshop, va mucho mas alla que eso y exige muchisimos mas conocimientos adicionales que, desde el respeto, no creo que poseas. Mi punto es que no existe "algún tutorial para aprender a generar un keygen para activar este tipo de licencia" (a no ser por supuesto que alguien mas lo haya hecho antes y haya compartido documentacion de como hacerlo paso a paso), para esto no existen caminos rapidos o atajos.
2- Dada la complejidad del tipo de activacion que se esta usando en comparacion con tu nivel en estos temas, te aconsejaria que empezaras buscando tutoriales basicos de como analizar y parchear ejecutables sencillos, solo con tiempo y mucha practica seras capaz entonces de empezar a entender de que va todo y quizas con muchisima suerte puedas lograr un parche exitoso. (repito, esto no es fast food)
3- Una vez mas con suerte y la ayuda de alguien con experiencia y quizas algo mas  :silbar:  quizas seas capaz de obtener algo

Suerte
#92
Cita de: Meta en  3 Marzo 2020, 00:20 AM
Pedazo de código. Eso si, tengo que entenderlo todo paso por paso. Si lo hiciste tu, buen trabajo.

LAs campturas te quedaron de lujo. Voy a investigar.

Si si lo hice yo  :xD de igual manera si no entiendes algo por parte del codigo o el algoritmo en si puedes preguntar, en realidad no es tan complicado. Como dije en un mensaje anterior, una vez que te abstraes lo suficiente puedes ver perfectamente como la relacion de un menu con un Arbol es casi perfecta, haciendo este tipo de estructura de datos las mas apropiada para implementarlo. El codigo se puede simplificar muchisimo si solo se deja el funcionamiento basico. La clase abstracta Menu es nuestra abstraccion del arbol y los atributos principales son:

Código (csharp) [Seleccionar]
protected internal Menu Parent;
protected internal List<Menu> Children;
protected internal int ChildIndex;


Parent sera el nodo padre o el menu padre si se quiere ver, Children los nodos hijos de dicho nodo padre, el cual es una lista de nodos pues evidentemente no estamos tratando con arbol binario en este caso pues un menu puede tener mas de dos entradas y finalmente ChildIndex sera nuestro selector.
Luego una de las funciones mas importantes es public void ControlLoop(), la encargada de mostrar el Nodo (menu) y procesar el input del usuario. Finalmente las clases HorizontalMenu/VerticalMenu y Entry son clases especializadas que implementan la clase abstracta Menu de acuerdo a su especificacion para lograr el objetivo de cada una y sus nombres son bien descriptivos del tipo de Nodo que serian.
Saludos

#93
Cita de: Meta en  1 Marzo 2020, 08:04 AM
¿Tu crees que es más fácil?
http://www.udb.edu.sv/udb/archivo/guia/informatica-ingenieria/programacion-iv/2013/ii/guia-6.pdf
https://docs.microsoft.com/es-es/dotnet/csharp/programming-guide/concepts/expression-trees/

No creo que era necesario referenciarme una conferencia de Arboles  :laugh:  se muy bien lo que son. En fin, en mi opinion una implementacion en este caso usando una ED tipo Arbol es la solucion ideal y vuelvo a repetirme, es una implementacion mas eficiente, dinamica y si, muchisimo mas sencilla aunque no lo parezca.
Como me parecio divertida la idea aqui dejo un sencillo framework (poc) que hice para crear menus en consola de forma dinamica usando un Arbol como abstraccion de datos. Aclaro que con esto no quiero decir que esta es la unica forma de hacerlo, simplemente que a mi parecer es la mas natural


Código (csharp) [Seleccionar]
/// <summary>
/// Menu.cs
/// Abstract menu class
/// </summary>
public abstract class Menu
{
    /// <summary>
    /// Menu header UI details
    /// </summary>
    public class Position
    {
        public int TopSpacing { get; set; }
        public int TopPadding { get; set; }
        public int LeftPadding { get; set; }
        public int LeftSpacing { get; set; }
        public bool LeftCentered { get; set; }
        public bool TopCentered { get; set; }
    }

    public const string MarkerSymbol = "=>";
    public List<string> HeaderText { get; set; }
    public string EntryTitle { get; set; }
    public bool Selected { get; set; }
    public Position HeaderPos { get; set; }
    public Position EntriesPos { get; set; }

    protected internal Menu Parent;
    protected internal List<Menu> Children;
    protected internal int ChildIndex;

    protected internal Menu()
    {
        Children = new List<Menu>();
        HeaderPos = new Position();
        EntriesPos = new Position();
    }

    protected internal void Select()
    {
        Selected = true;
    }

    protected internal void Deselect()
    {
        Selected = false;
    }

    protected internal string GetMarker()
    {
        return Selected ? MarkerSymbol : new string(' ', MarkerSymbol.Length);
    }

    public void AddChild(Menu child)
    {
        child.Parent = this;
        Children.Add(child);
    }

    protected internal string GetEntryString()
    {
        return $"{this.GetMarker()} {this.EntryTitle}";
    }

    public void ControlLoop()
    {
        Console.CursorVisible = false;
        do
        {
            ShowMenu();
            ProcessKeyPress();
        } while (true);
    }

    protected internal abstract void Execute();
    protected internal abstract void ShowMenu();
    protected internal abstract void ProcessKeyPress();
}


/// <summary>
/// VerticalMenu.cs
/// Vertical menu class
/// </summary>
public class VerticalMenu : Menu
{
    protected internal override void Execute()
    {
        ControlLoop();
    }

    protected internal override void ShowMenu()
    {
        Console.Clear();

        // calculating left positioning for menu header
        int leftPosition = (HeaderPos.LeftCentered)
                ? (Console.WindowWidth / 2) - (HeaderText.Max(x => x.Length) / 2)
                : HeaderPos.LeftSpacing;

        int topPosition = (HeaderPos.TopCentered)
            ? (Console.WindowHeight / 2) -
              (((HeaderPos.TopPadding > 0) ? HeaderText.Count * 2 * HeaderPos.TopPadding : HeaderText.Count +
              ((EntriesPos.TopPadding > 0) ? Children.Count * 2 * EntriesPos.TopPadding : Children.Count)) / 2)
            : Console.CursorTop + HeaderPos.TopSpacing;

        Console.SetCursorPosition(leftPosition, topPosition);
        foreach (string line in HeaderText)
        {
            Console.WriteLine(line);
            Console.SetCursorPosition(leftPosition, Console.CursorTop + HeaderPos.TopPadding);
        }

        // calculating left positioning for menu entries
        int totalLeft = Children.Select(x => x.GetEntryString().Length).ToList().Max(x => x);
        leftPosition = (EntriesPos.LeftCentered)
            ? (Console.WindowWidth / 2) -
              (totalLeft / 2)
            : EntriesPos.LeftSpacing;

        Console.SetCursorPosition(leftPosition, Console.CursorTop + EntriesPos.TopSpacing);
        foreach (var child in Children)
        {
            Console.WriteLine(child.GetEntryString());
            Console.SetCursorPosition(leftPosition, Console.CursorTop + EntriesPos.TopPadding);
        }
    }

    protected internal override void ProcessKeyPress()
    {
        var key = Console.ReadKey();
        switch (key.Key)
        {
            case ConsoleKey.UpArrow:
                MoveMarkerUp();
                break;

            case ConsoleKey.DownArrow:
                MoveMarkerDown();
                break;

            case ConsoleKey.Enter:
                ExecuteEntry();
                break;

            case ConsoleKey.Escape:
                TryExitConsole();
                break;
        }
    }

    private void MoveMarkerUp()
    {
        ChildIndex = (ChildIndex - 1 >= 0) ? ChildIndex -= 1 : Children.Count - 1;
        Children.ForEach(x => x.Deselect());
        Children[ChildIndex].Select();
    }

    private void MoveMarkerDown()
    {
        ChildIndex = (ChildIndex + 1 < Children.Count) ? ChildIndex += 1 : 0;
        Children.ForEach(x => x.Deselect());
        Children[ChildIndex].Select();
    }

    private void ExecuteEntry()
    {
        if (ChildIndex >= 0 && ChildIndex < Children.Count)
        {
            Menu menu = Children[ChildIndex];
            if (menu?.GetType() != typeof(Entry) && menu?.Children.Count == 0)
            {
                menu = this.Parent;
            }

            menu?.Execute();
        }
    }

    private void TryExitConsole()
    {
        if (this.Parent == null)
            Environment.Exit(0);
    }
}


/// <summary>
/// HorizontalMenu.cs
/// Horizontal menu class
/// </summary>
public class HorizontalMenu : Menu
{
    protected internal override void Execute()
    {
        ControlLoop();
    }

    protected internal override void ShowMenu()
    {
        Console.Clear();

        // calculating left positioning for menu header
        int leftPosition = (HeaderPos.LeftCentered)
                ? (Console.WindowWidth / 2) - (HeaderText.Max(x => x.Length) / 2)
                : HeaderPos.LeftSpacing;

        int topPosition = (HeaderPos.TopCentered)
            ? (Console.WindowHeight / 2) -
              (((HeaderPos.TopPadding > 0) ? HeaderText.Count * 2 * HeaderPos.TopPadding : HeaderText.Count +
              ((EntriesPos.TopSpacing > 0) ? EntriesPos.TopSpacing + 1 : 1)) / 2)
            : Console.CursorTop + HeaderPos.TopSpacing;

        Console.SetCursorPosition(leftPosition, topPosition);
        foreach (string line in HeaderText)
        {
            Console.WriteLine(line);
            Console.SetCursorPosition(leftPosition, Console.CursorTop + HeaderPos.TopPadding);
        }

        // calculating left positioning for menu entries
        int totalEntriesLeftSpace = Children.Select(x => x.GetEntryString().Length + EntriesPos.LeftPadding)
                                            .ToList().Sum(x => x) - EntriesPos.LeftPadding;
        topPosition = Console.CursorTop + EntriesPos.TopSpacing;
        leftPosition = (EntriesPos.LeftCentered)
            ? (Console.WindowWidth / 2) - (totalEntriesLeftSpace / 2)
            : EntriesPos.LeftSpacing;
        foreach (var entry in Children)
        {
            Console.SetCursorPosition(leftPosition, topPosition);
            Console.WriteLine(entry.GetEntryString());
            leftPosition += MarkerSymbol.Length + entry.EntryTitle.Length + EntriesPos.LeftPadding;
        }
    }

    protected internal override void ProcessKeyPress()
    {
        var key = Console.ReadKey();
        switch (key.Key)
        {
            case ConsoleKey.LeftArrow:
                MoveMarkerLeft();
                break;

            case ConsoleKey.RightArrow:
                MoveMarkerRight();
                break;

            case ConsoleKey.Enter:
                ExecuteEntry();
                break;

            case ConsoleKey.Escape:
                TryExitConsole();
                break;
        }
    }

    private void MoveMarkerLeft()
    {
        ChildIndex = (ChildIndex - 1 >= 0) ? ChildIndex -= 1 : Children.Count - 1;
        Children.ForEach(x => x.Deselect());
        Children[ChildIndex].Select();
    }

    private void MoveMarkerRight()
    {
        ChildIndex = (ChildIndex + 1 < Children.Count) ? ChildIndex += 1 : 0;
        Children.ForEach(x => x.Deselect());
        Children[ChildIndex].Select();
    }

    private void ExecuteEntry()
    {
        if (ChildIndex >= 0 && ChildIndex < Children.Count)
        {
            Menu menu = Children[ChildIndex];
            if (menu?.GetType() != typeof(Entry) && menu?.Children.Count == 0)
            {
                menu = this.Parent;
            }

            menu?.Execute();
        }
    }

    private void TryExitConsole()
    {
        if (this.Parent == null)
            Environment.Exit(0);
    }
}


/// <summary>
/// Entry.cs
/// Menu entry class
/// </summary>
public class Entry : Menu
{
    public Action Event { get; set; }

    protected internal override void Execute()
    {
        Event?.Invoke();
    }

    protected internal override void ShowMenu() { }

    protected internal override void ProcessKeyPress() { }
}



Su uso para crear menus seria muy basico


Código (csharp) [Seleccionar]
static void Main(string[] args)
{
    Menu mainMenu = new VerticalMenu
    {
        HeaderText = new List<string>()
        {
            "============",
            " Main Menu  ",
            "============",
            "Options:"
        }
    };
    Entry blueEntry = new Entry
    {
        Selected = true,
        EntryTitle = "Blue",
        Event = () => { Console.BackgroundColor = ConsoleColor.DarkBlue; }
    };
    Entry redEntry = new Entry
    {
        Selected = false,
        EntryTitle = "Red",
        Event = () => { Console.BackgroundColor = ConsoleColor.DarkRed; }
    };

    mainMenu.AddChild(blueEntry);
    mainMenu.AddChild(redEntry);
    mainMenu.ControlLoop();
}



Igual he añadido un par de opciones para jugar con el posicionamiento de los elementos en la ventana de la consola, como el centrado horizontal y vertical, padding, etc



Resumiendo todo lo anterior, como decia antes el codigo base es mucho mas sencillo usando un Arbol para almacenar cada menu y si le quitamos todo el codigo extra para lo ultimo que comente y demas mierdas que puse son mucho menos lineas de codigo y logica de funcionamiento en general, ademas tienes la posibilidad de crear todos los menus, submenus y entradas que quieras de forma dinamica simplemente usando dichas clases en cualquier proyecto.
Pues nada, estuvo divertido  ;-)
Saludos
#94
Porque no lo implementas usando algo similar a un arbol?. Creo que seria mucho mas eficiente, dinamico y sobretodo sencillo
Saludos
#95
No das mucho detalle de lo que intentas hacer, pero como dijo **Aincrad**, debes tener en cuenta que una vez que un proceso carga una libreria y usa la funcion que necesita, la libera de memoria, por lo que es muy poco probable que en el punto que hagas el listado de modulos obtengas absolutamente todas las librerias que el proceso ha usado o usara en el futuro. Repito, no se lo que intentas hacer, pero puedo decir un par de ideas

1- Lanzar tu aplicacion como debugger del juego y depurarlo a tu gusto (WaitForDebugEvent/ContinueDebugEvent)
2- Inyectarte en el proceso justo antes de que se cargue completamente (ejecute su ep) y hacer hook en LoadLibrary

Saludos

#96
Cita de: EdePC en 27 Febrero 2020, 22:36 PM
- He usado una RegEx más corta, me parece que le basta ..., luego voy concatenando una String para los positivos y otra para los negativos, unidas mediante una "coma", al final se usa esa misma coma para hacerle un Split quitando las vacias.

Tienes razon, la expresion se puede simplificar. Algun motivo por el que no usas un List/ArrayList directamente? En mi opinion la concatenacion/split de cadenas estaria de mas.

Código (csharp) [Seleccionar]
public int ExtractNumbersFromString(string input, ref ArrayList positives, ref ArrayList negatives)
{
    Regex rx = new Regex(@"(?<positivos>\d+)|(?<negativos>-\d+)");
    MatchCollection matches = rx.Matches(input);
    foreach (Match match in matches)
    {
        if (!string.IsNullOrEmpty(match.Groups["positivos"].Value))
        {
            positives.Add(match.Value);
        }
        else
        {
            negatives.Add(match.Value);
        }
    }

    return matches.Count;
}


Saludos

Edit: Supongo que seria mas util devolver la cantidad de matches en lugar de un bool  :silbar:
#97
Cita de: Reent en 27 Febrero 2020, 14:26 PM
tu idea la entendi pero tu codigo no.

Solo te he pasado la expresion regular que debes usar, todo lo que tienes que hacer es usarla en tu lenguaje

https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=netframework-4.8
#98
Puedes saber en un momento determinado que librerias tiene en memoria un proceso, luego necesitas saber si las que tiene en ese momento son todas las que se supone que deba cargar. Lo primero lo puedes hacer enumerando cada modulo en el proceso (OpenProcess/EnumProcessModules). Para lo segundo te podrias hacer hacer un listado de todas las librerias que carga el proceso en su ejecucion como base de comparacion
Saludos
#99
Para hacerlo en Windows necesitas dos cosas:
1- Obtener las dimensiones de la consola. Lo puedes hacer con GetConsoleScreenBufferInfo
2- Calcular y posicionar el cursor en la posicion correcta. Lo puedes hacer con SetConsoleCursorPosition

Saludos
#100
En estos casos las expresiones regulares son tus aliadas

Código (perl) [Seleccionar]
(?<positivos>[^-\w\s]\d*)|(?<negativos>[^+\w\s]\d*)

En el grupo "positivos" tendrias los numeros positivos y en el grupo "negativos" los negativos

Suerte