
Скриншот программы Sothink SWF Decompiler
Sothink SWF Decompiler от компании
SourceTec Software - одна из лучших программа для декомпиляции Flash-файлов в формате SWF и Flash EXE, извлечения из них ресурсов, скриптов, графики, музыки, восстановления исходных кодов проектов и т.д. Незаменимый инструмент при изучении чужих разработок и восстановления своих исходников в случае их утери. Было бы странным предполагать, что авторы будут распространять такую прелесть "за красивые глазки", так оно и есть, стоимость Sothink SWF Decompiler почти 80 вечнозеленых денег.
Скачиваем
дистрибутив и устанавливаем его. Предварительный анализ исполняемого файла показывает, что он упакован навесным протектором Armadillo. Для распаковки воспользуемся программой
ArmaGeddon. К сожалению, она пока не работает под Windows 7, так что придется запускать ее под какой-нибудь виртуальной машиной с установленной Windows XP.

Распаковываем файл
В логе видно, что для защиты использованы почти все опции, но ArmaGeddon успешно с ними справляется. Через несколько секунд получаем распакованный файл размером почти в два раза превышающий исходный. Попробуем немного сократить размер, удалив из него уже ненужные секции протектора. Сделать это можно при помощи программы
CFF Explorer, которая входит в состав Explorer Suite.

Удаляем из файла секции протектора
В нашем случае не использовалась опция протектора, когда имена секций заменяются на случайный набор символов, это немного облегчит работу. Секции протектора имеют имена, похожие на имена оригинальных секций, но с добавлением в конец цифры, к тому же они идут подряд: .text1, .adata, .data1, .pdata. Отрезайте их по одной, предварительно сделав резервную копию распакованного файла и проверяя каждый раз работоспособность полученного файла. Опытным путем установлено, что безболезненно можно отрезать секции .text1, .adata, .pdata, после чего файл сразу "похудел" наполовину. Загоняем его в дизассемблер и вернемся к теории. Протектор Armadillo предоставляет функции регистрации защищаемых программ своими средствами. Для взаимодействия с защищаемой программой используются переменные окружения, в которые записываются данные об имени пользователя, ключе регистрации (если он найден в системе), триальном времени работы, количестве одновременно запущенных копий и другую информацию. Эти переменные имеют неизменные имена, значит их можно поискать в файле.

Найдены имена переменных окружения
Имена переменных найдены, они хранятся в файле в юникоде. Переменная EXPIRED устанавливается, когда триальный срок закончился, в переменной DAYSLEFT записано количество оставшихся дней, USERKEY содержит регистрационный ключ, если он установлен. Подробнее о наименованиях переменных и их значениях можете почитать в документации к Armadillo, если интересно, нас же интересует только переменная USERKEY. Посмотрим, где и как она обрабатывается.
; Процедура проверки переменной окружения USERKEY. Возвращает EAX=1,
; если такая переменная установлена (т.е. программа зарегистрирована),
; и EAX=0, если нет.
.text:00446310 sub esp, 20Ch
.text:00446316 mov eax, dword_9F18B8
.text:0044631B xor eax, esp
.text:0044631D mov [esp+20Ch+var_4], eax
.text:00446324 push esi
.text:00446325 mov esi, [esp+210h+arg_0]
.text:0044632C push 104h ; nSize
.text:00446331 lea eax, [esp+214h+Src]
.text:00446335 push eax ; lpBuffer
; Получить переменную окружения USERKEY
.text:00446336 push offset aUserkey ; lpName
.text:0044633B call ds:GetEnvironmentVariableW
.text:00446341 test eax, eax
; Такая переменная не установлена
.text:00446343 jbe short loc_446387
.text:00446345 lea eax, [esp+210h+Src]
.text:00446349 lea edx, [eax+2]
.text:0044634C lea esp, [esp+0]
.text:00446350 loc_446350:
.text:00446350 mov cx, [eax]
.text:00446353 add eax, 2
.text:00446356 test cx, cx
.text:00446359 jnz short loc_446350
.text:0044635B sub eax, edx
.text:0044635D sar eax, 1
.text:0044635F push eax ; int
.text:00446360 lea ecx, [esp+214h+Src]
.text:00446364 push ecx ; Src
.text:00446365 mov ecx, esi
.text:00446367 call sub_4024D0
; Переменная есть, установить флаг EAX=1
.text:0044636C mov eax, 1
.text:00446371 pop esi
.text:00446372 mov ecx, [esp+20Ch+var_4]
.text:00446379 xor ecx, esp
.text:0044637B call sub_7BE489
.text:00446380 add esp, 20Ch
.text:00446386 retn
.text:00446387 ; -----------------------------------------------
.text:00446387 loc_446387:
.text:00446387 mov ecx, [esp+210h+var_4]
.text:0044638E pop esi
.text:0044638F xor ecx, esp
; Переменной нет, установить флаг EAX=0
.text:00446391 xor eax, eax
.text:00446393 call sub_7BE489
.text:00446398 add esp, 20Ch
.text:0044639E retn
.text:0044639E sub_446310 endp
По перекрестным ссылкам смотрим, что эта процедура проверки вызывается из другой процедуры, которая в свою очередь вызывается уже как минимум из трех мест. Логично предположить, что основной процедурой, возвращающей признак "зарегистрировано" является именно родительская процедура. Под отладчиком видно, что флаг зарегистрированности возвращается в регистре EAX. Значит пропатчим родительскую процедуру, записав в ее начало команды MOV EAX,1; RET. Сохраняем изменения, запускаем программу. Стартовое наг-окно пропало. Теперь проверяем функционал программы. Оппа, при попытке декомпиляции любого ролика выдается следующее сообщение:

