
Исследование защиты программы iResizer

Скриншот программы iResizer
Программа iResizer - удобный инструмент для изменения размеров графических файлов, с уникальной функцией сохранения исходных пропорций выбранных объектов. Также с ее помощью можно удалять с фотографий ненужные объекты. Конечно, это все прекрасно реализуется и в разных фотошопах, но iResizer позволяет выполнить такие операции буквально за несколько кликов мышкой. Как это все делается, вы можете посмотреть на офсайте, а здесь вы можете посмотреть, как сэкономить на этом процессе пару десятков баксов.
Скачиваем дистрибутив, устанавливаем. Из исполняемых файлов только главный файл программы и файл деинсталляции. Внешний осмотр главного файла показывает, что он ничем не упакован. Отлично, чтобы не терять времени, отправим его в дизассемблер, а сами пока посмотрим на поведение незарегистрированной программы. Триальная версия не сохраняет результат обработки изображения, других ограничений, в том числе и по времени работы, нет.

Окно ввода серийного номера
Поле ввода серийного номера не совсем обычное, оно сразу же показывает формат серийника, а также фильтрует при вводе недопустимые символы. Автор нам значительно облегчил задачу. Еще даже не открывая ни отладчика, мы знаем, что серийный номер может состоять только из латинских букв и имеет вид типа "ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZAA-AAAA".
Возвращаемся к дизассемблеру. Как я уже говорил, исполняемый файл только один, никаких дополнительных языковых файлов нет, при этом язык интерфейса переключается в зависимости от локали системы. Это значит, что все строчки сообщений хранятся где-то внутри файла. Удобнее всего искать строчки на английском языке, попробуем найти что-нибудь, связанное с регистрацией.

Нехорошая строка найдена
Очевидно, что это и есть сообщение, которое выдается при попытке сохранить файл в триальной версии на англоязычной локали. Снова возвращаемся к дизассемблеру. Здесь выводится найденное сообщение:
Code (Assembler) : Убрать нумерацию
- ...
- .text:0047E687 loc_47E687:
- .text:0047E687 mov [ebp+var_28], offset unk_BE7EA0
- .text:0047E68E mov ecx, offset unk_BE7EA0
- .text:0047E693 mov edx, 1
- .text:0047E698 lock xadd [ecx], edx
- .text:0047E69C push 0FFFFFFFFh
- .text:0047E69E push offset aInpaint ; "Inpaint"
- .text:0047E6A3 mov [ebp+var_4], 0
- .text:0047E6AA call sub_87C5B0
- .text:0047E6AF mov [ebp+var_24], eax
- .text:0047E6B2 push 0
- .text:0047E6B4 lea eax, [ebp+var_34]
- .text:0047E6B7 push offset aNo_0 ; "No"
- .text:0047E6BC push eax
- .text:0047E6BD mov byte ptr [ebp+var_4], 1
- .text:0047E6C1 call sub_479CE0
- .text:0047E6C6 mov esi, eax
- .text:0047E6C8 push 0
- .text:0047E6CA lea ecx, [ebp+var_30]
- .text:0047E6CD push offset aYes_1 ; "Yes"
- .text:0047E6D2 push ecx
- .text:0047E6D3 mov byte ptr [ebp+var_4], 2
- .text:0047E6D7 call sub_479CE0
- .text:0047E6DC mov ebx, eax
- .text:0047E6DE push 0
- .text:0047E6E0 lea edx, [ebp+var_2C]
- .text:0047E6E3 push offset aThisFeatureIsA
- ; "This feature is available in registered"...
- .text:0047E6E8 push edx
- .text:0047E6E9 mov byte ptr [ebp+var_4], 3
- .text:0047E6ED call sub_479CE0
- ...
Code (Assembler) : Убрать нумерацию
- ...
- .text:0047E36E mov edi, ecx
- .text:0047E370 mov eax, [edi+14h]
- .text:0047E373 mov eax, [eax+8]
- .text:0047E376 lea esi, [edi+14h]
- .text:0047E379 test eax, eax
- ; Первый условный переход
- .text:0047E37B jz loc_47E687
- .text:0047E381 push esi
- ; Вызвать функцию проверки правильности серийного номера
- .text:0047E382 call sub_47C4F0
- .text:0047E387 add esp, 4
- .text:0047E38A test al, al
- .text:0047E38C jnz short loc_47E39F
- .text:0047E38E push esi
- .text:0047E38F call sub_47C840
- .text:0047E394 add esp, 4
- .text:0047E397 test al, al
- ; Второй условный переход
- .text:0047E399 jz loc_47E687
- .text:0047E39F loc_47E39F:
- .text:0047E39F mov ecx, [edi+0B4h]
- .text:0047E3A5 push 0
- .text:0047E3A7 call sub_4CA4C0
- ...
HKEY_CURRENT_USER\Software\Teorex\iResizer
В исполняемом файле эти строки выглядит так:

