лечение программы под .net

Discussion in 'Реверсинг' started by lis84, 15 Sep 2009.

  1. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    Здравствуйте.

    Решил тут на днях тряхнуть стариной, и зарегать на себя небольшую программку.
    http://botva.onlinebots.net/

    Программка триальная, на 80 запусков, и раз в 2 часа завершает работу.

    Метод защиты - серийный номер, который генерится по аппаратному номеру привязанному к машине.

    Вобщем то ничего сложного. Покопавшись в отладчике убедил программу что введённая мной белиберда это и есть серийный номер :).

    Но возникла вторая проблема. Теперь программа ломится на сайт разработчика http://botva.onlinebots.net/checkregistrationcode.php и скидывает ему через post 2 параметра, ключ и email (в программе который вводится)

    Прошу помощи. Подскажите на какую api функцию повешать бряк, чтобы он сработал в момент передачи/получения ответа.
    Нашёл в памяти адрес строки с адресом (извините за тафталогию), пробовал бряк на чтение с памяти, но он не срабатывает (впрочем он у меня почему то никогда не срабатывал)

    Сама программа написанна на c#. Строки с адресом в экзешнике нет, скорее всего она как то кодирована. (чтобы тупо подменить адрес на свой).

    В дисшарпе нашол интересную функцию
    Скорее всего она и есть искомая весч, но ничего в ней не могу найти, за что зацепиться отладчиком.

    Может кто нибудь подскажет как справляться с такими защитами?
    Code:
                   private string Method2_5(bool p1, bool p2, bool p3)
            {
                string s2;
    
                int i = 0;
                string s1 = System.String.Empty;
                try
                {
                    System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(Root.Class8.Method8_1(847480816) + Field2_139 + Field2_140 + Root.Class8.Method8_1(847481588));
                    if (Field2_117)
                    {
                        if (Field2_116)
                        {
                            System.Net.ICredentials icredentials = new System.Net.NetworkCredential(Field2_250, Field2_249);
                            httpWebRequest.Proxy = new System.Net.WebProxy(Field2_248 + Root.Class8.Method8_1(847489944) + Field2_90.ToString(), true, null, icredentials);
                        }
                        else
                        {
                            httpWebRequest.Proxy = new System.Net.WebProxy(Field2_248, Field2_90);
                        }
                    }
                    else
                    {
                        httpWebRequest.Proxy = null;
                    }
                    httpWebRequest.Timeout = 30000;
                    httpWebRequest.ServicePoint.Expect100Continue = false;
                    httpWebRequest.AllowAutoRedirect = false;
                    httpWebRequest.Accept = Root.Class8.Method8_1(847480721);
                    httpWebRequest.Referer = Root.Class8.Method8_1(847480816) + Field2_139 + Field2_140 + Root.Class8.Method8_1(847481588);
                    httpWebRequest.Headers.Add(Root.Class8.Method8_1(847480667), Root.Class8.Method8_1(847480693));
                    httpWebRequest.Headers.Add(Root.Class8.Method8_1(847480599), Root.Class8.Method8_1(847480609));
                    httpWebRequest.Headers.Add(Root.Class8.Method8_1(847480637), Root.Class8.Method8_1(847480520));
                    httpWebRequest.Headers.Add(Root.Class8.Method8_1(847480561), Root.Class8.Method8_1(847480448));
                    httpWebRequest.UserAgent = Field2_251;
                    httpWebRequest.KeepAlive = true;
                    httpWebRequest.Headers.Add(Root.Class8.Method8_1(847480984), Field2_162);
                    System.Net.HttpWebResponse httpWebResponse = (System.Net.HttpWebResponse)httpWebRequest.GetResponse();
                    System.IO.StreamReader streamReader = new System.IO.StreamReader(httpWebResponse.GetResponseStream(), System.Text.Encoding.GetEncoding(1251));
                    s1 = streamReader.ReadToEnd();
                    httpWebResponse.Close();
                }
                catch (System.Exception e)
                {
                    Root.Class2.Class16 class16 = new Root.Class2.Class16();
                    class16.Field16_1 = e;
                    class16.Field16_3 = this;
                    Field2_281 = System.Convert.ToInt32(Field2_53.Value * (1000M));
                    class16.Field16_2 = (double)Field2_281;
                    class16.Field16_2 /= 1000.0;
                    Invoke(new System.Windows.Forms.MethodInvoker(class16.Method16_1));
                    Invoke(new System.Windows.Forms.MethodInvoker(class16.Method16_2));
                    return Root.Class8.Method8_1(847489664);
                }
                if (s1.IndexOf(Root.Class8.Method8_1(847482847)) > 0)
                {
                    if (p1)
                    {
                        Field2_190 = System.String.Empty;
                        while (s1[s1.IndexOf(Root.Class8.Method8_1(847482858)) + 16 + i] != 10)
                        {
                            Field2_190 = System.String.Concat(Field2_190, s1[s1.IndexOf(Root.Class8.Method8_1(847482858)) + 16 + i]);
                            i++;
                        }
                        Field2_190 = Field2_190.Replace(Root.Class8.Method8_1(847482755), System.String.Empty);
                    }
                    i = 0;
                    if (p3)
                    {
                        Field2_196 = System.String.Empty;
                        while (s1[s1.IndexOf(Root.Class8.Method8_1(847482763)) + 10 + i] != 32)
                        {
                            Field2_196 = System.String.Concat(Field2_196, s1[s1.IndexOf(Root.Class8.Method8_1(847482763)) + 10 + i]);
                            i++;
                        }
                    }
                    i = 0;
                    if (p2)
                    {
                        Field2_167 = System.String.Empty;
                        while (s1[s1.IndexOf(Root.Class8.Method8_1(847482784)) + 51 + i] != 60)
                        {
                            Field2_167 = System.String.Concat(Field2_167, s1[s1.IndexOf(Root.Class8.Method8_1(847482784)) + 51 + i]);
                            i++;
                        }
                        Field2_168 = System.String.Empty;
                        i = 0;
                        s1 = s1.Remove(0, s1.IndexOf(Root.Class8.Method8_1(847482784)) + 51 + i);
                        while (s1[s1.IndexOf(Root.Class8.Method8_1(847482784)) + 51 + i] != 60)
                        {
                            Field2_168 = System.String.Concat(Field2_168, s1[s1.IndexOf(Root.Class8.Method8_1(847482784)) + 51 + i]);
                            i++;
                        }
                    }
                    return Root.Class8.Method8_1(847481052);
                }
                return Root.Class8.Method8_1(847503990);
            }
    
     
  2. 0rs

    0rs Member

    Joined:
    30 Dec 2008
    Messages:
    70
    Likes Received:
    23
    Reputations:
    3
    А что за отладчик?
     
  3. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    syser.
    А какая разница?
    Раньше SoftIce юзил, в нём тоже бряки на память не срабатывали.
     
  4. PaCo

    PaCo Elder - Старейшина

    Joined:
    6 Feb 2008
    Messages:
    436
    Likes Received:
    138
    Reputations:
    25
    httpWebRequest - ставь в etc/host 127.0.0.1 botva.onlinebots.net , код по всей видимости после обфускации(хотя это не сильно то и важно), ну или man IL со всеми вытекающими.
     
  5. zeppe1in

    zeppe1in Elder - Старейшина

    Joined:
    12 Jul 2006
    Messages:
    343
    Likes Received:
    66
    Reputations:
    18
    ws2_32.send
    ws2_32.recv
    сисером по netу это конечно сильно)
     
  6. neprovad

    neprovad Elder - Старейшина

    Joined:
    19 Oct 2007
    Messages:
    899
    Likes Received:
    274
    Reputations:
    59
    если трудностей нет, то их надо создать, иначе ломать неинтересно)
     
  7. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    Эммм, а чем .net лечат?
    :) я просто других инструментов не знаю.
    Попробовал дисшарп и рефлектор, они выдают кучу функций без названий, ну и + я в c# не сильно шарю.

    А как обычно .net лечат (на данном примере можно порядок действий, какие проги юзать и что ими делать)?

    А про подмену через hosts я в первую очередь подумал. Просто тут надо будет абсолютному валенку объяснить как ставить веб сервер. Брр... я лучше доломаю получше, мне на работе куриц в бухгалтерии хватает.
     
  8. zeppe1in

    zeppe1in Elder - Старейшина

    Joined:
    12 Jul 2006
    Messages:
    343
    Likes Received:
    66
    Reputations:
    18
    lis84
    ну да, рефлектором надо. любой деобфускатор заюзать что бы в читаемый вид переименовал все функции. потом тут все строки зашифрованы, если их расшифровать то всё будет как на ладони).
    рипнуть функцию которая их расшифровывает не проблемма, но вручную каждую строку смотреть запара хотя я нашол таки место проверки серйника. надо теперь проитись по всем функциям и заменить вызов расшивровщика на саму строку.)
    ------
    открываеш в рефлекторе, F3 и щеш строки и константы "-2048782763" он найдёт одну функцию
    а вней
    Code:
                if ((this.​  || this.  ) && (this.(this.  , this..Text) !=  .(-2048733781)))
                    {
                        return;
                    }
    
    это и есть онлайн проверка.
    вот декодер строк http://www.sendspace.com/file/lswugk
    вставлять цифры без минуса. и должен лежать в папке с ботвой.
     
    #8 zeppe1in, 16 Sep 2009
    Last edited: 16 Sep 2009
    1 person likes this.
  9. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    Блин, а я что то даже не подумал что строки зашифрованны автором. Думал это фишка .net
    Даже кажется знаю какая функция шифрует, когда в коде рылся постоянно на вязов её натыкался там где строки должны были быть.

    :) спасибо, щас ещё покопаюсь.

    Вот ещё вопросик. Я первый раз сталкиваюсь с .net после того как я найду в рефлекторе нужную функцию, как её фиксить то? Рефлектор даёт сишный код, который по моему стойкому подозрению потом не компильнётся. Чтобы в бинарнике что то править в рефлекторе никаких зацепок :(.

    ПыСы. Программа после декомпиляции как и ожидалось не компилится :(
    Программа декодировщик строк не запускается
     
    #9 lis84, 17 Sep 2009
    Last edited: 17 Sep 2009
  10. 0rs

    0rs Member

    Joined:
    30 Dec 2008
    Messages:
    70
    Likes Received:
    23
    Reputations:
    3
    Чтобы править код нужен плагин Reflexil.
    Как его использовать можно тут почитать http://www.cumps.be/reverse-engineering-with-reflector-and-reflexil/
     
  11. Kaimi

    Kaimi Well-Known Member

    Joined:
    23 Aug 2007
    Messages:
    1,732
    Likes Received:
    809
    Reputations:
    231
    Открой в иде, посмотри опкоды функций и найди по ним в хекс редакторе.
    Вроде был плагин для рефлектора позволяющий редактировать код и сохранять изменения в файл.
     
    _________________________
  12. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    Не могу в упор найти эту строку.

    Кстати огромное спасибо за то что подсказал рефлекси. Теперь я понимаю что лезть с отладчиком в .net это глупо :) там всё гораздо проще.

    Вылечил проверку версии, вылечил серийный ключ локальный. Не могу найти где глобальная проверка :( (через интернет которая)
     
  13. zeppe1in

    zeppe1in Elder - Старейшина

    Joined:
    12 Jul 2006
    Messages:
    343
    Likes Received:
    66
    Reputations:
    18
    ты в рефлекторе ищеш? просто DisSharp например кривовато декомпилит.
    процедуру то находиш? там в поиске предпоследний квадратик нажать надо)
    а в самой процедуре уже смотри цифру "-2048733781", что значит active. там идёт вызов процедуры которая отправяет инфу на сервер и проверяется ответ равен ли он слову active.
    пс: почему декодер на запускается очень интерестно он хоть говорит чтонибудь?)
     
  14. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    Честно говоря в дисшарпе 3,1,4 код гораздо более читабельный

    У меня в рефлекторе такой цифры почему то не находится. Нашёл от обратного

    нашёл функцию проверки

    Code:
    private void (object , EventArgs )
    {
        if ((this..Text == string.Empty) || (this..Text == string.Empty))
        {
            MessageBox.Show( .(847473461));
        }
        else if (this. .Items.Count == 0)
        {
            MessageBox.Show( .(847473376));
        }
        else
        {
            this. ();
            try
            {
                this.   = this.  .SelectedItem.ToString().Replace(this.  .SelectedItem.ToString().Split(new char[] { ':' })[0] +  .(847489944), string.Empty).Trim();
            }
            catch (Exception)
            {
                MessageBox.Show( .(847473241));
                return;
            }
            if (!(this.   == string.Empty))
            {
                try
                {
                    if (this.())
                    {
                        return;
                    }
                }
                catch (Exception)
                {
                    return;
                }
                try
                {
                    if ((this.   || this.  ) && (this.(this.  , this..Text) !=  .(847489656)))
                    {
                        return;
                    }
                }
                catch (Exception)
                {
                    return;
                }
                if ((this.  .SelectedIndex == 0) || (this.  .SelectedIndex == 2))
                {
                    this.   =  .(847480486);
                }
    
    
    Собственно место

    Code:
       try
                {
                    if ((this.   || this.  ) && (this.(this.  , this..Text) !=  .(847489656)))
                    {
                        return;
                    }
                }
                catch (Exception)
                {
                    return;
                }
    Очень похоже на то что ты говоришь но вот незадача :((

    В виде опкода

    L_014c: ldc.i4 847489656
    L_0151: call string  ::(int32)
    L_0156: call bool [mscorlib]System.String::eek:p_Inequality(string, string)
    L_015b: brfalse L_0162
    L_0160: leave.s L_0109

    При смене перехода L_015b: brfalse L_0162 на противоположный, получаю exception :(

    UPD. Туплю уже просто. Заменял не на противоположный, а на безусловный.

    Всё хоткей. :) теперь подумаю как вырезать стук к серверу вообще. Ибо х.з что придумает автор, может парсить будем мыла халявщиков :)
     
    #14 lis84, 17 Sep 2009
    Last edited: 18 Sep 2009
    1 person likes this.
  15. lis84

    lis84 Banned

    Joined:
    28 Apr 2009
    Messages:
    59
    Likes Received:
    10
    Reputations:
    1
    Всем подсказывающим огромное спасибо.
    Доломал до красоты, с пропуском обращения на сайт авторов вообще.
    Решил потестить, а он не работает зараза :))) . В смысле к игре подключиться не может.
    Как ломанный, так и не ломанный :))
    Впрочем главное эстетическое удовольствие и то что я теперь знаю с какого бока подходить к .net
     
    1 person likes this.