Собщение незарегистрированной программы
То есть какая-то дополнительная проверка регистрации выполняется где-то еще. Поищем строчку этого сообщения в исполняемом файле. Она найдется в ресурсах.

Строка сообщения в ресурсах
Код строки 302, или в шестнадцатеричном виде 12Eh. Поищем в дизассемблированном листинге строку "12Eh".
; Вызвать какую-то функцию проверки чего-то
.text:00455C28 call sub_4466F0
.text:00455C2D test al, al
; Если она вернула AL=0, то окно с сообщением о незарегистрированной
; программе не выводить
.text:00455C2F jz short loc_455C5F
.text:00455C31 cmp byte ptr word_9FD804+1, 0
.text:00455C38 jz short loc_455C5F
.text:00455C3A lea eax, [esp+14h+var_10]
; Загрузить строку с кодом 302 (12Eh) из ресурсов
.text:00455C3E push 12Eh
.text:00455C43 push eax
.text:00455C44 call sub_4629D0
.text:00455C49 mov ecx, [esp+1Ch+var_10]
.text:00455C4D add esp, 8
; Вывести окно сообщения
.text:00455C50 push 0 ; int
.text:00455C52 push 41h ; uType
.text:00455C54 push ecx ; int
.text:00455C55 call ?AfxMessageBox@@YGHPB_WII@Z
; AfxMessageBox(wchar_t const *,uint,uint)
.text:00455C5A cmp eax, 1
.text:00455C5D jnz short loc_455C0D
.text:00455C5F loc_455C5F:
На вывод окна влияет результат процедуры sub_4466F0, для активации нужной нам ветки алгоритма она должна вернуть EAX=0:
.text:004466F0 call sub_445B50
.text:004466F5 mov ecx, eax
.text:004466F7 call sub_446690
.text:004466FC neg eax
.text:004466FE sbb eax, eax
.text:00446700 inc eax
.text:00446701 retn
Что она делает? Первая процедура интереса не представляет, так как не влияет на результат, а вот вторая, sub_446690, как раз и проверяет по очереди установленные переменные навесной защиты - наличие ключа и окончание триального срока. Для обхода всей этой канители нужно, чтобы sub_446690 вернула EAX=1. Второй патч - записываем в начало sub_446690 команды MOV EAX,1; RET. Сохраняем изменения, запускаем. Все признаки триальности исчезли, программа работает на полную мощность. Цель достигнута. Очень похожим способом обходятся защиты и других программ SourceTec, хотя и со своими тонкостями.
Про наличие кейгенов для навесных защит Armadillo, в том числе и для программ SourceTec, я прекрасно знаю, но информация о способах и алгоритмах кейгенинга для широкой публики недоступна, да и без навесного протектора программы обычно работают гораздо шустрее.