Алгоритм генерации ключа по имени, как узнать?

Тема в разделе "WASM.RESEARCH", создана пользователем romoga, 8 апр 2020.

  1. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    Привет всем.
    Есть одна карточная игра Canasta. Игра требует регистрации. Методом трассировки в Oly смог найти вытащить ключи генерируемые программой по вводимому имени. Есть листинг "исходника" на асме, но там сам черт ногу сломит. Как только не пытался я найти зависимости, не смог. Там или шифрование или битовые сдвиги. Вот пример
    Для вводимого имени
    0 ключ 104160
    00 ключ 119520
    000 ключ 130368
    Причем при трасировке алгоритм кажется переворачивает числа, т.е. в консоле вначале 061 и 401 потом превращаются в 104160. Вот исходник, как я предполагаю генерации
    Код (Text):
    1.  v10;
    2.     v14[v4++] = v11 + 48;
    3.   }
    4.   while ( v3 );
    5.   if ( v5 < 0 )
    6.     v14[v4++] = 45;
    7.   *(_BYTE *)a3 = v4;
    8.   v7 = a3 + 1;
    9.   v6 = v13;
    10.   if ( v13 > 255 )
    11.     v6 = 255;
    12.   v12 = __SETO__(v6, v4);
    13.   v8 = v6 - v4;
    14.   if ( !((unsigned __int8)(v8 < 0 ^ v12) | v8 == 0) )
    15.   {
    16.     *(_BYTE *)(v7 - 1) += v8;
    17.     while ( v8 )
    18.     {
    19.       *(_BYTE *)v7++ = 32;
    20.       --v8;
    21.     }
    22.   }
    23.   do
    24.   {
    25.     result = v15[v4];
    26.     *(_BYTE *)v7++ = result;
    27.     --v4;
    28.   }
    29.   while ( v4 );
    30.   return result;
    31.  
    файл программы прикрепляю
     

    Вложения:

    • cansetup.rar
      Размер файла:
      1,2 МБ
      Просмотров:
      335
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    В трех соснах заблудился.
    Код (C++):
    1. #include "pch.h"
    2. #include <iostream>
    3.  
    4. int main()
    5. {
    6.     unsigned char username[] ={'0','0','0'};
    7.     unsigned int table1[]={0x000000D9,0x00000063,0x00000058,0x00000022,0x0000003E,0x00000093,0x000000F0,0x00000008,
    8.         0x00000034,0x00000062,0x0000001B,0x000000BF,0x000000D7,0x000000B9,0x0000006F,0x0000004A,
    9.         0x0000005A,0x000000B2,0x00000084,0x00000024};
    10.     unsigned int key=0;
    11.     do {
    12.         for(int i=0;i<sizeof(username);i++)key+=username[i]*(i+1)*table1[i];
    13.         key%=1000000;
    14.     } while(key<100000);
    15.     printf("key=%d\r\n",key);
    16. }
    Код (Text):
    1. key=130368
     
  3. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    Если не сложно, можно подробнее. Не из размещенного же мной кода ты вытащил. Да еще так быстро. Каким софтом пользоваться? Игра написана на Delphi. Прогнал через DeDe но не сильно помогло
     
  4. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Ollydbg, EmEditor, Fasm. Рипнул, выкинул все лишнее. Все эти вызовы - обработка ошибок при куче бесполезных (кроме длины юзернейма, 20 символов) проверок. Остались кропали:
    [​IMG]
     
  5. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    f13nd, класс :good:, спасибо. А массив как обнаружить?
    1. unsigned int table1[]={0x000000D9,0x00000063,0x00000058,0x00000022,0x0000003E,0x00000093,0x000000F0,0x00000008,
    2. 0x00000034,0x00000062,0x0000001B,0x000000BF,0x000000D7,0x000000B9,0x0000006F,0x0000004A,
    3. 0x0000005A,0x000000B2,0x00000084,0x00000024};
     
  6. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    В смысле как? По его базе выбирается множитель:
    Код (ASM):
    1. 004C333A  IMUL EBP,DWORD PTR DS:[EAX*4+4F61CC]
    2.  
     
  7. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    почему username меняется? а значения из table1 напротив остаются как есть

    username=80
    tab=34
    key=65184
    username=160
    tab=34
    key=97776
    username=240
    tab=34
    key=130368
    username=64
    key=130368
     
  8. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Значения массива - множители, для каждой позиции символа юзернейма. Первый всегда *=1*0xD9 и складывается в общую сумму, второй всегда *=2*0x63 и складывается в общую сумму и т.д. Ключ не может быть меньше 6 символов: в нем намеренно числа 7+ разрядов преобразуются в остаток от деления на 1000000 и если получается меньше 6 разрядов, делается еще одна итерация. Откуда эти выкладки?
    Код (Text):
    1. '80' 108280
    2. '160' 101991
    3. '240' 101454
    4. '64' 110070
     
  9. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    наверное это особенности языка с++, уже все поперепробывал. не сходится
    при первых значениях table1=217 username=48
    строка будет выглядить так
    key=key+username*(i+1)*table1;
    ключ= ключ+48*(0+1)*217 будет 10416
    --------------------------------------------------
    что значит *= , как массив символов может быть множителем?
    знаю что нубские вопросы достали, правда хочу разобраться ((
     
  10. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    'a*=b' означает 'a=a*b'
    Код (Text):
    1. username='123'    //{0x31,0x32,0x33}
    2. key=0
    3.  
    4. key = 0 + 0x31*1+0xD9 + 0x32*2+0x63 + 0x33*3+0x58 = 0x2989 + 0x26AC + 0x3498 = 0x84CD
    5. key = key % 0xF4240 = 0x84CD
    6. //0x84CD меньше 0x186A0, еще итерация
    7.  
    8. key = 0x84CD + 0x31*1+0xD9 + 0x32*2+0x63 + 0x33*3+0x58 = 0x84CD + 0x84CD = 0x1099A
    9. key = key % 0xF4240 = 0x1099A
    10. //0x1099A меньше 0x186A0, еще итерация
    11.  
    12. key = 0x1099A + 0x31*1+0xD9 + 0x32*2+0x63 + 0x33*3+0x58 = 0x1099A + 0x84CD = 0x18E67
    13. key = key  % 0xF4240 = 0x18E67
    14. //0x18E67 больше 0x186A0
    15.  
    16. key = 0x18E67 = 101991
     
  11. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    Вот опять, я Вас не допонимаю либо потому что Вы в уме часть додумываете, либо особенности языка с++
    key = 0 + 0x31*1+(тут)0xD9 + 0x32*2+(тут)0x63 + 0x33*3(тут)+0x58 = 0x2989 + 0x26AC + 0x3498 = 0x84CD
    разве не знак умножить? иначе не получается 0x84CD
    Как мы можем получать тоже значение над которым производим действия деления?
    key = key % 0xF4240 = 0x84CD
    ключ = ключ / 0xF4240 = ключ ????
     
  12. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Да, там знак "умножить" должен быть. Оператор % в си это остаток от деления. Если хотя бы на базовом уровне ассемблер знаешь (иначе не нашел бы в ольге этот алгоритм), должен знать как idiv работает и что оказывается в edx после него. Третьи сутки разжовываю одну строчку алгоритма.
     
  13. romoga

    romoga New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2008
    Сообщения:
    20
    если честно ассемблер не очень знаю, так ковырял, смотрел адреса процедур, ставил брекпоинты и интуитивно добрался до алгоритма генерации ключа
    так на асме писал, и сейчас напишу программу простенькую, но когда дело доходит до исследования программ теряюсь в регистрах. что посоветуете для этого. Нужно именно понимание как у Вас. Вот вы увидили строчку
    IMUL EBP,DWORD PTR DS:[EAX*4+4F61CC] и сразу поняли что массив. Как такого уровня достич?

    особенно когда не явно указан регистр а смещение вообще в ступор вводит ((((
    p.s. извините что отошел от темы, пытался личное сообщение отправить , но Вам нельзя почему-то их отправлять
     
  14. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    А разве не очевидно, что это выборка значения из памяти по индексу, скалируемому на 4 (размер двойного слова)? Почему регистр указан неявно? Это общий для всего набора инструкций х86 способ адресации: комбинация из sib-байта и оффсета. Эти квадратные скобки быстро примелькаются, будешь видеть. В регистрах общего назначения х86 сложно потеряться: их меньше, чем пальцев на руках :acute:Как достичь? Лет 15 заниматься реверсом. Впервые слышу, чтобы кто-то интуитивно разобрался в лицензионной защите программы, не зная ни асма, ни устройства РЕ-файлов. Со мной примерно так же и было. Практикуйся, будет получаться. Многим книжки и гайды в этом помогают (а немногим даже это не в коня корм), можешь что-нибудь из такого поискать.