Названия веток реестра в файле
Чтобы заблокировать обращения к реестру, достаточно забить эти строчки нулевыми символами. Все, теперь программа "зарегистрирована", никуда ничего не пишет и становится портативной по-настоящему.
С удобными решениями закончили, переходим к решениям красивым. То есть попробуем отреверсить алгоритм генерации серийного номера. Вернемся к условным переходам при сохранении файла. Кроме всего прочего, там вызывается одна интересная функция, которую я отметил в листинге как "Функция проверки правильности серийного номера". Если посмотреть по перекрестным ссылкам, то она же вызывается еще из двух мест. Ситуация становится еще более понятной:
Code (Assembler) : Убрать нумерацию
- ...
- .text:0047D682 lea ecx, [ebp+arg_0]
- .text:0047D685 push ecx
- ; Вызвать функцию проверки правильности серийного номера
- .text:0047D686 call sub_47C4F0
- .text:0047D68B add esp, 4
- .text:0047D68E test al, al
- .text:0047D690 jnz short loc_47D6A6
- .text:0047D692 lea edx, [ebp+arg_0]
- .text:0047D695 push edx
- .text:0047D696 call sub_47C840
- .text:0047D69B add esp, 4
- .text:0047D69E test al, al
- .text:0047D6A0 jz loc_47D783
- .text:0047D6A6 loc_47D6A6:
- ; Вывести сообщение об успешной регистрации
- .text:0047D6A6 mov ecx, [esi+0B4h]
- .text:0047D6AC push 0
- .text:0047D6AE call sub_4CA4C0
- .text:0047D6B3 mov ecx, [esi+0B8h]
- .text:0047D6B9 push 0
- .text:0047D6BB call sub_4CA4C0
- .text:0047D6C0 lea edx, [ebp+arg_0]
- .text:0047D6C3 push edx
- .text:0047D6C4 lea ecx, [esi+14h]
- .text:0047D6C7 call sub_87A450
- .text:0047D6CC mov ecx, esi
- .text:0047D6CE call sub_47C340
- .text:0047D6D3 push 0FFFFFFFFh
- .text:0047D6D5 push offset aIresizer ; "iResizer"
- .text:0047D6DA call sub_87C5B0
- .text:0047D6DF mov [ebp+var_10], eax
- .text:0047D6E2 push 0
- .text:0047D6E4 lea eax, [ebp+var_14]
- .text:0047D6E7 push offset aThankYouForReg
- ; "Thank you for registration!"
- .text:0047D6EC push eax
- ...
Code (Assembler) : Убрать нумерацию
- ...
- .text:0047C50D mov word ptr [ebp+arg_0+2], cx
- .text:0047C511 push edi
- .text:0047C512 lea ecx, [ebp+arg_0+2]
- .text:0047C515 call sub_87B190
- ; Взять нулевой символ серийника
- .text:0047C51A movsx eax, al
- ; Умножить его на 3
- .text:0047C51D lea eax, [eax+eax*2]
- .text:0047C520 cdq
- ; Разделить на 19h
- .text:0047C521 mov ecx, 19h
- .text:0047C526 idiv ecx
- .text:0047C528 lea ecx, [ebp+var_2]
- ; Добавить результат к символу "A"
- .text:0047C52B lea edi, [edx+41h]
- ; Взять первый символ серийника
- .text:0047C52E call sub_87B190
- .text:0047C533 movsx edx, al
- ; Результаты равны?
- .text:0047C536 cmp edx, edi
- .text:0047C538 jz short loc_47C542
- .text:0047C53A loc_47C53A:
- ; Серийный номер неправильный, на выходе AL=0
- .text:0047C53A pop edi
- .text:0047C53B xor al, al
- .text:0047C53D pop esi
- .text:0047C53E mov esp, ebp
- .text:0047C540 pop ebp
- .text:0047C541 retn
- .text:0047C542 ; ------------------------------------
- .text:0047C542 loc_47C542:
- ; Следующие проверки. В листинге неудобочитаемые, но под отладчиком в
- ; пошаговом режиме все предельно понятно
- .text:0047C542 mov eax, [esi]
- .text:0047C544 mov ecx, [eax+0Ch]
- .text:0047C547 movzx edx, word ptr [ecx+4]
- .text:0047C54B mov [ebp+var_4], dx
- .text:0047C54F mov ecx, [eax+0Ch]
- .text:0047C552 movzx edx, word ptr [ecx]
- .text:0047C555 mov [ebp+var_2], dx
- .text:0047C559 mov eax, [eax+0Ch]
- .text:0047C55C mov cx, [eax+2]
- .text:0047C560 mov word ptr [ebp+arg_0+2], cx
- .text:0047C564 lea ecx, [ebp+arg_0+2]
- .text:0047C567 call sub_87B190
- .text:0047C56C lea ecx, [ebp+var_2]
- .text:0047C56F movsx edi, al
- .text:0047C572 call sub_87B190
- .text:0047C577 movsx eax, al
- .text:0047C57A imul eax, edi
- .text:0047C57D cdq
- .text:0047C57E mov ecx, 19h
- .text:0047C583 idiv ecx
- .text:0047C585 lea ecx, [ebp+var_4]
- .text:0047C588 lea edi, [edx+41h]
- .text:0047C58B call sub_87B190
- .text:0047C590 movsx edx, al
- .text:0047C593 cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C595 jnz short loc_47C53A
- .text:0047C597 mov eax, [esi]
- .text:0047C599 mov ecx, [eax+0Ch]
- .text:0047C59C mov dx, [ecx+6]
- .text:0047C5A0 mov [ebp+var_4], dx
- .text:0047C5A4 mov eax, [eax+0Ch]
- .text:0047C5A7 mov cx, [eax+4]
- .text:0047C5AB mov word ptr [ebp+arg_0+2], cx
- .text:0047C5AF lea ecx, [ebp+arg_0+2]
- .text:0047C5B2 call sub_87B190
- .text:0047C5B7 movsx eax, al
- .text:0047C5BA lea eax, [eax+eax*4]
- .text:0047C5BD cdq
- .text:0047C5BE mov ecx, 19h
- .text:0047C5C3 idiv ecx
- .text:0047C5C5 lea ecx, [ebp+var_4]
- .text:0047C5C8 lea edi, [edx+41h]
- .text:0047C5CB call sub_87B190
- .text:0047C5D0 movsx edx, al
- .text:0047C5D3 cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C5D5 jnz loc_47C53A
- .text:0047C5DB mov eax, [esi]
- .text:0047C5DD mov ecx, [eax+0Ch]
- .text:0047C5E0 movzx edx, word ptr [ecx+0Ah]
- .text:0047C5E4 mov [ebp+var_2], dx
- .text:0047C5E8 mov ecx, [eax+0Ch]
- .text:0047C5EB movzx edx, word ptr [ecx+4]
- .text:0047C5EF mov [ebp+var_4], dx
- .text:0047C5F3 mov eax, [eax+0Ch]
- .text:0047C5F6 mov cx, [eax+6]
- .text:0047C5FA mov word ptr [ebp+arg_0+2], cx
- .text:0047C5FE lea ecx, [ebp+arg_0+2]
- .text:0047C601 call sub_87B190
- .text:0047C606 lea ecx, [ebp+var_4]
- .text:0047C609 movsx edi, al
- .text:0047C60C call sub_87B190
- .text:0047C611 movsx eax, al
- .text:0047C614 imul eax, edi
- .text:0047C617 lea eax, [eax+eax*2]
- .text:0047C61A cdq
- .text:0047C61B mov ecx, 19h
- .text:0047C620 idiv ecx
- .text:0047C622 lea ecx, [ebp+var_2]
- .text:0047C625 lea edi, [edx+41h]
- .text:0047C628 call sub_87B190
- .text:0047C62D movsx edx, al
- .text:0047C630 cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C632 jnz loc_47C53A
- .text:0047C638 mov eax, [esi]
- .text:0047C63A mov ecx, [eax+0Ch]
- .text:0047C63D movzx edx, word ptr [ecx+0Ch]
- .text:0047C641 mov [ebp+var_2], dx
- .text:0047C645 mov ecx, [eax+0Ch]
- .text:0047C648 movzx edx, word ptr [ecx+8]
- .text:0047C64C mov [ebp+var_4], dx
- .text:0047C650 mov eax, [eax+0Ch]
- .text:0047C653 mov cx, [eax+0Ah]
- .text:0047C657 mov word ptr [ebp+arg_0+2], cx
- .text:0047C65B lea ecx, [ebp+arg_0+2]
- .text:0047C65E call sub_87B190
- .text:0047C663 lea ecx, [ebp+var_4]
- .text:0047C666 movsx edi, al
- .text:0047C669 call sub_87B190
- .text:0047C66E movsx eax, al
- .text:0047C671 imul eax, edi
- .text:0047C674 add eax, 0Eh
- .text:0047C677 cdq
- .text:0047C678 mov ecx, 19h
- .text:0047C67D idiv ecx
- .text:0047C67F lea ecx, [ebp+var_2]
- .text:0047C682 lea edi, [edx+41h]
- .text:0047C685 call sub_87B190
- .text:0047C68A movsx edx, al
- .text:0047C68D cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C68F jnz loc_47C53A
- .text:0047C695 mov eax, [esi]
- .text:0047C697 mov ecx, [eax+0Ch]
- .text:0047C69A movzx edx, word ptr [ecx+0Eh]
- .text:0047C69E mov [ebp+var_6], dx
- .text:0047C6A2 mov ecx, [eax+0Ch]
- .text:0047C6A5 movzx edx, word ptr [ecx+0Ah]
- .text:0047C6A9 mov [ebp+var_2], dx
- .text:0047C6AD mov ecx, [eax+0Ch]
- .text:0047C6B0 movzx edx, word ptr [ecx+0Ch]
- .text:0047C6B4 mov [ebp+var_4], dx
- .text:0047C6B8 mov eax, [eax+0Ch]
- .text:0047C6BB mov cx, [eax+0Ch]
- .text:0047C6BF mov word ptr [ebp+arg_0+2], cx
- .text:0047C6C3 lea ecx, [ebp+arg_0+2]
- .text:0047C6C6 call sub_87B190
- .text:0047C6CB lea ecx, [ebp+var_4]
- .text:0047C6CE movsx edi, al
- .text:0047C6D1 call sub_87B190
- .text:0047C6D6 movsx edx, al
- .text:0047C6D9 lea ecx, [ebp+var_2]
- .text:0047C6DC add edi, edx
- .text:0047C6DE call sub_87B190
- .text:0047C6E3 movsx eax, al
- .text:0047C6E6 add eax, edi
- .text:0047C6E8 cdq
- .text:0047C6E9 mov ecx, 19h
- .text:0047C6EE idiv ecx
- .text:0047C6F0 lea ecx, [ebp+var_6]
- .text:0047C6F3 lea edi, [edx+41h]
- .text:0047C6F6 call sub_87B190
- .text:0047C6FB movsx edx, al
- .text:0047C6FE cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C700 jnz loc_47C53A
- .text:0047C706 mov eax, [esi]
- .text:0047C708 mov ecx, [eax+0Ch]
- .text:0047C70B mov dx, [ecx+12h]
- .text:0047C70F mov [ebp+var_6], dx
- .text:0047C713 mov eax, [eax+0Ch]
- .text:0047C716 mov cx, [eax+10h]
- .text:0047C71A mov word ptr [ebp+arg_0+2], cx
- .text:0047C71E lea ecx, [ebp+arg_0+2]
- .text:0047C721 call sub_87B190
- .text:0047C726 movsx eax, al
- .text:0047C729 lea eax, [eax+eax*4]
- .text:0047C72C add eax, eax
- .text:0047C72E cdq
- .text:0047C72F mov ecx, 19h
- .text:0047C734 idiv ecx
- .text:0047C736 lea ecx, [ebp+var_6]
- .text:0047C739 lea edi, [edx+41h]
- .text:0047C73C call sub_87B190
- .text:0047C741 movsx edx, al
- .text:0047C744 cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C746 jnz loc_47C53A
- .text:0047C74C mov eax, [esi]
- .text:0047C74E mov ecx, [eax+0Ch]
- .text:0047C751 movzx edx, word ptr [ecx+14h]
- .text:0047C755 mov [ebp+var_2], dx
- .text:0047C759 mov ecx, [eax+0Ch]
- .text:0047C75C movzx edx, word ptr [ecx+0Ch]
- .text:0047C760 mov [ebp+var_6], dx
- .text:0047C764 mov ecx, [eax+0Ch]
- .text:0047C767 movzx edx, word ptr [ecx+0Eh]
- .text:0047C76B mov word ptr [ebp+arg_0+2], dx
- .text:0047C76F mov eax, [eax+0Ch]
- .text:0047C772 mov cx, [eax+0Ah]
- .text:0047C776 mov [ebp+var_4], cx
- .text:0047C77A push ebx
- .text:0047C77B lea ecx, [ebp+arg_0+2]
- .text:0047C77E call sub_87B190
- .text:0047C783 lea ecx, [ebp+var_6]
- .text:0047C786 movsx ebx, al
- .text:0047C789 call sub_87B190
- .text:0047C78E movsx edi, al
- .text:0047C791 lea ecx, [ebp+var_4]
- .text:0047C794 imul edi, ebx
- .text:0047C797 call sub_87B190
- .text:0047C79C movsx edx, al
- .text:0047C79F lea eax, [edx+edi+29h]
- .text:0047C7A3 cdq
- .text:0047C7A4 mov ecx, 19h
- .text:0047C7A9 idiv ecx
- .text:0047C7AB lea ecx, [ebp+var_2]
- .text:0047C7AE lea edi, [edx+41h]
- .text:0047C7B1 call sub_87B190
- .text:0047C7B6 movsx edx, al
- .text:0047C7B9 pop ebx
- .text:0047C7BA cmp edx, edi
- ; Символы не совпадают, серийный номер неправильный
- .text:0047C7BC jnz loc_47C53A
- .text:0047C7C2 mov esi, [esi]
- .text:0047C7C4 mov eax, [esi+0Ch]
- .text:0047C7C7 movzx ecx, word ptr [eax+16h]
- .text:0047C7CB mov [ebp+var_2], cx
- .text:0047C7CF mov edx, [esi+0Ch]
- .text:0047C7D2 mov ax, [edx+10h]
- .text:0047C7D6 mov [ebp+var_4], ax
- .text:0047C7DA mov ecx, [esi+0Ch]
- .text:0047C7DD mov dx, [ecx+12h]
- .text:0047C7E1 mov [ebp+var_6], dx
- .text:0047C7E5 mov eax, [esi+0Ch]
- .text:0047C7E8 movzx ecx, word ptr [eax+14h]
- .text:0047C7EC mov word ptr [ebp+arg_0+2], cx
- .text:0047C7F0 lea ecx, [ebp+arg_0+2]
- .text:0047C7F3 call sub_87B190
- .text:0047C7F8 lea ecx, [ebp+var_6]
- .text:0047C7FB movsx edi, al
- .text:0047C7FE call sub_87B190
- .text:0047C803 movsx esi, al
- .text:0047C806 lea ecx, [ebp+var_4]
- .text:0047C809 imul esi, edi
- .text:0047C80C call sub_87B190
- .text:0047C811 movsx eax, al
- .text:0047C814 imul eax, esi
- .text:0047C817 inc eax
- .text:0047C818 cdq
- .text:0047C819 mov ecx, 19h
- .text:0047C81E idiv ecx
- .text:0047C820 lea ecx, [ebp+var_2]
- .text:0047C823 lea esi, [edx+41h]
- .text:0047C826 call sub_87B190
- .text:0047C82B movsx edx, al
- .text:0047C82E cmp edx, esi
- ; Символы совпадают? Результат в AL
- .text:0047C830 pop edi
- .text:0047C831 setz al
- ...
[0] = любой разрешенный символ
[1] = ([0] * 3) % 19h + 'A'
[2] = ([1] * [0]) % 19h + 'A'
[3] = ([2] * 5) % 19h + 'A'
[4] = любой разрешенный символ
[5] = ([3] * [2] * 3) % 19h + 'A'
[6] = ([5] * [4] + 0Eh) % 19h + 'A'
[7] = ([6] + [6] + [5]) % 19h + 'A'
[8] = любой разрешенный символ
[9] = ([8] * 0Ah) % 19h + 'A'
[10] = ([6] * [7] + [5] + 29h) % 19h + 'A'
[11] = ([10] * [9] * [8] + 1) % 19h + 'A'
Как видите, значимые только первые три группы символов серийного номера, остальные символы не используются и могут быть любыми из числа допустимых. Перевести псевдокод на любой язык программирования не составит никакого труда. Зная алгоритм, генерируем правильный серийный номер и регистрируем программу. Все работает, цель достигнута.

Программа успешно зарегистрирована
iResizer, как и другие продукты автора, - на самом деле очень полезные программы, к тому же сделаны качественно. И, хоть это не в моих правилах, я все-таки рекомендую по возможности поддержать разработчика. А автору бы я порекомендовал задуматься о портабелизации своих программ штатными средствами, без необходимости их потрошения.
Просмотров: 4785 | Комментариев: 7
Метки: исследование защиты, графика

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье

ManHunter
(25.03.2012 в 14:17):
brute, это и есть один из методов "лечения".

brute
(25.03.2012 в 06:32):
поправил два перехода, которые не давали сохранить изменения: теперь программа "не зарегистрирована", но работает.

AyTkACT
(24.03.2012 в 20:31):
Как всегда чётко!

JIEMM
(24.03.2012 в 20:11):
Спасибо за ссылку MAN-попробую сделать все так как описано здесь!

ManHunter
(24.03.2012 в 13:38):
google -> IDA Pro

JIEMM
(24.03.2012 в 13:19):
ДАЙТЕ ссыль на данный дизассемблер плизз!!

Добавить комментарий
Заполните форму для добавления комментария

Вы не могли бы подсказать, как до него добраться?