HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Этичный хакинг или пентестинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 29.09.2024, 01:15
ROP
Новичок
Регистрация: 27.08.2019
Сообщений: 0
С нами: 3533622

Репутация: 0
По умолчанию

1.0 Введение
Хоть компания Adobe и ушла из России, но потребность в их софте всё ещё остаётся. Решают её по-разному: кто-то использует другие аккаунты, кто-то использует ключи, а кто-то одевает повязку и спускает на воду свой цифровой фрегат.
На последнем мы как раз и остановимся. В этой статье проанализируем Adobe GenP.

Adobe GenP — это патчер, предназначенный для активации продуктов Adobe Creative Cloud, начиная с версий 2019 года и до текущих релизов. Он позволяет устанавливать и использовать приложения Adobe: Photoshop, Illustrator, Premiere Pro и другие, без необходимости приобретения лицензии.
Патчер — это программа, предназначенная для модификации программного обеспечения. Чаще всего используемая для обхода проверки лицензий и других защитных механизмов.
В отличие от многих других патчеров у него есть даже своё комьюнити на Reddit!



Кстати, помимо основного сообщества рекомендую обратить внимание на Community bookmarks. Там много полезных туториалов и дополнительной информации.

План статьи:

1.0 Введение

2.0 Файлы

3.0 Установка Creative Cloud и первый запуск

3.1 Про установку Adobe
3.2 Запуск GenP
4.0 Разбираемся в исходном коде
4.1 Начало скрипта
4.2 Основной цикл патчера
4.2.1. Обработчик кнопки поиска
4.2.2. Обработчик кнопки выбора папки
4.2.3. Обработчик кнопки выбора/отмены всех элементов
4.2.4. Обработчик кнопки Pop-up
4.2.5. Обработчик кнопки "Patch CC" и как работает эта магия
4.2.5.1. Весь цикл поиска и патчинга кратко
4.2.5.2. Вернёмся к обработчику кнопки "Patch CC"
4.2.5.3. Сравниваем пропатченные байты с оригинальными и ищем их
4.2.6. Обработчик кнопки "Restore"
4.2.7. Обработчик кнопки "Patch"
5.0 Изучаем патчи из INI-файла
5.1. Секция CustomPatterns
5.2. Секция DefaultPatterns
5.3. Оставшиеся патчи
6.0 Вывод



2.0 Файлы
Архив с GenP, который будет разбирать, был загружен с Reddit.



Его контрольные суммы:

Код:
iz3lne.zip
MD5:
Код:
6b104ba9deb749a6b6ce88b9c6997dae
SHA1:
Код:
19d9b52477606b78bdce568235c0acb9321c1bc4
SHA256:
Код:
14ce93ae01d50b9d2ff3c36c3edd574a9f8bcec56451f3a865fcc210c617a77b
Архив с GenP состоит из следующих частей:



Исполняемый файл и исходник со всем необходимым, если мы хотим собрать патчер сами. Исходник написан в виде скрипта для AutoIt.



3.0 Установка Creative Cloud и первый запуск
3.1 Про установку Adobe
Установщик для Creative Cloud (далее CC) загружаем с официального сайта. На момент написания статьи его MD5:
Код:
0011ec2b0f49f83ccf67aa706a638ccc
. Но и с более новыми версиями всё работает (дата проверки 27.09.2024).



ОБЯЗАТЕЛЬНО снимаем тут галочку, чтобы патчи не слетали. Должно быть так, как на скрине.

3.2 Запуск GenP
После установки видим магазин приложений, где нам предлагают купить софт.

Попробуем запустить GenP.

Он предлагает повысить привилегии GenP, чтобы нормально пропатчить XD и UWP-приложения. Откажемся.
Патчинг происходит таким образом:
  1. Патчим Adobe Creative Cloud, чтобы скачивать приложения - кнопка "Patch CC"
  2. Патчим отдельные приложения - кнопки "Search" и "Patch".

Нажмём "Patch CC".

Все приложения Adobe CC закрываются. Выводится лог патча: какой файл патчится и что в нём ищется/заменяется - это первая/вторая строка после названия файла. Попробуем запустить Adobe CC.

Появилась возможность скачивать любое приложение, как будто у нас есть подписка. Скачаем и запустим Adobe Audition для теста.

Нас просят купить подписку. Вернёмся в GenP и выполним поиск.

Пропатчим. Перед этим желательно закрыть Audition.

Нам вывелся лог патча. Попробуем запустить снова программу.

Теперь можем спокойно использовать софт. Также есть возможность заблокировать всплывающие окна (pop-up's). Adobe Illustrator также успешно патчится.

Более того, мы можем восстановить оригинальные файлы до патча через кнопку "Restore".

4.0 Разбираемся в исходном коде
Код представлен в виде скрипта для AutoIt.

Читается как многие скриптовые языки вроде того же Python.

4.1 Начало скрипта
Первые две строчки кода указывают, что в трее не будет иконки от скрипта и то что он выполняется с правами админа.

Visual Basic:


Код:
#
NoTrayIcon
#
RequireAdmin
Затем идут настройки конкретно для AutoIT.

Visual Basic:


Код:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#
AutoIt3Wrapper_Icon
=
ICONS
/
Logo
.
ico
#
AutoIt3Wrapper_Outfile_x64
=
GenP
-
3.4
.14
.1
.
exe
#
AutoIt3Wrapper_Res_Comment
=
GenP v3
.4
.14
.1
#
AutoIt3Wrapper_Res_Description
=
GenP v3
.4
.14
.1
#
AutoIt3Wrapper_Res_Fileversion
=
3.4
.14
.1
#
AutoIt3Wrapper_Res_ProductName
=
GenP v3
.4
.14
.1
#
AutoIt3Wrapper_Res_ProductVersion
=
3.4
.14
.1
#
AutoIt3Wrapper_Res_CompanyName
=
GenP
#
AutoIt3Wrapper_Res_LegalCopyright
=
GenP
#
AutoIt3Wrapper_Res_LegalTradeMarks
=
GenP
#
AutoIt3Wrapper_Res_requestedExecutionLevel
=
asInvoker
#
AutoIt3Wrapper_Run_Au3Stripper
=
y
#
Au3Stripper_Parameters
=
/
pe
/
sf
/
sv
/
rm
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
  • Код:
    #NoTrayIcon
    - отключает иконку в системном трее для этого скрипта.
  • Код:
    #RequireAdmin
    - требует права администратора для выполнения скрипта.
  • Код:
    #AutoIt3Wrapper_Icon=ICONS/Logo.ico
    - задает иконку для исполняемого файла.
  • Код:
    #AutoIt3Wrapper_Outfile_x64=GenP-3.4.14.1.exe
    - указывает имя выходного файла для 64-битной системы.
  • Код:
    #AutoIt3Wrapper_Res_*
    - различные настройки ресурсов, такие как комментарии, описание, версия файла и продукта, имя компании, авторские права и торговые марки.
  • Код:
    #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
    - устанавливает уровень выполнения для исполняемого файла (в данном случае, как вызывающий).
  • Код:
    #AutoIt3Wrapper_Run_Au3Stripper=y
    - включает использование Au3Stripper, инструмента для уменьшения размера скрипта.
  • Код:
    #Au3Stripper_Parameters=/pe /sf /sv /rm
    - параметры для Au3Stripper, которые включают удаление комментариев, пустых строк и других ненужных элементов.
Затем идут include'ы.

Visual Basic:


Код:
#
include

#
include

#
include

#
include

#
include

#
include

#
include

#
include

#
include

#
include
Далее небольшой блок кода:

Visual Basic:


Код:
AutoItSetOption
(
"GUICloseOnESC"
,
0
)
;
1
=
ESC closes
,
0
=
ESC won
't close
Global
Const
$
g_AppWndTitle
=
"GenP v3.4.14.1"
,
$
g_AppVersion
=
"Original version by uncia/CGP - GenP Community Edition - v3.4.14.1"
If
_Singleton
(
$
g_AppWndTitle
,
1
)
=
0
Then
Exit
EndIf
Первая строка указывает, что при нажатии ESC окно программы не будет закрываться. Вторая строка указывает заголовок приложения и дополнительную информацию о приложении.
Блок
Код:
if
служит для запуска только одного экземпляра приложения.

Затем объявляются глобальные переменные:

Visual Basic:


Код:
Global
$
MyLVGroupIsExpanded
=
True
Global
$
fInterrupt
=
0
Global
$
FilesToPatch[
0
][
1
]
,
$
FilesToPatchNull[
0
][
1
]
Global
$
FilesToRestore[
0
][
1
]
,
$
fFilesListed
=
0
Global
$
MyhGUI
,
$
hTab
,
$
hMainTab
,
$
hLogTab
,
$
idMsg
,
$
idListview
,
$
g_idListview
,
$
idButtonSearch
,
$
idButtonStop
Global
$
idButtonCustomFolder
,
$
idBtnCure
,
$
idBtnDeselectAll
,
$
ListViewSelectFlag
=
1
Global
$
idBtnBlockPopUp
,
$
idBtnPatchCC
,
$
idMemo
,
$
timestamp
,
$
idLog
,
$
idBtnRestore
,
$
idBtnCopyLog
Далее идёт проверка наличия
Код:
config.ini
. Если его нет, то он создаётся по указанному пути.

Visual Basic:


Код:
Global
$
sINIPath
=
@
ScriptDir
&
"\config.ini"
If
Not
FileExists
(
$
sINIPath
)
Then
FileInstall
(
"config.ini"
,
@
ScriptDir
&
"\config.ini"
)
EndIf
Этот конфиг-файл выглядит так:

Часть контента скрыл, чтобы скрин поместился на экран. Этот файл важен для работы патчера, так как содержит названия файлов, что будет искать патчер, сами патчи и указания, какие конкретно патчи к чему применяются.
  1. Секция
    Код:
    [Default]
    :
    • Содержит ключ Path, который указывает путь по умолчанию до папки с программами Adobe.
  2. Секция
    Код:
    [TargetFiles]
    :
    • Содержит список файлов, которые будет искать патчер.
  3. Секция
    Код:
    [DefaultPatterns]
    :
    • Содержит ключ Values с набором имён применяемых патчей. Используется для тех программ, что нет в [CustomPatterns].
  4. Секция
    Код:
    [CustomPatterns]
    :
    • Содержит ключи для различных файлов и их соответствующие имена патчей.
  5. Секция
    Код:
    [Patches]
    :
    • Содержит ключи (имена патчей) и значения (сами патчи в виде искомых и заменяемых байт).
Затем мы читаем из INI-файла путь до папки с программами Adobe по умолчанию. Если указанного пути нет, то используем путь по умолчанию - это
Код:
"C:\Program Files\Adobe"
. Также мы пишем этот путь в INI-файл.

Visual Basic:


Код:
Global
$
MyDefPath
=
IniRead
(
$
sINIPath
,
"Default"
,
"Path"
,
"C:\Program Files\Adobe"
)
If
Not
FileExists
(
$
MyDefPath
)
Or
Not
StringInStr
(
FileGetAttrib
(
$
MyDefPath
)
,
"D"
)
Then
IniWrite
(
$
sINIPath
,
"Default"
,
"Path"
,
"C:\Program Files\Adobe"
)
$
MyDefPath
=
"C:\Program Files\Adobe"
EndIf
Далее идёт работа с Nsudo - инструмент, позволяющий запускать процессы с правами System или TrustedInstaller. По описанию она нужна для корректной работы Adobe XD и приложений UWP.

Вот краткое объяснение функции:

Сначала происходит копирование файла
Код:
NSudoLG.exe
во временную директорию (обычно
Код:
C:\Users\\AppData\Local\Temp
). Далее проверка.

Если скрипт не запущен от имени
Код:
SYSTEM
и файл
Код:
NSudoLG.exe
существует:
Выводится диалоговое окно с вопросом о повышении привилегий до TrustedInstaller.
Если пользователь соглашается, скрипт перезапускается с повышенными привилегиями.
Если условия не выполнены:
Проверяется существование директории
Код:
"C:\Windows\System32\config\systemprofile\Desktop"
. Нужна для нормальной работы приложений, чьи привилегии были повышены.
Если директория не существует, она создаётся.
В конце удаление временного файла
Код:
NSudoLG.exe
.

Затем снова объявляются глобальные переменные:

Visual Basic:


Код:
Global
$
MyRegExpGlobalPatternSearchCount
=
0
,
$
Count
=
0
,
$
idProgressBar
Global
$
aOutHexGlobalArray[
0
]
,
$
aNullArray[
0
]
,
$
aInHexArray[
0
]
Global
$
MyFileToParse
=
""
,
$
MyFileToParsSweatPea
=
""
,
$
MyFileToParseEaclient
=
""
Global
$
sz_type
,
$
bFoundAcro32
=
False
,
$
bFoundLrARM
=
False
,
$
bFoundCCARM
=
False
,
$
bFoundPsARM
=
False
,
$
bFoundGenericARM
=
False
,
$
aSpecialFiles
,
$
sSpecialFiles
=
"|"
Global
$
ProgressFileCountScale
,
$
FileSearchedCount
Далее идёт код, что читает содержимое секций
Код:
TargetFiles
и
Код:
CustomPatterns
из
Код:
config.ini
.

Visual Basic:


Код:
Local
$
tTargetFileList_Adobe
=
IniReadSection
(
$
sINIPath
,
"TargetFiles"
)
Global
$
TargetFileList_Adobe[
0
]
If
Not
@
error
Then
ReDim
$
TargetFileList_Adobe[
$
tTargetFileList_Adobe[
0
][
0
]]
For
$
i
=
1
To
$
tTargetFileList_Adobe[
0
][
0
]
$
TargetFileList_Adobe[
$
i
-
1
]
=
StringReplace
(
$
tTargetFileList_Adobe[
$
i][
1
]
,
'"', "")
Next
EndIf
;_ArrayDisplay
(
$
TargetFileList_Adobe
,
"TargetFileList_Adobe"
)
$
aSpecialFiles
=
IniReadSection
(
$
sINIPath
,
"CustomPatterns"
)
;_ArrayDisplay
(
$
aSpecialFiles
)
For
$
i
=
1
To
UBound
(
$
aSpecialFiles
)
-
1
$
sSpecialFiles
=
$
sSpecialFiles
&
$
aSpecialFiles[
$
i][
0
]
&
"|"
Next
;MsgBox
(
0
,
""
,
$
sSpecialFiles
)
Тут есть даже отладочный код. Можно убрать комментарии и запустить скрипт с ним. Для дальнейшего понимания патчера важно запомнить, что:

Код:
$TargetFileList_Adobe
-
Код:
TargetFiles
из конфига.

Код:
$sSpecialFiles
-
Код:
CustomPatterns
из конфига.

Затем идёт блок кода для настройки GUI-части:

Visual Basic:


Код:
GUIRegisterMsg
(
$
WM_COMMAND
,
"WM_COMMAND"
)
MainGui
(
)
Функция
Код:
MainGui
находится в самом скрипте и создает графический интерфейс для приложения: табы, ListView, кнопки для выбора пути, поиска, патчинга, блокировки всплывающих окон и восстановления файлов, а также прогресс-бар и лог активности.
После этого идёт главный код в цикле
Код:
While 1
.

4.2 Основной цикл патчера

Visual Basic:


Код:
$
idMsg
=
GUIGetMsg
(
)
Select
Case
$
idMsg
=
$
GUI_EVENT_CLOSE
            GUIDelete
(
$
MyhGUI
)
Exit
Case
$
idMsg
=
$
GUI_EVENT_RESIZED
            ContinueCase
Case
$
idMsg
=
$
GUI_EVENT_RESTORE
            ContinueCase
Case
$
idMsg
=
$
GUI_EVENT_MAXIMIZE
            Local
$
iWidth
            Local
$
aGui
=
WinGetPos
(
$
MyhGUI
)
Local
$
aRect
=
_GUICtrlListView_GetViewRect
(
$
g_idListview
)
If
(
$
aRect[
2
]
>
$
aGui[
2
]
)
Then
$
iWidth
=
$
aGui[
2
]
-
75
Else
$
iWidth
=
$
aRect[
2
]
-
25
EndIf
GUICtrlSendMsg
(
$
idListview
,
$
LVM_SETCOLUMNWIDTH
,
1
,
$
iWidth
)
Этот фрагмент настраивает закрытие окна, изменение его размера и максимизацию. Далее идёт обработка кнопки "Stop" в поиске.

Далее в коде будет обработка событий для кнопки "Search".

4.2.1. Обработчик кнопки поиска
В самом начале идёт настройка списка файлов (в
Код:
ListView
) под вывод и появление надписи, что нам нужно подождать:

Visual Basic:


Код:
Case
$
idMsg
=
$
idButtonSearch
$
fInterrupt
=
0
GUICtrlSetState
(
$
idButtonSearch
,
$
GUI_HIDE
)
GUICtrlSetState
(
$
idButtonStop
,
$
GUI_SHOW
)
ToggleLog
(
0
)
GUICtrlSetState
(
$
idBtnDeselectAll
,
128
)
GUICtrlSetState
(
$
idBtnBlockPopUp
,
128
)
GUICtrlSetState
(
$
idListview
,
128
)
GUICtrlSetState
(
$
idBtnCure
,
128
)
GUICtrlSetState
(
$
idButtonCustomFolder
,
128
)
GUICtrlSetState
(
$
idBtnPatchCC
,
128
)
;Search through all files
and
folders
in
directory
and
fill ListView
            _GUICtrlListView_DeleteAllItems
(
$
g_idListview
)
_GUICtrlListView_SetExtendedListViewStyle
(
$
idListview
,
BitOR
(
$
LVS_EX_FULLROWSELECT
,
$
LVS_EX_GRIDLINES
,
$
LVS_EX_DOUBLEBUFFER
)
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
0
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
1
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
2
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
2
)
_GUICtrlListView_RemoveAllGroups
(
$
idListview
)
_GUICtrlListView_InsertGroup
(
$
idListview
,
-
1
,
1
,
""
,
1
)
; Group
1
_GUICtrlListView_SetGroupInfo
(
$
idListview
,
1
,
"Info"
,
1
,
$
LVGS_COLLAPSIBLE
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
0
,
""
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
1
,
"Preparing..."
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
2
,
""
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
3
,
"Be patient, please."
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
0
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
1
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
2
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
3
,
1
)
_Expand_All_Click
(
)
_GUICtrlListView_SetGroupInfo
(
$
idListview
,
1
,
"Info"
,
1
,
$
LVGS_COLLAPSIBLE
)
Функция
Код:
_Expand_All_Click
самописная:

Visual Basic:


Код:
Func _Expand_All_Click
(
)
Local
$
aInfo
,
$
aCount
=
_GUICtrlListView_GetGroupCount
(
$
idListview
)
; Group Count
If
$
aCount
>
0
Then
; Change group information
For
$
i
=
1
To
28
$
aInfo
=
_GUICtrlListView_GetGroupInfo
(
$
idListview
,
$
i
)
_GUICtrlListView_SetGroupInfo
(
$
idListview
,
$
i
,
$
aInfo[
0
]
,
$
aInfo[
1
]
,
$
LVGS_NORMAL
)
_GUICtrlListView_SetGroupInfo
(
$
idListview
,
$
i
,
$
aInfo[
0
]
,
$
aInfo[
1
]
,
$
LVGS_COLLAPSIBLE
)
Next
EndIf
EndFunc   ;
=
=
>
_Expand_All_Click
Также есть обратная функция:

Visual Basic:


Код:
Func _Collapse_All_Click
(
)
Local
$
aInfo
,
$
aCount
=
_GUICtrlListView_GetGroupCount
(
$
idListview
)
; Group Count
If
$
aCount
>
0
Then
If
$
MyLVGroupIsExpanded
=
1
Then
; Change group information
For
$
i
=
1
To
28
$
aInfo
=
_GUICtrlListView_GetGroupInfo
(
$
idListview
,
$
i
)
_GUICtrlListView_SetGroupInfo
(
$
idListview
,
$
i
,
$
aInfo[
0
]
,
$
aInfo[
1
]
,
$
LVGS_COLLAPSED
)
Next
Else
_Expand_All_Click
(
)
EndIf
$
MyLVGroupIsExpanded
=
Not
$
MyLVGroupIsExpanded
EndIf
EndFunc   ;
=
=
>
_Collapse_All_Click
Код:
_Expand_All_Click
: Раскрывает все группы в ListView, делая их видимыми и сворачиваемыми.

Код:
_Collapse_All_Click
: Сворачивает все группы, если они были раскрыты, и наоборот, раскрывает все группы, если они были свернуты.

Далее идут подготовительные блоки:

Visual Basic:


Код:
; Clear previous results
$
FilesToPatch
=
$
FilesToPatchNull
$
FilesToRestore
=
$
FilesToPatchNull
$
timestamp
=
TimerInit
(
)
Очищаем предыдущие результаты и настраиваем таймер. Затем идёт блок, что ищет файлы, считает их количество, настраивает прогресс-бар и некоторые переменные.

Visual Basic:


Код:
Local
$
FileCount
            Local
$
aSize
=
DirGetSize
(
$
MyDefPath
,
$
DIR_EXTENDED
)
; extended mode
If
UBound
(
$
aSize
)
>
=
2
Then
$
FileCount
=
$
aSize[
1
]
$
ProgressFileCountScale
=
100
/
$
FileCount
$
FileSearchedCount
=
0
ProgressWrite
(
0
)
RecursiveFileSearch
(
$
MyDefPath
,
0
,
$
FileCount
)
;Search through all files
and
folders
                Sleep
(
100
)
ProgressWrite
(
0
)
EndIf
Параметр
Код:
$MyDefPath
в этот момент содержит содержимое секции
Код:
[Default]
из INI-файла:

INI:


Код:
[Default]
Path
=C:\Program Files\Adobe
Функция
Код:
RecursiveFileSearch
самописная:

Visual Basic:


Код:
Func RecursiveFileSearch
(
$
INSTARTDIR
,
$
DEPTH
,
$
FileCount
)
;_FileListToArrayEx
    _GUICtrlListView_SetItemText
(
$
idListview
,
1
,
"Searching for files."
,
1
)
;_GUICtrlListView_SetItemGroupID
(
$
idListview
,
0
,
1
)
Local
$
RecursiveFileSearch_MaxDeep
=
6
; Local
$
RecursiveFileSearch_WhenFoundRaiseToLevel
=
0
;
0
to
disable raising
If
$
DEPTH
>
$
RecursiveFileSearch_MaxDeep
Then
Return
Local
$
STARTDIR
=
$
INSTARTDIR
&
"\"
$
FileSearchedCount
+
=
1
Local
$
HSEARCH
=
FileFindFirstFile
(
$
STARTDIR
&
"*.*"
)
If
@
error
Then
Return
Local
$
NEXT
,
$
IPATH
,
$
isDir
While
$
fInterrupt
=
0
$
NEXT
=
FileFindNextFile
(
$
HSEARCH
)
$
FileSearchedCount
+
=
1
If
@
error
Then
ExitLoop
$
isDir
=
StringInStr
(
FileGetAttrib
(
$
STARTDIR
&
$
NEXT
)
,
"D"
)
If
$
isDir
Then
Local
$
targetDepth
$
targetDepth
=
RecursiveFileSearch
(
$
STARTDIR
&
$
NEXT
,
$
DEPTH
+
1
,
$
FileCount
)
; raise up
in
recursion
to
wanted level
;~
if
(
$
targetDepth
>
0
)
and
_
;~
(
$
targetDepth

1
Then
If
Not
StringInStr
(
$
IPATH
,
".bak"
)
Then
;_ArrayAdd
(
$
FilesToPatch
,
$
DEPTH
&
" - "
&
$
IPATH
)
If
StringInStr
(
$
IPATH
,
"Adobe"
)
Or
StringInStr
(
$
IPATH
,
"Acrobat"
)
Then
If
StringInStr
(
$
IPATH
,
"4.js"
)
And
Not
StringInStr
(
$
IPATH
,
"UXP\com.adobe.ccx.start\js\4.js"
)
Then
Return
EndIf
If
StringInStr
(
$
IPATH
,
"manifest.json"
)
And
Not
StringInStr
(
$
IPATH
,
"UXP\com.adobe.ccx.start\manifest.json"
)
Then
Return
EndIf
_ArrayAdd
(
$
FilesToPatch
,
$
IPATH
)
EndIf
Else
_ArrayAdd
(
$
FilesToRestore
,
$
IPATH
)
EndIf
; File Found
and
stored
-
Quit search
in
current dir
;~
return
$
RecursiveFileSearch_WhenFoundRaiseToLevel
EndIf
Next
EndIf
EndIf
WEnd
;Lazy screenupdates
If
1
=
Random
(
0
,
10
,
1
)
Then
MemoWrite
(
@
CRLF
&
"Searching in "
&
$
FileCount
&
" files"
&
@
TAB
&
@
TAB
&
"Found : "
&
UBound
(
$
FilesToPatch
)
&
@
CRLF
&
_
"---"
&
@
CRLF
&
_
"Level: "
&
$
DEPTH
&
" Time elapsed : "
&
Round
(
TimerDiff
(
$
timestamp
)
/
1000
,
0
)
&
" second(s)"
&
@
TAB
&
@
TAB
&
"Excluded because of *.bak: "
&
UBound
(
$
FilesToRestore
)
&
@
CRLF
&
_
"---"
&
@
CRLF
&
_
$
INSTARTDIR
_
)
ProgressWrite
(
$
ProgressFileCountScale
*
$
FileSearchedCount
)
EndIf
FileClose
(
$
HSEARCH
)
EndFunc   ;
=
=
>
RecursiveFileSearch
Она выполняет поиск файлов из
Код:
$TargetFileList_Adobe
(секция
Код:
[TargetFiles]
в INI) и добавляет пути до них в массив
Код:
$FilesToPatch
- файла для патчинга, которые нашлись из
Код:
[TargetFiles]
. Также если где-то нашлись бекапы оригинальных файлов (с постфиксом
Код:
.bak
), то они добавляются в
Код:
$FilesToRestore
.
Для теста можно добавить вывод массива в процессе работы.

Или так:

Также в логах выводится дополнительная информация.
Далее в обработчике кнопки поиска идёт блок, который также ищет файлы, но в заранее определённых директориях Adobe (по умолчанию). Оба блока нужны, чтобы обработать случаи, когда путь до файлов Adobe стандартный (по умолчанию) и кастомный.

Visual Basic:


Код:
If
$
MyDefPath
=
"C:\Program Files"
Or
$
MyDefPath
=
"C:\Program Files\Adobe"
Then
Local
$
sProgramFiles
=
EnvGet
(
'ProgramFiles(x86)') & "\Common Files\Adobe"
$
aSize
=
DirGetSize
(
$
sProgramFiles
,
$
DIR_EXTENDED
)
; extended mode
If
UBound
(
$
aSize
)
>
=
2
Then
$
FileCount
=
$
aSize[
1
]
                    RecursiveFileSearch
(
$
sProgramFiles
,
0
,
$
FileCount
)
;Search through all files
and
folders
                    ProgressWrite
(
0
)
EndIf
EndIf
Затем идёт вывод найденных файлов через самописную функцию
Код:
FillListViewWithFiles
:

Visual Basic:


Код:
Func FillListViewWithFiles
(
)
_GUICtrlListView_DeleteAllItems
(
$
g_idListview
)
_GUICtrlListView_SetExtendedListViewStyle
(
$
idListview
,
BitOR
(
$
LVS_EX_FULLROWSELECT
,
$
LVS_EX_GRIDLINES
,
$
LVS_EX_DOUBLEBUFFER
,
$
LVS_EX_CHECKBOXES
)
)
; Two column load
If
UBound
(
$
FilesToPatch
)
>
0
Then
Global
$
aItems[UBound
(
$
FilesToPatch
)
][
2
]
For
$
i
=
0
To
UBound
(
$
aItems
)
-
1
$
aItems[
$
i][
0
]
=
$
i
$
aItems[
$
i][
1
]
=
$
FilesToPatch[
$
i][
0
]
Next
_GUICtrlListView_AddArray
(
$
idListview
,
$
aItems
)
MemoWrite
(
@
CRLF
&
UBound
(
$
FilesToPatch
)
&
" File(s) were found in "
&
Round
(
TimerDiff
(
$
timestamp
)
/
1000
,
0
)
&
" second(s) at:"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyDefPath
&
@
CRLF
&
"---"
&
@
CRLF
&
"Press the 'Patch Files'"
)
LogWrite
(
1
,
UBound
(
$
FilesToPatch
)
&
" File(s) were found in "
&
Round
(
TimerDiff
(
$
timestamp
)
/
1000
,
0
)
&
" second(s)"
&
@
CRLF
)
;_ArrayDisplay
(
$
FilesToPatch
)
$
fFilesListed
=
1
Else
MemoWrite
(
@
CRLF
&
"Nothing was found in"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyDefPath
&
@
CRLF
&
"---"
&
@
CRLF
&
"waiting for user action"
)
LogWrite
(
1
,
"Nothing was found in "
&
$
MyDefPath
)
$
fFilesListed
=
0
EndIf
EndFunc   ;
=
=
>
FillListViewWithFiles
Информация выводится в логах. В конце обработчика кнопки будет настройка GUI-частей.
Также есть такие небольшие функции:

Visual Basic:


Код:
; Write a line
to
the memo control
Func MemoWrite
(
$
sMessage
)
GUICtrlSetData
(
$
idMemo
,
$
sMessage
)
EndFunc   ;
=
=
>
MemoWrite

Func LogWrite
(
$
bTS
,
$
sMessage
)
GUICtrlSetDataEx
(
$
idLog
,
$
sMessage
,
$
bTS
)
EndFunc   ;
=
=
>
LogWrite

Func ToggleLog
(
$
bShow
)
If
$
bShow
=
1
Then
GUICtrlSetState
(
$
idMemo
,
$
GUI_HIDE
)
GUICtrlSetState
(
$
idLog
,
$
GUI_SHOW
)
Else
GUICtrlSetState
(
$
idLog
,
$
GUI_HIDE
)
GUICtrlSetState
(
$
idMemo
,
$
GUI_SHOW
)
EndIf
EndFunc   ;
=
=
>
ToggleLog

Func SendToClipBoard
(
)
If
BitAND
(
GUICtrlGetState
(
$
idMemo
)
,
$
GUI_HIDE
)
=
$
GUI_HIDE
Then
ClipPut
(
GUICtrlRead
(
$
idLog
)
)
Else
ClipPut
(
GUICtrlRead
(
$
idMemo
)
)
EndIf
EndFunc   ;
=
=
>
SendToClipBoard
Краткое описание этих функций:
  1. Код:
    MemoWrite
    записывает строку текста в элемент управления
    Код:
    Memo
    (текстовое поле для многострочного ввода).
  2. Код:
    LogWrite
    записывает строку текста в элемент управления
    Код:
    Log
    (журнал) со временной меткой к сообщению или без неё.
  3. Код:
    ToggleLog
    переключает видимость между элементами управления
    Код:
    Memo
    и
    Код:
    Log
    .
  4. Код:
    SendToClipBoard
    копирует текст из видимого элемента управления (либо
    Код:
    Memo
    , либо
    Код:
    Log
    ) в буфер обмена. Если элемент
    Код:
    Memo
    скрыт, копируется текст из
    Код:
    Log
    , иначе копируется текст из
    Код:
    Memo
    .
Тут можно увидеть использование функции
Код:
GUICtrlSetDataEx
. Её код прилагается:

Visual Basic:


Код:
Func GUICtrlSetDataEx
(
$
hWnd
,
$
sText
,
$
bTS
)
If
Not
IsHWnd
(
$
hWnd
)
Then
$
hWnd
=
GUICtrlGetHandle
(
$
hWnd
)
Local
$
iLength
=
DllCall
(
"user32.dll"
,
"lresult"
,
"SendMessageW"
,
"hwnd"
,
$
hWnd
,
"uint"
,
0
x000E
,
"wparam"
,
0
,
"lparam"
,
0
)
DllCall
(
"user32.dll"
,
"lresult"
,
"SendMessageW"
,
"hwnd"
,
$
hWnd
,
"uint"
,
0
xB1
,
"wparam"
,
$
iLength[
0
]
,
"lparam"
,
$
iLength[
0
]
)
;
$
EM_SETSEL
If
$
bTS
=
1
Then
Local
$
iData
=
@
CRLF
&
@
YEAR
&
"-"
&
@
MON
&
"-"
&
@
MDAY
&
" "
&
@
HOUR
&
":"
&
@
MIN
&
":"
&
@
SEC
&
"."
&
@
MSEC
&
" "
&
$
sText
Else
Local
$
iData
=
$
sText
EndIf
DllCall
(
"user32.dll"
,
"lresult"
,
"SendMessageW"
,
"hwnd"
,
$
hWnd
,
"uint"
,
0
xC2
,
"wparam"
,
True
,
"wstr"
,
$
iData
)
;
$
EM_REPLACESEL
EndFunc   ;
=
=
>
GUICtrlSetDataEx
Она выполняет запись текста в элемент управления (например, текстовое поле) с возможностью добавления временной метки.

4.2.2. Обработчик кнопки выбора папки
Далее идёт обработчик выбора своей папки с программами Adobe вместо стандартной.

Visual Basic:


Код:
Case
$
idMsg
=
$
idButtonCustomFolder     ;
Select
Custom Path

            ToggleLog
(
0
)
MyFileOpenDialog
(
)
_Expand_All_Click
(
)
If
$
fFilesListed
=
0
Then
GUICtrlSetState
(
$
idBtnCure
,
128
)
GUICtrlSetState
(
$
idBtnDeselectAll
,
128
)
GUICtrlSetState
(
$
idButtonSearch
,
64
)
GUICtrlSetState
(
$
idButtonSearch
,
256
)
;
Set
focus
Else
GUICtrlSetState
(
$
idButtonSearch
,
128
)
GUICtrlSetState
(
$
idBtnDeselectAll
,
64
)
GUICtrlSetState
(
$
idBtnCure
,
64
)
GUICtrlSetState
(
$
idBtnCure
,
256
)
;
Set
focus
EndIf
Функция
Код:
MyFileOpenDialog
самописная.

Visual Basic:


Код:
Func MyFileOpenDialog
(
)
; Create a constant variable
in
Local scope
of
the message
to
display
in
FileOpenDialog
.
Local
Const
$
sMessage
=
"Select a Path"
; Display an open dialog
to
select
a file
.
FileSetAttrib
(
"C:\Program Files\WindowsApps"
,
"-H"
)
Local
$
MyTempPath
=
FileSelectFolder
(
$
sMessage
,
$
MyDefPath
,
0
,
$
MyDefPath
,
$
MyhGUI
)
If
@
error
Then
; Display the
error
message
.
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"No folder was selected."
)
FileSetAttrib
(
"C:\Program Files\WindowsApps"
,
"+H"
)
MemoWrite
(
@
CRLF
&
"Path"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyDefPath
&
@
CRLF
&
"---"
&
@
CRLF
&
"waiting for user action"
)
Else
GUICtrlSetState
(
$
idBtnCure
,
128
)
$
MyDefPath
=
$
MyTempPath
        IniWrite
(
$
sINIPath
,
"Default"
,
"Path"
,
$
MyDefPath
)
_GUICtrlListView_DeleteAllItems
(
$
g_idListview
)
_GUICtrlListView_SetExtendedListViewStyle
(
$
idListview
,
BitOR
(
$
LVS_EX_GRIDLINES
,
$
LVS_EX_FULLROWSELECT
,
$
LVS_EX_SUBITEMIMAGES
)
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
0
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
1
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
2
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
3
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
4
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
5
)
_GUICtrlListView_AddItem
(
$
idListview
,
""
,
6
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
0
,
""
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
1
,
"Path:"
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
2
,
" "
&
$
MyDefPath
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
3
,
"Step 1:"
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
4
,
" Press 'Search Files' - wait until GenP finds all files"
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
5
,
"Step 2:"
,
1
)
_GUICtrlListView_AddSubItem
(
$
idListview
,
6
,
" Press 'Patch Files' - wait until GenP will do it's job"
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
0
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
1
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
2
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
3
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
4
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
5
,
1
)
_GUICtrlListView_SetItemGroupID
(
$
idListview
,
6
,
1
)
_GUICtrlListView_SetGroupInfo
(
$
idListview
,
1
,
"Info"
,
1
,
$
LVGS_COLLAPSIBLE
)
FileSetAttrib
(
"C:\Program Files\WindowsApps"
,
"+H"
)
MemoWrite
(
@
CRLF
&
"Path"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyDefPath
&
@
CRLF
&
"---"
&
@
CRLF
&
"Press the Search button"
)
; Display the selected folder
.
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"You chose the following folder:"
&
@
CRLF
&
$
MyDefPath
)
GUICtrlSetState
(
$
idBtnBlockPopUp
,
$
GUI_SHOW
)
GUICtrlSetState
(
$
idBtnRestore
,
$
GUI_HIDE
)
$
fFilesListed
=
0
EndIf
EndFunc   ;
=
=
>
MyFileOpenDialog
Она отображает диалоговое окно для выбора папки и снимает скрытый атрибут с папки
Код:
C:\Program Files\WindowsApps
. Если папка выбрана, обновляет путь, сохраняет его в INI-файле, очищает и обновляет
Код:
ListView
с новыми элементами, восстанавливает скрытый атрибут и выводит сообщение с инструкцией.

4.2.3. Обработчик кнопки выбора/отмены всех элементов
Затем идёт обработчик для выбора или отмены выбора всех элементов:

Visual Basic:


Код:
Case
$
idMsg
=
$
idBtnDeselectAll     ; Deselect
-
Select
All
            ToggleLog
(
0
)
If
$
ListViewSelectFlag
=
1
Then
For
$
i
=
0
To
_GUICtrlListView_GetItemCount
(
$
idListview
)
-
1
_GUICtrlListView_SetItemChecked
(
$
idListview
,
$
i
,
0
)
Next
$
ListViewSelectFlag
=
0
;
Set
Flag
to
Deselected State
Else
For
$
i
=
0
To
_GUICtrlListView_GetItemCount
(
$
idListview
)
-
1
_GUICtrlListView_SetItemChecked
(
$
idListview
,
$
i
,
1
)
Next
$
ListViewSelectFlag
=
1
;
Set
Flag
to
Selected State
EndIf
4.2.4. Обработчик кнопки Pop-up
Следующий обработчик для кнопки "Pop-up":

Visual Basic:


Код:
Case
$
idMsg
=
$
idBtnBlockPopUp     ; Pop
-
up button
            ToggleLog
(
0
)
BlockPopUp
(
)
Функцию
Код:
BlockPopUp
нам нужно разобрать.

Visual Basic:


Код:
Func BlockPopUp
(
)
GUICtrlSetState
(
$
hLogTab
,
$
GUI_SHOW
)
GUICtrlSetState
(
$
idBtnBlockPopUp
,
128
)
MemoWrite
(
@
CRLF
&
"Checking for an active internet connection..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Local
$
sCmdInfo
=
"""C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe"" -Command ""Test-Connection 8.8.8.8 -Count 1 -Quiet"""
Local
$
iPID
=
Run
(
$
sCmdInfo
,
""
,
@
SW_HIDE
,
BitOR
(
$
STDERR_CHILD
,
$
STDOUT_CHILD
)
)
Local
$
sOutput
=
""
While
1
$
sOutput
&
=
StdoutRead
(
$
iPID
)
If
@
error
Then
ExitLoop
WEnd
ProcessWaitClose
(
$
iPID
)
If
StringReplace
(
$
sOutput
,
@
CRLF
,
""
)
=
"True"
Then
Тут происходит настройка GUI и проверка наличия интернет-соединения через Powershell-команду:

Bash:


Код:
Test-Connection
8.8
.8.8 -Count
1
-Quiet
Она вернёт нам True, если интернет есть.
Затем идёт блок кода для разрешения IP-адресов доменов
Код:
adobe.io
и
Код:
3u6k9as4bj.adobestats.io
.

Visual Basic:


Код:
If
StringReplace
(
$
sOutput
,
@
CRLF
,
""
)
=
"True"
Then
MemoWrite
(
@
CRLF
&
"Resolving ip-addresses..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
$
sCmdInfo
=
; Powershell
-
скрипт
$
iPID
=
Run
(
$
sCmdInfo
,
""
,
@
SW_HIDE
,
BitOR
(
$
STDERR_CHILD
,
$
STDOUT_CHILD
)
)
$
sOutput
=
""
While
1
$
sOutput
&
=
StdoutRead
(
$
iPID
)
If
@
error
Then
ExitLoop
WEnd
ProcessWaitClose
(
$
iPID
)
If
StringInStr
(
$
sOutput
,
"False"
)
Then
MemoWrite
(
@
CRLF
&
"Failed to resolve ip-addresses, try using a VPN..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
2000
)
Else
.
.
.
Разрешение IP-адресов (или "резолвинг" IP-адресов) — это процесс преобразования доменного имени (например,
Код:
example.com
) в его соответствующий IP-адрес (например,
Код:
101.34.200.8
).
В функции выполняется PowerShell-скрипт для разрешения IP-адресов доменов
Код:
adobe.io
и
Код:
3u6k9as4bj.adobestats.io
:
  • Читается вывод скрипта в переменную
    Код:
    $sOutput
    .
  • Если в выводе содержится "False", записывает сообщение о неудаче в журнал и предлагает использовать VPN.
  • Иначе добавляется правило в брандмауэр Windows для блокировки IP-адресов. Это разберём далее.
Пока перейдём к самому скрипту. Изначально он был в однострочном виде, но для нашего удобства представим его так:

Bash:


Код:
$currentDate
=
Get-Date
$ipAddresses
=
@
(
)
try
{
$SOA
=
(
Resolve-DnsName -Name adobe.io -Type SOA -ErrorAction Stop
)
.PrimaryServer
}
catch
{
$SOA
=
$null
}
if
(
$SOA
)
{
Do
{
if
((New-TimeSpan -Start $currentDate -End (Get-Date))
.TotalSeconds -gt
5
)
{
if
(
$ipAddresses
.Count -eq
0
)
{
$ipAddresses
+=
'False'
}
break
}
try
{
$ipAddress
=
(
Resolve-DnsName -Name adobe.io -Server
$SOA
-ErrorAction Stop
)
.IPAddress
}
catch
{
$ipAddress
=
$null
}
if
(
$ipAddress
)
{
$ipAddresses
+=
$ipAddress
}
$ipAddresses
=
$ipAddresses
|
Select -Unique
|
Sort-Object
}
While
(
$ipAddresses
.Count -lt
8
)
}
else
{
$ipAddresses
+=
'False'
}
Do
{
if
((New-TimeSpan -Start $currentDate -End (Get-Date))
.TotalSeconds -gt
5
-or
$ipAddresses
[
0
]
-eq
'False'
)
{
break
}
try
{
$ipAddress
=
(
Resolve-DnsName -Name 3u6k9as4bj.adobestats.io -ErrorAction Stop
)
.IPAddress
}
catch
{
$ipAddress
=
$null
}
if
(
$ipAddress
)
{
$ipAddresses
+=
$ipAddress
}
$ipAddresses
=
$ipAddresses
|
Select -Unique
|
Sort-Object
}
While
(
$ipAddresses
.Count -lt
12
-and
$ipAddresses
[
0
]
-ne
'False'
)
$ipAddresses
=
$ipAddresses
-ne
'False'
|
Select -Unique
|
Sort-Object
$ipAddressList
=
if
(
$ipAddresses
.Count -eq
0
)
{
'False'
}
else
{
$ipAddresses
-join
','
}
$ipAddressList
Скрипт определяет авторитетный сервер (SOA) для домена
Код:
adobe.io
. Затем собирает уникальные IP-адреса для доменов
Код:
adobe.io
и
Код:
3u6k9as4bj.adobestats.io
.
В итоге мы получим список уникальных IP-адресов такого вида:

Код:


Код:
107.22.247.231,18.207.85.246,23.22.254.206...
Затем идёт блок Else, что добавляет правило в брандмауэр Windows для блокировки IP-адресов:

Visual Basic:


Код:
If
StringInStr
(
$
sOutput
,
"False"
)
Then
MemoWrite
(
@
CRLF
&
"Failed to resolve ip-addresses, try using a VPN..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
2000
)
Else
MemoWrite
(
@
CRLF
&
"Adding Windows Firewall rule..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
$
sCmdInfo
=
"netsh advfirewall firewall delete rule name=""Adobe Unlicensed Pop-up"""
$
iPID
=
Run
(
$
sCmdInfo
,
""
,
@
SW_HIDE
,
BitOR
(
$
STDERR_CHILD
,
$
STDOUT_CHILD
)
)
ProcessWaitClose
(
$
iPID
)
$
sCmdInfo
=
"netsh advfirewall firewall add rule name=""Adobe Unlicensed Pop-up"" dir=out action=block remoteip="""
&
StringReplace
(
$
sOutput
,
@
CRLF
,
""
)
&
""""
$
iPID
=
Run
(
$
sCmdInfo
,
""
,
@
SW_HIDE
,
BitOR
(
$
STDERR_CHILD
,
$
STDOUT_CHILD
)
)
ProcessWaitClose
(
$
iPID
)
EndIf
Данный код удаляет старое правило в брандмауэре, если оно было:

Bash:


Код:
netsh advfirewall firewall delete rule
name
=
"Adobe Unlicensed Pop-up"
Затем уже добавляет своё:

Bash:


Код:
netsh advfirewall firewall
add
rule
name
=
"Adobe Unlicensed Pop-up"
dir
=
out
action
=
block
remoteip
=
"..."
Вместо "..." подставятся IP из прошлого ps-скрипта. Получим команду подобного вида:

Bash:


Код:
netsh advfirewall firewall
add
rule
name
=
"Adobe Unlicensed Pop-up"
dir
=
out
action
=
block
remoteip
=
"107.22.247.231,18.207.85.246,23.22.254.206..."
Далее идёт блок кода, что работает с файлом
Код:
hosts
.

Visual Basic:


Код:
MemoWrite
(
@
CRLF
&
"Blocking Hosts..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
$
sCmdInfo
=
; Powershell
-
скрипт
$
iPID
=
Run
(
$
sCmdInfo
,
""
,
@
SW_HIDE
,
$
STDOUT_CHILD
)
$
sOutput
=
""
While
1
$
sLine
=
StdoutRead
(
$
iPID
)
If
@
error
Then
ExitLoop
$
sOutput
&
=
$
sLine
WEnd
If
StringInStr
(
$
sOutput
,
"Script execution complete."
)
Then
MemoWrite
(
@
CRLF
&
"All Hosts blocked."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Else
MemoWrite
(
@
CRLF
&
"Failed to block Hosts, try using a VPN..."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
EndIf
Тут снова используется Powershell-скрипт:

Bash:


Код:
try
{
if
(
-not
(
[
Security.Principal.WindowsPrincipal
]
[
Security.Principal.WindowsIdentity
]
::GetCurrent
(
))
.IsInRole
(
[
Security.Principal.WindowsBuiltInRole
]
::Administrator
))
{
Write-Host
'Script execution failed...'
return
}
$hostsPath
=
'C:\Windows\System32\drivers\etc\hosts'
$bakPath
=
$hostsPath
+
'.bak'
if
(
-not
(
Test-Path
$bakPath
))
{
Copy-Item -Path
$hostsPath
-Destination
$bakPath
}
$webContent
=
(
Invoke-RestMethod -Uri
'https://a.dove.isdumb.one/list.txt'
-UseBasicParsing
)
.Split
(
$([char]0x0A)
)
|
ForEach-Object
{
$_
.Trim
(
)
}
$currentHostsContent
=
Get-Content -Path
$hostsPath
$startMarker
=
'# '
$endMarker
=
'# '
$blockStart
=
$currentHostsContent
.IndexOf
(
$startMarker
)
$blockEnd
=
$currentHostsContent
.IndexOf
(
$endMarker
)
if
(
$blockStart
-eq -1 -or
$blockEnd
-eq -1
)
{
$currentHostsContent
+=
$startMarker
$currentHostsContent
+=
$endMarker
$blockStart
=
$currentHostsContent
.IndexOf
(
$startMarker
)
$blockEnd
=
$currentHostsContent
.IndexOf
(
$endMarker
)
}
$newBlock
=
@
(
$startMarker
)
+
$webContent
+
$endMarker
$newHostsContent
=
$currentHostsContent
[
0
..
(
$blockStart
-
1
)
]
+
$newBlock
+
$currentHostsContent
[
(
$blockEnd
+
1
)
..
$currentHostsContent
.Length
]
Set-Content -Path
$hostsPath
-Value
$newHostsContent
Write-Host
'Script execution complete.'
}
catch
{
Write-Host
'Script execution failed...'
}
Данный скрипт выполняет предварительные действия:
  1. Проверка наличие прав администратора. Если нет, то завершает выполнение.
  2. Создание резервной копии файла
    Код:
    hosts
    :
    Код:
    C:\Windows\System32\drivers\etc\hosts.bak
  3. Загрузка файла
    Код:
    https://a.dove.isdumb.one/list.txt
    и разделяет загруженный контент по строкам и удаляет пробелы в начале и конце каждой строки.
Файл
Код:
list.txt
можно взять из этого репозитория: GitHub - ignaciocastro/a-dove-is-dumb: Easily block Adobe telemetry checking domains. Continuously Updated. Useful for HostsMan / SwitchHosts / Pi-hole users
А далее происходит работа с файлом
Код:
hosts
. Мы записываем содержимое
Код:
list.txt
между строками
Код:

.

До выполнения скрипта:

Код:


Код:
127.0.0.1 localhost
После:

Код:


Код:
127.0.0.1 localhost
# 
# Данные из list.txt
#
Таким образом, функция
Код:
BlockPopUp
просто добавляет правила в брандмауэр и записи в файл
Код:
hosts
. Теперь настало время самого интересного - начинаем разбор патчинга Creative Cloud и программ Adobe.

4.2.5. Обработчик кнопки "Patch CC" и как работает эта магия

Обработкой кнопки "Patch CC" занимается вот этот обработчик:

Visual Basic:


Код:
Case
$
idMsg
=
$
idBtnPatchCC     ; Patch Creative Cloud button
Global
$
appsPanelFile
Global
$
containerBLFile
Global
$
adobeDesktopServiceFile
.
.
.
Первое, что патчит код - это
Код:
AppsPanelBL.dll
.

Visual Basic:


Код:
If
FileExists
(
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
)
Then
$
appsPanelFile
=
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
ElseIf
FileExists
(
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
)
Then
$
appsPanelFile
=
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
Else
$
appsPanelFile
=
FileOpenDialog
(
"Select a File"
,
@
ScriptDir
,
"AppsPanelBL.dll (AppsPanelBL.dll)"
)
EndIf
ProgressWrite
(
0
)
If
FileExists
(
$
appsPanelFile
)
Then
MyGlobalPatternSearch
(
$
appsPanelFile
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"File Path:"
&
@
CRLF
&
""
&
@
CRLF
&
$
appsPanelFile
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
100
)
MyGlobalPatternPatch
(
$
appsPanelFile
,
$
aOutHexGlobalArray
)
Sleep
(
500
)
EndIf
Выполняется проверка на существование файла. А затем в нём ищутся паттерны, которые будут взяты из INI-файла через
Код:
MyGlobalPatternSearch
.

Visual Basic:


Код:
Func MyGlobalPatternSearch
(
$
MyFileToParse
)
;ConsoleWrite
(
$
MyFileToParse
&
@
CRLF
)
$
aInHexArray
=
$
aNullArray   ; Nullifay Array that will contain Hex later
$
aOutHexGlobalArray
=
$
aNullArray     ; Nullifay Array that will contain Hex later

    ProgressWrite
(
0
)
$
MyRegExpGlobalPatternSearchCount
=
0
$
Count
=
15
Local
$
sFileName
=
StringRegExpReplace
(
$
MyFileToParse
,
"^.*\\"
,
""
)
Local
$
sExt
=
StringRegExpReplace
(
$
sFileName
,
"^.*\."
,
""
)
MemoWrite
(
@
CRLF
&
$
MyFileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
"Preparing to Analyze"
&
@
CRLF
&
"---"
&
@
CRLF
&
"*****"
)
LogWrite
(
1
,
"Checking File: "
&
$
sFileName
&
" "
)
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"$sFileName = "
&
$
sFileName
&
@
CRLF
&
"$sExt = "
&
$
sExt
)
If
$
sExt
=
"exe"
Then
_ProcessCloseEx
(
""""
&
$
sFileName
&
""""
)
EndIf
If
$
sFileName
=
"AppsPanelBL.dll"
Or
$
sFileName
=
"ContainerBL.dll"
Or
$
sFileName
=
"Adobe Desktop Service.exe"
Then
_ProcessCloseEx
(
"""Creative Cloud.exe"""
)
_ProcessCloseEx
(
"""Adobe Desktop Service.exe"""
)
Sleep
(
100
)
EndIf
If
StringInStr
(
$
sSpecialFiles
,
$
sFileName
)
Then
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"Special File: "
&
$
sFileName
)
LogWrite
(
0
,
" - using Custom Patterns"
)
ExecuteSearchPatterns
(
$
sFileName
,
0
,
$
MyFileToParse
)
Else
LogWrite
(
0
,
" - using Default Patterns"
)
ExecuteSearchPatterns
(
$
sFileName
,
1
,
$
MyFileToParse
)
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"File: "
&
$
sFileName
&
@
CRLF
&
"Not in Special Files"
)
EndIf
Sleep
(
100
)
EndFunc   ;
=
=
>
MyGlobalPatternSearch
Функции передаётся путь до файла. Затем из него извлекается:
  1. Имя файла вместе с расширением;
  2. Отдельно расширение файла.

Visual Basic:


Код:
If
$
sExt
=
"exe"
Then
_ProcessCloseEx
(
""""
&
$
sFileName
&
""""
)
EndIf
If
$
sFileName
=
"AppsPanelBL.dll"
Or
$
sFileName
=
"ContainerBL.dll"
Or
$
sFileName
=
"Adobe Desktop Service.exe"
Then
_ProcessCloseEx
(
"""Creative Cloud.exe"""
)
_ProcessCloseEx
(
"""Adobe Desktop Service.exe"""
)
Sleep
(
100
)
EndIf
Затем закрываются процессы Creative Cloud, чтобы успешно пропатчить нужный файл. В конце функции вызывается
Код:
ExecuteSearchPatterns
в зависимости от того, есть ли искомый файл в
Код:
$sSpecialFiles
- это секция
Код:
[CustomPatterns]
в INI-файле.

Для дальнейшего понимания патчера важно запомнить, что:

Код:
$TargetFileList_Adobe
-
Код:
TargetFiles
из конфига.

Код:
$sSpecialFiles
-
Код:
CustomPatterns
из конфига.

Если такой файл есть, то вызывается
Код:
ExecuteSearchPatterns($sFileName, 0, $MyFileToParse)
.
Иначе -
Код:
ExecuteSearchPatterns($sFileName, 1, $MyFileToParse)
.

Сейчас как раз разберём её.

Visual Basic:


Код:
Func ExecuteSearchPatterns
(
$
FileName
,
$
DefaultPatterns
,
$
MyFileToParse
)
Local
$
aPatterns
,
$
sPattern
,
$
sData
,
$
aArray
,
$
sSearch
,
$
sReplace
,
$
iPatternLength
If
$
DefaultPatterns
=
0
Then
$
aPatterns
=
IniReadArray
(
$
sINIPath
,
"CustomPatterns"
,
$
FileName
,
""
)
Else
$
aPatterns
=
IniReadArray
(
$
sINIPath
,
"DefaultPatterns"
,
"Values"
,
""
)
EndIf
;_ArrayDisplay
(
$
aPatterns
,
"Patterns for "
&
$
FileName
)
For
$
i
=
0
To
UBound
(
$
aPatterns
)
-
1
$
sPattern
=
$
aPatterns[
$
i]
$
sData
=
IniRead
(
$
sINIPath
,
"Patches"
,
$
sPattern
,
""
)
If
StringInStr
(
$
sData
,
"|"
)
Then
$
aArray
=
StringSplit
(
$
sData
,
"|"
)
If
UBound
(
$
aArray
)
=
3
Then
$
sSearch
=
StringReplace
(
$
aArray[
1
]
,
'"', '')
$
sReplace
=
StringReplace
(
$
aArray[
2
]
,
'"', '')
$
iPatternLength
=
StringLen
(
$
sSearch
)
If
$
iPatternLength

StringLen
(
$
sReplace
)
Or
Mod
(
$
iPatternLength
,
2
)

0
Then
MsgBox
(
$
MB_SYSTEMMODAL
,
"Error"
,
"Pattern Error in config.ini:"
&
$
sPattern
&
@
CRLF
&
$
sSearch
&
@
CRLF
&
$
sReplace
)
Exit
EndIf
;MsgBox
(
0
,
0
,
$
MyFileToParse
&
@
CRLF
&
$
sSearch
&
@
CRLF
&
$
aReplace
&
@
CRLF
&
$
sPattern
)
LogWrite
(
1
,
"Searching for: "
&
$
sPattern
&
": "
&
$
sSearch
)
MyRegExpGlobalPatternSearch
(
$
MyFileToParse
,
$
sSearch
,
$
sReplace
,
$
sPattern
)
;
Exit
;
STOP
AT FIRST VALUE
-
COMMENT
OUT
TO
CONTINUE
EndIf
;
Exit
EndIf
Next
EndFunc   ;
=
=
>
ExecuteSearchPatterns
Код:
$FileName
- имя файла

Код:
$DefaultPatterns
- 1 или 0 (True или False)

Код:
$MyFileToParse
- путь до файла

Если передаётся 0, то используется
Код:
[CustomPatterns]
. Иначе -
Код:
[DefaultPatterns]
. Затем начинается основной цикл, где происходит обработка данных из INI-файла и передача в
Код:
MyRegExpGlobalPatternSearch
.

4.2.5.1. Весь цикл поиска и патчинга кратко
Рассмотрим работу всего цикла поиска и патчинга, забегая немного вперёд. Посмотрим на INI-файл:

INI:


Код:
...
[DefaultPatterns]
Values
="ProfileExpired1","ProfileExpired3","ProfileExpired4","ProfileExpired5","ProfileExpired6","ValidateLicense1","ValidateLicense2","ValidateLicense3","CmpEax61","CmpEax62","CmpEax63","CmpEax64","Profile1","Profile2","Banner1","Banner2","InstantShutdown1"
[CustomPatterns]
Acrobat.dll
="Acrobat3","Acrobat5"
acrodistdll.dll
="Acrodist2","Acrodist3","Acrodist4","Acrodist5","AcroRegistry1","AcroNew1"
acrotray.exe
="AcroTray2","AcroTray3","AcroTray4","AcroTray5","AcroRegistry1","AcroNew1"
AppsPanelBL.dll
="CreativeCloud1","CreativeCloud2"
ContainerBL.dll
="CreativeCloud3"
...
[Patches]
CreativeCloud1
="8378????0F84????????8378????0F84????????8378????0F84????????33C0"|"C640????0F84????????C640????0F84????????C640????0F84????????33C0"
CreativeCloud2
="E8????????85C00F85????????83EC??8BCC89"|"E8????????FEC00F85????????83EC??8BCC89"
CreativeCloud3
="??????0F85890300"|"??????E98A030000"
Acrobat1
="488BCFE8????????85C00F84????????488D??????????488BCFE8????????85C075??8D"|"488BCFE8????????FFC00F84????????488D??????????488BCFE8????????31C075??8D"
Acrobat2
="6685C0740FE8????????6685C07405BB01000000"|"6685C07400E8????????6685C07400BB01000000"
Acrobat3
="6685C0741A6685??0F85??020000"|"6685C090906685??0F85??020000"
...
В секции
Код:
[CustomPatterns]
есть ключи, имена которых - это имена файлов для патчинга. У имён-файлов (ключей) есть значения. Значения используются в секции
Код:
[Patches]
, которая содержит байты для поиска и патчинга.
Например, если патчится файл
Код:
AppsPanelBL.dll
, то используются патчи
Код:
"CreativeCloud1"
,
Код:
"CreativeCloud2"
(из-за прямого указания в строке
Код:
AppsPanelBL.dll="CreativeCloud1","CreativeCloud2"
):

В секции патчей это будет:

INI:


Код:
CreativeCloud1
="8378????0F84????????8378????0F84????????8378????0F84????????33C0"|"C640????0F84????????C640????0F84????????C640????0F84????????33C0"
CreativeCloud2
="E8????????85C00F85????????83EC??8BCC89"|"E8????????FEC00F85????????83EC??8BCC89"
Байты для поиска и замены разделены символов
Код:
|
. Для
Код:
CreativeCloud1
будут искаться байты
Код:
"8378????0F84????????8378????0F84????????8378????0F84????????33C0"
, а заменой им будет
Код:
"C640????0F84????????C640????0F84????????C640????0F84????????33C0"
.
Затем поиск и замена будут выполнены для
Код:
CreativeCloud2
. До знаков вопроса в патчах мы сейчас дойдём. Для понимания нам нужно изучить
Код:
MyRegExpGlobalPatternSearch
. Вот так она вызывается в
Код:
MyRegExpGlobalPatternSearch
:

Visual Basic:


Код:
MyRegExpGlobalPatternSearch
(
$
MyFileToParse
,
$
sSearch
,
$
sReplace
,
$
sPattern
)
Код:
$MyFileToParse
- путь до файла

Код:
$sSearch
- байты, которые ищутся (до символа | в секции с патчами)

Код:
$sReplace
- байты, на которые произойдёт замена (после символа | в секции с патчами)

Код:
$sPattern
- значение ключа из набора в секции
Код:
[CustomPatterns]
(
Код:
CreativeCloud1
,
Код:
CreativeCloud2
и другие).

Функция
Код:
MyRegExpGlobalPatternSearch
:

Visual Basic:


Код:
Func MyRegExpGlobalPatternSearch
(
$
FileToParse
,
$
PatternToSearch
,
$
PatternToReplace
,
$
PatternName
)
; Path
to
a file
to
parse
    ;MsgBox
(
$
MB_SYSTEMMODAL
,
"Path"
,
$
FileToParse
)
;ConsoleWrite
(
$
FileToParse
&
@
CRLF
)
Local
$
hFileOpen
=
FileOpen
(
$
FileToParse
,
$
FO_READ
+
$
FO_BINARY
)
FileSetPos
(
$
hFileOpen
,
60
,
0
)
$
sz_type
=
FileRead
(
$
hFileOpen
,
4
)
FileSetPos
(
$
hFileOpen
,
Number
(
$
sz_type
)
+
4
,
0
)
$
sz_type
=
FileRead
(
$
hFileOpen
,
2
)
If
$
sz_type
=
"0x4C01"
And
StringInStr
(
$
FileToParse
,
"Acrobat"
,
2
)
>
0
Then
; Acrobat x86 won
't work with this script
MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
"File is 32bit. Aborting..."
&
@
CRLF
&
"---"
)
FileClose
(
$
hFileOpen
)
Sleep
(
100
)
$
bFoundAcro32
=
True
ElseIf
$
sz_type
=
"0x64AA"
Then
; AArch64
(
ARM64
)
and
~~AArch32
(
ARM32
)
architectures~~
(
big
-
endian
)
.
only exist
as
photoshop
,
lightroom
,
and
ccdesktop at time
of
writing
If
StringInStr
(
$
FileToParse
,
"Lightroom"
,
2
)
>
0
Then
; Lightroom ARM
            MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
"Lightroom is ARM. Aborting..."
&
@
CRLF
&
"---"
)
FileClose
(
$
hFileOpen
)
Sleep
(
100
)
$
bFoundLrARM
=
True
ElseIf
StringInStr
(
$
FileToParse
,
"AppsPanelBL.dll"
,
2
)
Or
StringInStr
(
$
FileToParse
,
"ContainerBL.dll"
,
2
)
Or
StringInStr
(
$
FileToParse
,
"Adobe Desktop Service.exe"
,
2
)
>
0
Then
; CC Desktop ARM
            MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
"Creative Cloud is ARM. Aborting..."
&
@
CRLF
&
"---"
)
FileClose
(
$
hFileOpen
)
Sleep
(
100
)
$
bFoundCCARM
=
True
ElseIf
StringInStr
(
$
FileToParse
,
"Photoshop"
,
2
)
>
0
Then
; Photoshop ARM
            MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
"Photoshop is ARM. Aborting..."
&
@
CRLF
&
"---"
)
FileClose
(
$
hFileOpen
)
Sleep
(
100
)
$
bFoundPsARM
=
True
Else
; Other ARM
            MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
"File is ARM. Aborting..."
&
@
CRLF
&
"---"
)
FileClose
(
$
hFileOpen
)
Sleep
(
100
)
$
bFoundGenericARM
=
True
EndIf
Else
FileSetPos
(
$
hFileOpen
,
0
,
0
)
Local
$
sFileRead
=
FileRead
(
$
hFileOpen
)
Local
$
GeneQuestionMark
,
$
AnyNumOfBytes
,
$
OutStringForRegExp
For
$
i
=
256
To
1
Step
-
2
; limiting
to
256
-
?
-
$
GeneQuestionMark
=
_StringRepeat
(
"??"
,
$
i
/
2
)
; Repeat the
string
-
?
?
-
$
i
/
2
times
.
$
AnyNumOfBytes
=
"(.{"
&
$
i
&
"})"
$
OutStringForRegExp
=
StringReplace
(
$
PatternToSearch
,
$
GeneQuestionMark
,
$
AnyNumOfBytes
)
$
PatternToSearch
=
$
OutStringForRegExp
Next
Local
$
sSearchPattern
=
$
OutStringForRegExp     ;
string
Local
$
aReplacePattern
=
$
PatternToReplace     ;
string
Local
$
sWildcardSearchPattern
=
""
,
$
sWildcardReplacePattern
=
""
,
$
sFinalReplacePattern
=
""
Local
$
aInHexTempArray[
0
]
        Local
$
sSearchCharacter
=
""
,
$
sReplaceCharacter
=
""
$
aInHexTempArray
=
$
aNullArray
$
aInHexTempArray
=
StringRegExp
(
$
sFileRead
,
$
sSearchPattern
,
$
STR_REGEXPARRAYGLOBALFULLMATCH
,
1
)
For
$
i
=
0
To
UBound
(
$
aInHexTempArray
)
-
1
$
aInHexArray
=
$
aNullArray
$
sSearchCharacter
=
""
$
sReplaceCharacter
=
""
$
sWildcardSearchPattern
=
""
$
sWildcardReplacePattern
=
""
$
sFinalReplacePattern
=
""
$
aInHexArray
=
$
aInHexTempArray[
$
i]
            ;_ArrayDisplay
(
$
aInHexArray
)
If
@
error
=
0
Then
$
sWildcardSearchPattern
=
$
aInHexArray[
0
]   ; full founded Search Pattern index
0
$
sWildcardReplacePattern
=
$
aReplacePattern

                ;MsgBox
(
-
1
,
""
,
$
sWildcardSearchPattern
&
@
CRLF
&
$
sWildcardReplacePattern
)
; full search
and
full patch
with
?
?
symbols
If
StringInStr
(
$
sWildcardReplacePattern
,
"?"
)
Then
;MsgBox
(
$
MB_SYSTEMMODAL
,
"Found ? symbol"
,
"Constructing new Replace string"
)
For
$
j
=
1
To
StringLen
(
$
sWildcardReplacePattern
)
+
1
; Retrieve a characters from the
$
jth position
in
each
string
.
$
sSearchCharacter
=
StringMid
(
$
sWildcardSearchPattern
,
$
j
,
1
)
$
sReplaceCharacter
=
StringMid
(
$
sWildcardReplacePattern
,
$
j
,
1
)
If
$
sReplaceCharacter

"?"
Then
$
sFinalReplacePattern
&
=
$
sReplaceCharacter
Else
$
sFinalReplacePattern
&
=
$
sSearchCharacter
EndIf
Next
Else
$
sFinalReplacePattern
=
$
sWildcardReplacePattern
EndIf
_ArrayAdd
(
$
aOutHexGlobalArray
,
$
sWildcardSearchPattern
)
_ArrayAdd
(
$
aOutHexGlobalArray
,
$
sFinalReplacePattern
)
ConsoleWrite
(
$
PatternName
&
"---"
&
@
TAB
&
$
sWildcardSearchPattern
&
"    "
&
@
CRLF
)
ConsoleWrite
(
$
PatternName
&
"R"
&
"--"
&
@
TAB
&
$
sFinalReplacePattern
&
"    "
&
@
CRLF
)
MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
$
PatternName
&
@
CRLF
&
"---"
&
@
CRLF
&
$
sWildcardSearchPattern
&
@
CRLF
&
$
sFinalReplacePattern
)
LogWrite
(
1
,
"Replacing with: "
&
$
sFinalReplacePattern
)
Else
ConsoleWrite
(
$
PatternName
&
"---"
&
@
TAB
&
"No"
&
"    "
&
@
CRLF
)
MemoWrite
(
@
CRLF
&
$
FileToParse
&
@
CRLF
&
"---"
&
@
CRLF
&
$
PatternName
&
"---"
&
"No"
)
EndIf
$
MyRegExpGlobalPatternSearchCount
+
=
1
Next
FileClose
(
$
hFileOpen
)
$
sFileRead
=
""
ProgressWrite
(
Round
(
$
MyRegExpGlobalPatternSearchCount
/
$
Count
*
100
)
)
Sleep
(
100
)
EndIf
;
=
=
>
If
$
sz_type
=
"0x4C01"
EndFunc   ;
=
=
>
MyRegExpGlobalPatternSearch
Первое, что проверяет функция - патчим ли мы Adobe Acrobat с архитектурой x32. Если да, то функция завершается, так как скрипт не может обработать такой случай. Далее проверяется, используем ли мы файл с архитектурой ARM. Если да, то снова завершение функции. GenP рассчитан в основном на x64.

Далее функция читает файл, путь до которого был ей передан, и находит точные байты в нём (без знаков ?), добавляя их в массив
Код:
$aOutHexGlobalArray
:

Visual Basic:


Код:
_ArrayAdd
(
$
aOutHexGlobalArray
,
$
sWildcardSearchPattern
)
_ArrayAdd
(
$
aOutHexGlobalArray
,
$
sFinalReplacePattern
)
В первый элемент массива будут добавлены точные байты, которые были найдены в файле.
Во второй элемент массива будут добавлены точные байты, на которые произойдёт замена.

Функция заменяет знаки
Код:
??
на байты из самого файла, чтобы получились "точные байты". Забегая вперёд, потом благодаря массиву
Код:
$aOutHexGlobalArray
функция
Код:
MyGlobalPatternPatch
просто пропатчит точные искомые байты на точные заменяемые. Но перед этим создаст резервную копию.

Рассмотрим схематично замену байтов в файле. Значения
Код:
CreativeCloud1
для файла
Код:
AppsPanelBL.dll
:

INI:


Код:
CreativeCloud1
="8378????0F84????????8378????0F84????????8378????0F84????????33C0"|"C640????0F84????????C640????0F84????????C640????0F84????????33C0"
Более понятная запись:

INI:


Код:
"8378????0F84????????8378????0F84????????8378????0F84????????33C0" ; байты, которые ищем
"C640????0F84????????C640????0F84????????C640????0F84????????33C0" ; байты, на которые заменяем
2 знака вопроса выступают в роли одного любого байта, который не будет изменён. Или по-другому это часть регулярного выражения. Отсюда и Reg в названии функции.

INI:


Код:
"83 78 ?? ?? 0F 84 ?? ?? ?? ?? 83 78 ?? ?? 0F 84 ..." ; байты, которые ищем
"C6 40 ?? ?? 0F 84 ?? ?? ?? ?? C6 40 ?? ?? 0F 84..." ; байты, на которые заменяем
Вот так записано более понятно. Функция
Код:
MyRegExpGlobalPatternSearch
сделает из вопросов точные байты:

INI:


Код:
"83 78 FF FF 0F 84 FF FF FF FF 83 78 FF FF 0F 84 ..." ; байты, которые ищем
"C6 40 FF FF 0F 84 FF FF FF FF C6 40 FF FF 0F 84..." ; байты, на которые заменяем
Для примера представим, что в самом файле на месте вопросов были байты 0xFF.
Байт 0x83 заменится на 0xC6,
Байт 0x78 заменится на 0x40,
Байт 0xFF заменится на 0xFF,
Байт 0xFF заменится на 0xFF,
Байт 0x0F заменится на 0x0F,
Байт 0x84 заменится на 0x84,
и так далее

4.2.5.2. Вернёмся к обработчику кнопки "Patch CC"
Теперь снова вернёмся к обработчику нажатия кнопки "Patch CC".

Visual Basic:


Код:
If
FileExists
(
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
)
Then
$
appsPanelFile
=
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
ElseIf
FileExists
(
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
)
Then
$
appsPanelFile
=
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
Else
$
appsPanelFile
=
FileOpenDialog
(
"Select a File"
,
@
ScriptDir
,
"AppsPanelBL.dll (AppsPanelBL.dll)"
)
EndIf
ProgressWrite
(
0
)
If
FileExists
(
$
appsPanelFile
)
Then
MyGlobalPatternSearch
(
$
appsPanelFile
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"File Path:"
&
@
CRLF
&
""
&
@
CRLF
&
$
appsPanelFile
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
100
)
MyGlobalPatternPatch
(
$
appsPanelFile
,
$
aOutHexGlobalArray
)
Sleep
(
500
)
EndIf
После того как вызов
Код:
MyGlobalPatternSearch
пропатчит файл, запустится функция
Код:
MyGlobalPatternPatch
.

Visual Basic:


Код:
Func MyGlobalPatternPatch
(
$
MyFileToPatch
,
$
MyArrayToPatch
)
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
$
MyFileToPatch
)
;_ArrayDisplay
(
$
MyArrayToPatch
)
ProgressWrite
(
0
)
;MemoWrite
(
"Current path"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyFileToPatch
&
@
CRLF
&
"---"
&
@
CRLF
&
"medication :)"
)
Local
$
iRows
=
UBound
(
$
MyArrayToPatch
)
; Total number
of
rows

    MsgBox
(
0
,
"q"
,
$
MyArrayToPatch
)
MsgBox
(
0
,
"q"
,
$
iRows
)
If
$
iRows
>
0
Then
MemoWrite
(
@
CRLF
&
"Path"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyFileToPatch
&
@
CRLF
&
"---"
&
@
CRLF
&
"medication :)"
)
Local
$
hFileOpen
=
FileOpen
(
$
MyFileToPatch
,
$
FO_READ
+
$
FO_BINARY
)
Local
$
sFileRead
=
FileRead
(
$
hFileOpen
)
Local
$
sStringOut
For
$
i
=
0
To
$
iRows
-
1
Step
2
MsgBox
(
0
,
"q"
,
$
MyArrayToPatch[
$
i]
)
MsgBox
(
0
,
"q"
,
$
MyArrayToPatch[
$
i
+
1
]
)
$
sStringOut
=
StringReplace
(
$
sFileRead
,
$
MyArrayToPatch[
$
i]
,
$
MyArrayToPatch[
$
i
+
1
]
,
0
,
1
)
$
sFileRead
=
$
sStringOut
$
sStringOut
=
$
sFileRead
            ProgressWrite
(
Round
(
$
i
/
$
iRows
*
100
)
)
Next
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"binary: "
&
Binary
(
$
sStringOut
)
)
FileClose
(
$
hFileOpen
)
FileMove
(
$
MyFileToPatch
,
$
MyFileToPatch
&
".bak"
,
$
FC_OVERWRITE
)
Local
$
hFileOpen1
=
FileOpen
(
$
MyFileToPatch
,
$
FO_OVERWRITE
+
$
FO_BINARY
)
FileWrite
(
$
hFileOpen1
,
Binary
(
$
sStringOut
)
)
FileClose
(
$
hFileOpen1
)
ProgressWrite
(
0
)
Sleep
(
100
)
;MemoWrite1
(
@
CRLF
&
"---"
&
@
CRLF
&
"Waitng for your command :)"
&
@
CRLF
&
"---"
)
LogWrite
(
1
,
"File patched."
&
@
CRLF
)
Else
;Empty array
-
>
no search
-
replace patterns
        ;File
is
already patched
or
no patterns were found
.
MemoWrite
(
@
CRLF
&
"No patterns were found"
&
@
CRLF
&
"---"
&
@
CRLF
&
"or"
&
@
CRLF
&
"---"
&
@
CRLF
&
"file is already patched."
)
Sleep
(
100
)
LogWrite
(
1
,
"No patterns were found or file already patched."
&
@
CRLF
)
EndIf
;Sleep
(
100
)
;MemoWrite2
(
"***"
)
EndFunc   ;
=
=
>
MyGlobalPatternPatch
Данная функция открывает файл и благодаря глобальному массиву
Код:
$aOutHexGlobalArray
ищет точные байты в файле и заменяет их на точные нужные. Передачу этого массива, как аргумента, можно найти в обработчике. Перед записью изменения создаётся бекап файла с расширением
Код:
.bak
, чтобы в случае чего его можно было бы восстановить. Таким образом,
Код:
MyGlobalPatternSearch
и все функции, что вызываются внутри неё, ищут точные байты в файле для замены и на основе них создают точные байты, на которые произойдёт замена. Саму замену байтов выполняет
Код:
MyGlobalPatternPatch
. Связаны 2 эти функции через
Код:
$aOutHexGlobalArray
.

Таким образом, во всём обработчике "Patch CC" прослеживается общий шаблон:

Код:


Код:
1. Проверка, существует ли обрабатываемый файл в Program Files (x86) или в Program Files. Иначе выбираем сами.
2. Функцией MyGlobalPatternSearch ищутся точные исходные и заменяемые байты и записываются в глобальный массив $aOutHexGlobalArray.
3. Функция MyGlobalPatternPatch использует $aOutHexGlobalArray и заменяет точные искомые байты на точные заменяемые. Также создаёт бекап исходного файла.
В коде это:

Visual Basic:


Код:
If
FileExists
(
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
)
Then
$
appsPanelFile
=
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
ElseIf
FileExists
(
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
)
Then
$
appsPanelFile
=
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll"
Else
$
appsPanelFile
=
FileOpenDialog
(
"Select a File"
,
@
ScriptDir
,
"AppsPanelBL.dll (AppsPanelBL.dll)"
)
EndIf
ProgressWrite
(
0
)
If
FileExists
(
$
appsPanelFile
)
Then
MyGlobalPatternSearch
(
$
appsPanelFile
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"File Path:"
&
@
CRLF
&
""
&
@
CRLF
&
$
appsPanelFile
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
100
)
MyGlobalPatternPatch
(
$
appsPanelFile
,
$
aOutHexGlobalArray
)
Sleep
(
500
)
EndIf
ProgressWrite
(
0
)
If
$
bFoundCCARM
=
False
Then
If
FileExists
(
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\ContainerBL.dll"
)
Then
$
containerBLFile
=
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\ContainerBL.dll"
ElseIf
FileExists
(
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\ADS\ContainerBL.dll"
)
Then
$
containerBLFile
=
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\ADS\ContainerBL.dll"
Else
$
containerBLFile
=
FileOpenDialog
(
"Select a File"
,
@
ScriptDir
,
"ContainerBL.dll (ContainerBL.dll)"
)
EndIf
ProgressWrite
(
0
)
If
FileExists
(
$
containerBLFile
)
Then
MyGlobalPatternSearch
(
$
containerBLFile
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"File Path:"
&
@
CRLF
&
""
&
@
CRLF
&
$
containerBLFile
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
100
)
MyGlobalPatternPatch
(
$
containerBLFile
,
$
aOutHexGlobalArray
)
Sleep
(
500
)
EndIf
ProgressWrite
(
0
)
If
FileExists
(
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\Adobe Desktop Service.exe"
)
Then
$
adobeDesktopServiceFile
=
"C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\Adobe Desktop Service.exe"
ElseIf
FileExists
(
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\ADS\Adobe Desktop Service.exe"
)
Then
$
adobeDesktopServiceFile
=
"C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\ADS\Adobe Desktop Service.exe"
Else
$
adobeDesktopServiceFile
=
FileOpenDialog
(
"Select a File"
,
@
ScriptDir
,
"Adobe Desktop Service.exe (Adobe Desktop Service.exe)"
)
EndIf
If
FileExists
(
$
adobeDesktopServiceFile
)
Then
MyGlobalPatternSearch
(
$
adobeDesktopServiceFile
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"File Path:"
&
@
CRLF
&
""
&
@
CRLF
&
$
adobeDesktopServiceFile
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Sleep
(
100
)
MyGlobalPatternPatch
(
$
adobeDesktopServiceFile
,
$
aOutHexGlobalArray
)
Sleep
(
500
)
EndIf
ProgressWrite
(
0
)
MemoWrite
(
@
CRLF
&
"All files patched."
&
@
CRLF
&
""
&
@
CRLF
&
""
)
Кроме этого проверяется, что мы не используем ARM-версии файлов. Ну и всё пишется в лог
Теперь посмотрим, какие именно изменения вносятся. Как мы узнали, меняются эти файлы:

Код:


Код:
C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll
C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\ContainerBL.dll
C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\Adobe Desktop Service.exe
Вместо
Код:
Program Files
может быть
Код:
Program Files (x86)
. У меня как раз этот случай. Патчинг этих файлов позволяет скачивать платные программы Adobe из Creative Cloud.

До патча:

После патча:

Экспериментально у себя я выяснил, что для достижения такого результата обязательно нужно пропатчить
Код:
ContainerBL.dll
и
Код:
AppsPanelBL.dll
. Вероятно, патчинг
Код:
Adobe Desktop Service.exe
нужен для подстраховки.

4.2.5.3. Сравниваем пропатченные байты с оригинальными и ищем их
Мы сравним файл до патча и после патча. Я буду делать это через IDA. Но сначала нужно найти точные байты.

Это можно сделать этой утилитой на C++:

C++:


Код:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
struct
Pattern
{
std
::
string name
;
std
::
vector
>
patterns
;
}
;
// Функция для парсинга паттернов
std
::
vector

parsePatterns
(
)
{
std
::
vector

patterns
=
{
{
"CreativeCloud1"
,
{
{
"8378????0F84????????8378????0F84????????8378????0F84????????33C0"
,
"C640????0F84????????C640????0F84????????C640????0F84????????33C0"
}
}
}
,
{
"CreativeCloud2"
,
{
{
"E8????????85C00F85????????83EC??8BCC89"
,
"E8????????FEC00F85????????83EC??8BCC89"
}
}
}
,
{
"CreativeCloud3"
,
{
{
"??????0F85890300"
,
"??????E98A030000"
}
}
}
,
{
"Acrobat1"
,
{
{
"488BCFE8????????85C00F84????????488D??????????488BCFE8????????85C075??8D"
,
"488BCFE8????????FFC00F84????????488D??????????488BCFE8????????31C075??8D"
}
}
}
,
{
"Acrobat2"
,
{
{
"6685C0740FE8????????6685C07405BB01000000"
,
"6685C07400E8????????6685C07400BB01000000"
}
}
}
,
{
"Acrobat3"
,
{
{
"6685C0741A6685??0F85??020000"
,
"6685C090906685??0F85??020000"
}
}
}
,
{
"Acrobat4"
,
{
{
"00E8????E7FF66893D??????03381D??????03751F4533C0488D15??????02488D0D??????02E8????E7FF6685C00F84BAFEFFFF8BDFE9B3FEFFFFB801000000"
,
"00E8????E7FF66893D??????03381D??????03EB1F4533C0488D15??????02488D0D??????02E8????E7FF6685C00F84BAFEFFFF8BDFE9B3FEFFFFB801000000"
}
}
}
,
{
"Acrobat5"
,
{
{
"753FE8????????6685C0740933C9E8????????EB25488D05????????48894424204C8D0D????????33D2448D423C488D0D??????00E8????????66893D????????381D????????75"
,
"EB3FE8????????6685C0740933C9E8????????EB25488D05????????48894424204C8D0D????????33D2448D423C488D0D??????00E8????????66893D????????381D????????EB"
}
}
}
,
{
"Acrodist1"
,
{
{
"85C00F84????????E8????????85C00F85????????E8"
,
"85C00F84????????E8????????FFC00F85????????E8"
}
}
}
,
{
"Acrodist2"
,
{
{
"00908BC8E8??????00CCCCCCCCCCCC48895C24104889"
,
"00908BC8E8??????00CCCCCCCCCCCC31C0C324104889"
}
}
}
,
{
"Acrodist3"
,
{
{
"5E5B5DC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4055535657415441554156415748"
,
"5E5B5DC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC31C0C35657415441554156415748"
}
}
}
,
{
"Acrodist4"
,
{
{
"00005072696E745F447269766572"
,
"0000B001906E745F447269766572"
}
}
}
,
{
"Acrodist5"
,
{
{
"51??????????????????????????????48895C????????????????????????55"
,
"51??????????????????????????????33C0C3????????????????????????55"
}
}
}
,
{
"AcroNew1"
,
{
{
"C3488BC1C3CC48895C24084889??2410"
,
"C3488BC1C3CCC3895C24084889??2410"
}
}
}
,
{
"AcroRegistry1"
,
{
{
"0FB6C3488B5C2458????????????????895C"
,
"B801000000909090????????????????895C"
}
}
}
,
{
"AcroTray1"
,
{
{
"E8????????84C074??E8????????84C075??33DB"
,
"E8????????FEC074??E8????????FEC075??33DB"
}
}
}
,
{
"AcroTray2"
,
{
{
"0F8459030000803D??????00000F8545030000"
,
"E95A03000090803D??????0000E94603000090"
}
}
}
,
{
"AcroTray3"
,
{
{
"0F85A302000048397C24400F84"
,
"E9A40200009048397C24400F85"
}
}
}
,
{
"AcroTray4"
,
{
{
"244884DB0F84C70100"
,
"244884DB0F85C70100"
}
}
}
,
{
"AcroTray5"
,
{
{
"????????E86791D9FFE862B2D8FF????"
,
"????????9090909090B801000000????"
}
}
}
,
{
"DesktopService1"
,
{
{
"68008B40148985CCFEFFFF85C0"
,
"68008B40148985CCFEFFFF33C0"
}
}
}
,
{
"Banner1"
,
{
{
"72656C6174696F6E7368697050726F66696C65"
,
"78656C6174696F6E7368697050726F66696C65"
}
}
}
,
{
"Banner2"
,
{
{
"000000000000000072656C6174696F6E"
,
"000000000000000078656C6174696F6E"
}
}
}
,
{
"BridgeCamRaw1"
,
{
{
"84C074??8B??83??0174??83??0174??83??01"
,
"84C074??8B??83??01EB??83??0174??83??01"
}
}
}
,
{
"BridgeCamRaw2"
,
{
{
"4084??0F85????????4084??0F84"
,
"4084??0F85????????40FEC60F85"
}
}
}
,
{
"CmpEax61"
,
{
{
"8B??85C074??83F80674????83????007D"
,
"C7??0300000083F8067400??83????00EB"
}
}
}
,
{
"CmpEax62"
,
{
{
"8B??85C074??83F80674????83??????007D"
,
"C7??0300000083F8067400??83??????00EB"
}
}
}
,
{
"CmpEax63"
,
{
{
"8B????85C074??83F80674????83????007D"
,
"C7????0300000083F8067400??83????00EB"
}
}
}
,
{
"CmpEax64"
,
{
{
"8B????85C074??83F80674????83??????007D"
,
"C7????0300000083F8067400??83??????00EB"
}
}
}
,
{
"HevcMpegEnabler1"
,
{
{
"FF50100FB6"
,
"FFC0900FB6"
}
}
}
,
{
"HevcMpegEnabler2"
,
{
{
"FF5010??0FB6"
,
"FFC090??0FB6"
}
}
}
,
{
"HevcMpegEnabler3"
,
{
{
"FF50??0FB6"
,
"FFC0900FB6"
}
}
}
,
{
"HevcMpegEnabler4"
,
{
{
"FF50????0FB6"
,
"FFC090??0FB6"
}
}
}
,
{
"Profile1"
,
{
{
"00007504488D4850"
,
"00007500488D4850"
}
}
}
,
{
"Profile2"
,
{
{
"00007504488D5050"
,
"00007500488D5050"
}
}
}
,
{
"ProfileExpired1"
,
{
{
"85C075??????????75??B892010000E9"
,
"31C075004883FF0F7500B800000000E9"
}
}
}
,
{
"ProfileExpired2"
,
{
{
"85C075??B892010000E9"
,
"85C07500B800000000E9"
}
}
}
,
{
"ProfileExpired3"
,
{
{
"85C075????????75??B892010000E9"
,
"31C075????????7500B800000000E9"
}
}
}
,
{
"ProfileExpired4"
,
{
{
"488D4D??483B??0F??????000048????4889??4885C9"
,
"488D4D??483B??C700000000004831C94889??4885C9"
}
}
}
,
{
"ProfileExpired5"
,
{
{
"488B0B4889034885C974??BA04000000E8????????B00148"
,
"C7000000000048890348C7C1000000000F1F440000B00148"
}
}
}
,
{
"ProfileExpired6"
,
{
{
"4885C974??BA04000000E8????????4C8D5C"
,
"C700000000004889034831C90F1F004C8D5C"
}
}
}
,
{
"TeamProjectEnabler1"
,
{
{
"488379????740A488379????7403B001C332C0C3"
,
"488379????740A488379????7403B001C3B001C3"
}
}
}
,
{
"ValidateLicense1"
,
{
{
"83F80175??BA94010000"
,
"83F80175??BA00000000"
}
}
}
,
{
"ValidateLicense2"
,
{
{
"83F8040F95C281C293010000"
,
"83F8040F95C2BA0000000090"
}
}
}
,
{
"ValidateLicense3"
,
{
{
"83F8040F95C181C193010000"
,
"83F8040F95C1B90000000090"
}
}
}
,
{
"InstantShutdown1"
,
{
{
"00??????????E875000000????????C0"
,
"00??????????9090909090????????C0"
}
}
}
,
{
"PluginVerification1"
,
{
{
"5F5E????????????????????????????48895C2410??8974"
,
"5F5E????????????????????????????C390909090??8974"
}
}
}
,
{
"LoginVerification1"
,
{
{
"4C8B??????????????????????????????????????742C48"
,
"4C8B??????????????????????????????????????EB2C48"
}
}
}
,
{
"JS1"
,
{
{
"52656C6174696F6E7368697050726F66696C653A612E??2E6F7074696F6E616C"
,
"58656C6174696F6E7368697050726F66696C653A612E??2E6F7074696F6E616C"
}
}
}
,
{
"JS2"
,
{
{
"52656C6174696F6E7368697050726F66696C652E66696E6428653D3E652E75736564466F724C656761637950726F66696C65293B72657475726E20692E6D61696E53746F7265"
,
"58656C6174696F6E7368697050726F66696C652E66696E6428653D3E652E75736564466F724C656761637950726F66696C65293B72657475726E20692E6D61696E53746F7265"
}
}
}
,
{
"JS3"
,
{
{
"52656C6174696F6E7368697050726F66696C652E66696E6428653D3E652E75736564466F724C656761637950726F66696C65297D7D2929"
,
"58656C6174696F6E7368697050726F66696C652E66696E6428653D3E652E75736564466F724C656761637950726F66696C65297D7D2929"
}
}
}
,
{
"JS4"
,
{
{
"52656C6174696F6E7368697050726F66696C65297C7C766F696420303D3D3D69"
,
"58656C6174696F6E7368697050726F66696C65297C7C766F696420303D3D3D69"
}
}
}
,
{
"Version"
,
{
{
"6363782E7374617274222C0A20202276657273696F6E223A2022372E"
,
"6363782E7374617274222C0A20202276657273696F6E223A2022392E"
}
}
}
}
;
return
patterns
;
}
// Функция для преобразования паттерна в байтовый массив и маску
void
parseHexPattern
(
const
std
::
string
&
pattern
,
std
::
vector

&
bytes
,
std
::
vector

&
mask
)
{
for
(
size_t i
=
0
;
i

(
std
::
stoi
(
byteString
,
nullptr
,
16
)
)
;
bytes
.
push_back
(
byte
)
;
mask
.
push_back
(
0xFF
)
;
}
catch
(
const
std
::
invalid_argument
&
e
)
{
std
::
cerr

&
data
,
const
std
::
vector

&
pattern
,
const
std
::
vector

&
mask
,
size_t pos
)
{
for
(
size_t i
=
0
;
i

&
data
,
const
std
::
vector

&
pattern
,
const
std
::
vector

&
mask
,
const
std
::
string
&
patternType
,
bool
&
headerPrinted
,
const
std
::
string
&
patternName
)
{
bool
found
=
false
;
for
(
size_t i
=
0
;
i
"

(
data
[
i
+
j
]
)
"

data
(
(
std
::
istreambuf_iterator

(
file
)
)
,
std
::
istreambuf_iterator

(
)
)
;
auto
patterns
=
parsePatterns
(
)
;
for
(
const
auto
&
pattern
:
patterns
)
{
bool
anyFound
=
false
;
bool
headerPrinted
=
false
;
for
(
const
auto
&
[
searchPattern
,
replacePattern
]
:
pattern
.
patterns
)
{
std
::
vector

searchBytes
,
searchMask
;
parseHexPattern
(
searchPattern
,
searchBytes
,
searchMask
)
;
std
::
vector

replaceBytes
,
replaceMask
;
parseHexPattern
(
replacePattern
,
replaceBytes
,
replaceMask
)
;
if
(
searchAndPrintPattern
(
data
,
searchBytes
,
searchMask
,
"Искомый   "
,
headerPrinted
,
pattern
.
name
)
)
{
anyFound
=
true
;
}
if
(
searchAndPrintPattern
(
data
,
replaceBytes
,
replaceMask
,
"Заменяемый"
,
headerPrinted
,
pattern
.
name
)
)
{
anyFound
=
true
;
}
}
if
(
anyFound
)
{
std
::
cout
search.exe AppsPanelBL.dll

Искомый   : 83 78 2c 00 0f 84 95 01 00 00 83 78 44 00 0f 84 8b 01 00 00 83 78 5c 00 0f 84 81 01 00 00 33 c0

Искомый   : e8 76 47 10 00 85 c0 0f 85 9d 00 00 00 83 ec 18 8b cc 89
Искомый   : e8 01 a9 0e 00 85 c0 0f 85 8f 02 00 00 83 ec 18 8b cc 89
Искомый   : e8 09 b7 02 00 85 c0 0f 85 1f 02 00 00 83 ec 18 8b cc 89
Искомый   : e8 83 fd ff ff 85 c0 0f 85 bd 04 00 00 83 ec 18 8b cc 89
Искомый   : e8 f2 f7 ff ff 85 c0 0f 85 74 01 00 00 83 ec 18 8b cc 89
Искомый   : e8 ef f5 ff ff 85 c0 0f 85 76 02 00 00 83 ec 18 8b cc 89
Искомый   : e8 cf f2 ff ff 85 c0 0f 85 76 02 00 00 83 ec 18 8b cc 89

Искомый   : ff 84 c0 0f 85 89 03 00
Искомый   : ff 84 c0 0f 85 89 03 00
Искомый   : 74 24 38 0f 85 89 03 00
Заменяемый: ff 32 c0 e9 8a 03 00 00
Заменяемый: 0a 01 00 e9 8a 03 00 00
Только иногда она находит лишние байты. Но нам нужно искать только те, что патчатся. Для
Код:
AppsPanelBL.dll
это будет
Код:
CreativeCloud1
и
Код:
CreativeCloud2
. На
Код:
CreativeCloud3
просто не смотрим.

INI:


Код:
AppsPanelBL.dll
="CreativeCloud1","CreativeCloud2"
Далее файл нужно открыть в IDA, нажать ALT+B и ввести первые 5-10 найденных байт:

Нажимаем 2 раза на запись.

Попали сюда. Теперь отобразим опкоды инструкций.

Таким образом можно сравнивать файлы до патча и после. Так мы посмотрим, как поменяются инструкции.
Так как GenP делает бекапы (.bak), то можно сравнивать бекапы с пропатченными файлами.

Код:
C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\Adobe Desktop Service.exe
Код:
DesktopService1
Слева я буду располагать файл до патча, а справа после. Если хотите перейти в режим листинга IDA (как на скрине), нажмите пробел. И снова в настройках включите отображение опкодов.

Код:
C:\Program Files\Common Files\Adobe\Adobe Desktop Common\AppsPanel\AppsPanelBL.dll
Код:
CreativeCloud1
Код:
CreativeCloud2
Код:
C:\Program Files\Common Files\Adobe\Adobe Desktop Common\ADS\ContainerBL.dll
Код:
CreativeCloud3
Проанализировав различия между этими файлами, видим, что ничего вредоносного в них он не добавляет. Просто меняет ход выполнения программы. Где-то через замену инструкций условных переходов, где-то через замену инструкций перед ними. Можно даже сделать всё это вручную и получить тот же результат.

Далее нам нужно будет рассмотреть, как работает обработчик патчинга файлов самих программ Adobe. Но перед этим рассмотрим обработчик кнопки восстановления оригинального файла - "Restore".

4.2.6. Обработчик кнопки "Restore"
Она появляется, если после поиска файлов для патча (кнопка "Search") мы выберем какой-либо или какие-либо из них, и есть файл
Код:
.bak
для выбранного.

Начало его обработчика:

Visual Basic:


Код:
Case
$
idMsg
=
$
idBtnRestore
            GUICtrlSetData
(
$
idLog
,
"Activity Log"
&
@
CRLF
)
ToggleLog
(
0
)
GUICtrlSetState
(
$
idListview
,
128
)
GUICtrlSetState
(
$
idBtnDeselectAll
,
128
)
GUICtrlSetState
(
$
idButtonSearch
,
128
)
GUICtrlSetState
(
$
idBtnCure
,
128
)
Основная функция там - это
Код:
RestoreFile
:

Visual Basic:


Код:
If
_GUICtrlListView_GetItemChecked
(
$
idListview
,
$
i
)
=
True
Then
_GUICtrlListView_SetItemSelected
(
$
idListview
,
$
i
)
$
ItemFromList
=
_GUICtrlListView_GetItemText
(
$
idListview
,
$
i
,
1
)
$
iCheckedItems
=
_GUICtrlListView_GetSelectedCount
(
$
idListview
)
$
iProgress
=
100
/
$
iCheckedItems
                    ProgressWrite
(
0
)
RestoreFile
(
$
ItemFromList
)
ProgressWrite
(
$
iProgress
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"Path"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
ItemFromList
&
@
CRLF
&
"---"
&
@
CRLF
&
"restoring :)"
)
Sleep
(
100
)
; Scroll control
10
pixels
-
1
line
                    _GUICtrlListView_Scroll
(
$
idListview
,
0
,
10
)
_GUICtrlListView_EnsureVisible
(
$
idListview
,
$
i
,
0
)
Sleep
(
100
)
EndIf
Этой функции передаётся путь до файла. Её код:

Visual Basic:


Код:
Func RestoreFile
(
$
MyFileToDelete
)
If
FileExists
(
$
MyFileToDelete
&
".bak"
)
Then
FileDelete
(
$
MyFileToDelete
)
FileMove
(
$
MyFileToDelete
&
".bak"
,
$
MyFileToDelete
,
$
FC_OVERWRITE
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"File restored"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyFileToDelete
)
LogWrite
(
1
,
$
MyFileToDelete
)
LogWrite
(
1
,
"File restored."
)
Else
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"No backup file found"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
MyFileToDelete
)
LogWrite
(
1
,
$
MyFileToDelete
)
LogWrite
(
1
,
"No backup file found."
)
EndIf
EndFunc   ;
=
=
>
RestoreFile
Тут всё просто
Удаляем пропатченный файл и переименовываем
Код:
.bak-файл
в файл без постфикса
Код:
.bak
. Конечно же, если бекап этого файла существует.

4.2.7. Обработчик кнопки "Patch"
Ну а теперь переходим к обработчику кнопки "Patch", что доступна после "Search".

Visual Basic:


Код:
Case
$
idMsg
=
$
idBtnCure
            ToggleLog
(
0
)
GUICtrlSetState
(
$
idListview
,
128
)
GUICtrlSetState
(
$
idBtnDeselectAll
,
128
)
GUICtrlSetState
(
$
idButtonSearch
,
128
)
GUICtrlSetState
(
$
idBtnCure
,
128
)
GUICtrlSetState
(
$
idBtnBlockPopUp
,
128
)
GUICtrlSetState
(
$
idBtnRestore
,
128
)
GUICtrlSetState
(
$
idButtonCustomFolder
,
128
)
GUICtrlSetState
(
$
idBtnPatchCC
,
128
)
_Expand_All_Click
(
)
_GUICtrlListView_EnsureVisible
(
$
idListview
,
0
,
0
)
.
.
.
Это начало кода функции.

Visual Basic:


Код:
For
$
i
=
0
To
_GUICtrlListView_GetItemCount
(
$
idListview
)
-
1
If
_GUICtrlListView_GetItemChecked
(
$
idListview
,
$
i
)
=
True
Then
_GUICtrlListView_SetItemSelected
(
$
idListview
,
$
i
)
$
ItemFromList
=
_GUICtrlListView_GetItemText
(
$
idListview
,
$
i
,
1
)
MyGlobalPatternSearch
(
$
ItemFromList
)
ProgressWrite
(
0
)
Sleep
(
100
)
MemoWrite
(
@
CRLF
&
"Path"
&
@
CRLF
&
"---"
&
@
CRLF
&
$
ItemFromList
&
@
CRLF
&
"---"
&
@
CRLF
&
"medication :)"
)
LogWrite
(
1
,
$
ItemFromList
)
Sleep
(
100
)
MyGlobalPatternPatch
(
$
ItemFromList
,
$
aOutHexGlobalArray
)
; Scroll control
10
pixels
-
1
line
                    _GUICtrlListView_Scroll
(
$
idListview
,
0
,
10
)
_GUICtrlListView_EnsureVisible
(
$
idListview
,
$
i
,
0
)
Sleep
(
100
)
EndIf
При выборе какого-либо элемента и при нажатии кнопки "Patch" в функцию
Код:
MyGlobalPatternSearch
передаётся путь до файла. В
Код:
MyGlobalPatternSearch
, как мы помним, решается, что брать из INI-файла для этого искомого файла, затем проверяется сам файл и уже далее ищутся байты в нём.
После поиска нужных байт и занесения их в
Код:
$aOutHexGlobalArray
, вызывается
Код:
MyGlobalPatternPatch
. Тут всё, как в патчинге самого Creative Cloud. Но отличие в том, что при патчинге Creative Cloud искомые файлы были в секции
Код:
[CustomPatterns]
:

INI:


Код:
[CustomPatterns]
...
AppsPanelBL.dll
="CreativeCloud1","CreativeCloud2"
ContainerBL.dll
="CreativeCloud3"
Adobe Desktop Service.exe
="DesktopService1"
...
Но теперь нам нужно пропатчить сами программы, а не Creative Cloud. Вот полный список файлов, что будет искать GenP:

INI:


Код:
[TargetFiles]
1
="acrobat.dll"
2
="acrodistdll.dll"
3
="acrotray.exe"
4
="aero.exe"
5
="afterfxlib.dll"
6
="animate.exe"
7
="animator.exe"
8
="animator (beta).exe"
9
="auui.dll"
10
="adobe bridge.exe"
11
="designer.exe"
12
="dreamweaver.exe"
13
="dvaappsupport.dll"
14
="encoder.exe"
15
="encoder (beta).exe"
16
="euclid-core"
17
="gemini_uwp_bridge.dll"
18
="illustrator.exe"
19
="lightroom.exe"
20
="lightroomcc.exe"
21
="modeler.exe"
22
="modeler beta.exe"
23
="ngl-lib.dll"
24
="painter.exe"
25
="photoshop.exe"
26
="public.dll"
27
="registration.dll"
28
="sampler.exe"
29
="sampler beta.exe"
30
="stager.exe"
31
="sweetpeasupport.dll"
32
="xd.exe"
33
="appframework.rpln"
34
="objectmodel.dll"
35
="4.js"
36
="manifest.json"
А вот список специальных файлов:

INI:


Код:
[CustomPatterns]
Acrobat.dll
="Acrobat3","Acrobat5"
acrodistdll.dll
="Acrodist2","Acrodist3","Acrodist4","Acrodist5","AcroRegistry1","AcroNew1"
acrotray.exe
="AcroTray2","AcroTray3","AcroTray4","AcroTray5","AcroRegistry1","AcroNew1"
AppsPanelBL.dll
="CreativeCloud1","CreativeCloud2"
ContainerBL.dll
="CreativeCloud3"
Adobe Bridge.exe
="ProfileExpired1","ValidateLicense1","ValidateLicense2","ValidateLicense3","CmpEax61","CmpEax62","CmpEax63","CmpEax64","Profile1","Profile2","Banner1","BridgeCamRaw1","BridgeCamRaw2","InstantShutdown1"
dvaappsupport.dll
="TeamProjectEnabler1"
SweetPeaSupport.dll
="HevcMpegEnabler3","HevcMpegEnabler4"
AppFramework.rpln
="LoginVerification1"
ObjectModel.dll
="PluginVerification1"
Adobe Desktop Service.exe
="DesktopService1"
4.js
="JS1","JS2","JS3","JS4"
manifest.json
="Version"
Файлов из
Код:
TargetFiles
явно больше. Как быть с теми, что не в секции со специальными файлами?
В таком случае используется набор патчей из секции
Код:
[DefaultPatterns]
:

INI:


Код:
[DefaultPatterns]
Values
="ProfileExpired1","ProfileExpired3","ProfileExpired4","ProfileExpired5","ProfileExpired6","ValidateLicense1","ValidateLicense2","ValidateLicense3","CmpEax61","CmpEax62","CmpEax63","CmpEax64","Profile1","Profile2","Banner1","Banner2","InstantShutdown1"
Патчи по умолчанию применяются для всех файлов, что не находятся в секции
Код:
[CustomPatterns]
. В функции
Код:
MyGlobalPatternSearch
и
Код:
ExecuteSearchPatterns
как раз можно это увидеть:

Visual Basic:


Код:
Func MyGlobalPatternSearch
(
$
MyFileToParse
)
.
.
.
If
StringInStr
(
$
sSpecialFiles
,
$
sFileName
)
Then
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"Special File: "
&
$
sFileName
)
LogWrite
(
0
,
" - using Custom Patterns"
)
ExecuteSearchPatterns
(
$
sFileName
,
0
,
$
MyFileToParse
)
Else
LogWrite
(
0
,
" - using Default Patterns"
)
ExecuteSearchPatterns
(
$
sFileName
,
1
,
$
MyFileToParse
)
;MsgBox
(
$
MB_SYSTEMMODAL
,
""
,
"File: "
&
$
sFileName
&
@
CRLF
&
"Not in Special Files"
)
EndIf
.
.
.
Visual Basic:


Код:
Func ExecuteSearchPatterns
(
$
FileName
,
$
DefaultPatterns
,
$
MyFileToParse
)
Local
$
aPatterns
,
$
sPattern
,
$
sData
,
$
aArray
,
$
sSearch
,
$
sReplace
,
$
iPatternLength
If
$
DefaultPatterns
=
0
Then
$
aPatterns
=
IniReadArray
(
$
sINIPath
,
"CustomPatterns"
,
$
FileName
,
""
)
Else
$
aPatterns
=
IniReadArray
(
$
sINIPath
,
"DefaultPatterns"
,
"Values"
,
""
)
EndIf
.
.
.
Явно видно, что в случае если
Код:
$DefaultPatterns
равен 1, то читается значение ключа
Код:
Values
из секции
Код:
[DefaultPatterns]
. А если же файл будет из секции
Код:
CustomPatterns
, то и использоваться будут те байты, что указаны в этой секции. Например, как с
Код:
Acrobat.dll
:

INI:


Код:
[CustomPatterns]
Acrobat.dll
="Acrobat3","Acrobat5"
5.0 Изучаем патчи из INI-файла
Теперь рассмотрим патчи из секции
Код:
[Patches]
. Как и с файлами Creative Cloud, слева на скринах будет файл до патча, а справа - после. Сначала рассмотрим оставшиеся значения для ключей из
Код:
[CustomPatterns]
, а затем из
Код:
[DefaultPatterns]
. Важно учесть то, что не все значения для ключей будут найдены и применены. Некоторые останутся ненайденными и байты из них не будут использоваться для патча. Скорее всего, они использовались у некоторых старых версий приложений. Я покажу в IDA только то, что нашлось у меня. Также в файлах могут встречаться байты из других. Дубликаты я буду пропускать.

5.1. Секция CustomPatterns

Код:
C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.dll
Код:
Acrobat3
Код:
Acrobat5
Код:
C:\Program Files\Adobe\Acrobat DC\Acrobat\acrodistdll.dll
Код:
Acrodist4
Код:
AcroRegistry1
Код:
AcroNew1
Код:
C:\Program Files\Adobe\Acrobat DC\Acrobat\acrotray.exe
Новых нет.

Код:
C:\Program Files\Adobe\Adobe Bridge 2024\Adobe Bridge.exe
Код:
Banner1
Код:
BridgeCamRaw2
Код:
CmpEax63
Код:
Profile2
Код:
ProfileExpired1
Код:
ValidateLicense2
Код:
C:\Program Files\Adobe\Adobe After Effects 2024\Support Files\dvaappsupport.dll
Код:
TeamProjectEnabler1
Код:
C:\Program Files\Adobe\Adobe After Effects 2024\Support Files\SweetPeaSupport.dll
Код:
HevcMpegEnabler3
Код:
HevcMpegEnabler4
Код:
C:\Program Files\Adobe\Adobe Photoshop 2024\Required\UXP\com.adobe.ccx.start\js\4.js
Код:
JS1
Код:
JS2
Код:
JS3
Код:
JS4
Код:
C:\Program Files\Adobe\Adobe Photoshop 2024\Required\UXP\com.adobe.ccx.start\manifest.json
Код:
Version
5.2. Секция DefaultPatterns

Код:
C:\Program Files\Adobe\Adobe Photoshop 2024\Photoshop.exe
Код:
Banner2
Код:
Profile1
Код:
ProfileExpired4
Код:
C:\Program Files\Adobe\Adobe Illustrator 2024\Support Files\Contents\Windows\Illustrator.exe
Код:
ProfileExpired6
Код:
C:\Program Files\Adobe\Adobe Substance 3D Designer\Adobe Substance 3D Designer.exe
Код:
ProfileExpired5
Код:
C:\Program Files\Adobe\Adobe Dreamweaver 2021\Dreamweaver.exe
Код:
ValidateLicense3
5.3. Оставшиеся патчи
После анализа всех программ у меня остались нетронутыми такие байты:

INI:


Код:
Acrobat1
="488BCFE8????????85C00F84????????488D??????????488BCFE8????????85C075??8D"|"488BCFE8????????FFC00F84????????488D??????????488BCFE8????????31C075??8D"
Acrobat2
="6685C0740FE8????????6685C07405BB01000000"|"6685C07400E8????????6685C07400BB01000000"
Acrobat4
="00E8????E7FF66893D??????03381D??????03751F4533C0488D15??????02488D0D??????02E8????E7FF6685C00F84BAFEFFFF8BDFE9B3FEFFFFB801000000"|"00E8????E7FF66893D??????03381D??????03EB1F4533C0488D15??????02488D0D??????02E8????E7FF6685C00F84BAFEFFFF8BDFE9B3FEFFFFB801000000"
Acrodist1
="85C00F84????????E8????????85C00F85????????E8"|"85C00F84????????E8????????FFC00F85????????E8"
Acrodist2
="00908BC8E8??????00CCCCCCCCCCCC48895C24104889"|"00908BC8E8??????00CCCCCCCCCCCC31C0C324104889"
Acrodist3
="5E5B5DC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4055535657415441554156415748"|"5E5B5DC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC31C0C35657415441554156415748"
Acrodist5
="51??????????????????????????????48895C????????????????????????55"|"51??????????????????????????????33C0C3????????????????????????55"
AcroTray1
="E8????????84C074??E8????????84C075??33DB"|"E8????????FEC074??E8????????FEC075??33DB"
AcroTray2
="0F8459030000803D??????00000F8545030000"|"E95A03000090803D??????0000E94603000090"
AcroTray3
="0F85A302000048397C24400F84"|"E9A40200009048397C24400F85"
AcroTray4
="244884DB0F84C70100"|"244884DB0F85C70100"
AcroTray5
="????????E86791D9FFE862B2D8FF????"|"????????9090909090B801000000????"
BridgeCamRaw1
="84C074??8B??83??0174??83??0174??83??01"|"84C074??8B??83??01EB??83??0174??83??01"
CmpEax61
="8B??85C074??83F80674????83????007D"|"C7??0300000083F8067400??83????00EB"
CmpEax62
="8B??85C074??83F80674????83??????007D"|"C7??0300000083F8067400??83??????00EB"
CmpEax64
="8B????85C074??83F80674????83??????007D"|"C7????0300000083F8067400??83??????00EB"
HevcMpegEnabler1
="FF50100FB6"|"FFC0900FB6"
HevcMpegEnabler2
="FF5010??0FB6"|"FFC090??0FB6"
ProfileExpired2
="85C075??B892010000E9"|"85C07500B800000000E9"
ProfileExpired3
="85C075????????75??B892010000E9"|"31C075????????7500B800000000E9"
ValidateLicense1
="83F80175??BA94010000"|"83F80175??BA00000000"
InstantShutdown1
="00??????????E875000000????????C0"|"00??????????9090909090????????C0"
PluginVerification1
="5F5E????????????????????????????48895C2410??8974"|"5F5E????????????????????????????C390909090??8974"
LoginVerification1
="4C8B??????????????????????????????????????742C48"|"4C8B??????????????????????????????????????EB2C48"
В этом случае можно поступить по-другому: мы используем онлайн-дизассемблер (Online x86 and x64 Intel Instruction Assembler). Передадим в него искомые и заменяемые байты, чтобы сравнить. Знаки
Код:
??
я заменю
Код:
00
вот так:
https://cyberchef.org/#recipe=Find_/_Replace(%7B'option':'Simple%20string','string':'? ?'%7D,'00',true,false,true,false)From_Hex('Auto')T o_Hex('Space',0)&input=NDg4QkNGRTg/Pz8/Pz8/P0ZGQzAwRjg0Pz8/Pz8/Pz80ODhEPz8/Pz8/Pz8/PzQ4OEJDRkU4Pz8/Pz8/Pz8zMUMwNzU/PzhE
Этот способ даст не на 100% точный вывод дизассемблера, а приблизительный. Но точный нам тут и не нужен. Для проверки того, вредоносен ли патч, хватит и приблизительного вывода. К тому же изменения в патчах маленькие, обычно меняют инструкции перед условным переходом, сам условный переход или что-то заменяют чем-то. Это всё не будет вредоносным.

Код:
Acrobat1
Код:
Acrobat2
Код:
Acrobat4
Код:
Acrodist1
Код:
Acrodist2
Код:
Acrodist3
Код:
Acrodist5
Код:
AcroTray1
Код:
AcroTray2
Код:
AcroTray3
Код:
AcroTray4
Код:
AcroTray5
Код:
BridgeCamRaw1
Код:
CmpEax61
Код:
CmpEax62
Код:
CmpEax64
Код:
HevcMpegEnabler1
Код:
HevcMpegEnabler2
Код:
ProfileExpired2
Код:
ProfileExpired3
Код:
ValidateLicense1
Код:
InstantShutdown1
Код:
PluginVerification1
Код:
LoginVerification1
6.0 Вывод
Мы вместе с вами изучили этот патчер и не нашли ничего особо вредоносного внутри него. Даже рассмотрели все патчи и все функции. Но важный момент - мы работали с исходником GenP. Помимо исходника в архиве идёт ещё и EXE-файл. Насчёт его ничего сказать не могу, так как ещё не ревёрсил его. Поэтому если вы хотите тоже его изучить, для безопасности ЗАГРУЖАЙТЕ AutoIt С ОФИЦИАЛЬНОГО САЙТА И СОБИРАЙТЕ СВОЙ EXE ИЗ ИСХОДНИКА! Также обращайте внимание на версию GenP. Ниже я прикреплю контрольные суммы файлов, что были рассмотрены в статье.

Архив с GenP:

Код:
iz3lne.zip
MD5:
Код:
6b104ba9deb749a6b6ce88b9c6997dae
SHA1:
Код:
19d9b52477606b78bdce568235c0acb9321c1bc4
SHA256:
Код:
14ce93ae01d50b9d2ff3c36c3edd574a9f8bcec56451f3a865fcc210c617a77b
Код:
GenP-3.4.14.1.au3
MD5:
Код:
42c434f0a040132e37eddb5b1d886f8e
SHA1:
Код:
3e94d309d3c1dbd4dd9077082e9caf5926bc0fde
SHA256:
Код:
3dd6cf96e38768110c8f0e64ae8c698e43931ff9fb57b4a1476b63f4e5d45554
Код:
config.ini
MD5:
Код:
add427035968bc6f8bcdf0c5d7580495
SHA1:
Код:
7c1d13771b0546c31b87b36d1f158665ba9f793b
SHA256:
Код:
66232a4d8677cd50612eaebc664b2f2f3556b497d5bf8657967c259ef4723b68
 
Ответить с цитированием

  #2  
Старый 09.02.2025, 22:41
UBUNTUM
Новичок
Регистрация: 08.02.2025
Сообщений: 0
С нами: 665024

Репутация: 0
По умолчанию

Это сильно чувак)
 
Ответить с цитированием

  #3  
Старый 06.05.2025, 18:20
UBUNTUM
Новичок
Регистрация: 08.02.2025
Сообщений: 0
С нами: 665024

Репутация: 0
По умолчанию

Ссылка на Reddit не актуальна!
 
Ответить с цитированием

  #4  
Старый 06.05.2025, 21:35
velvetx
Новичок
Регистрация: 05.05.2025
Сообщений: 0
С нами: 541250

Репутация: 0
По умолчанию

спасибо
успокоил)
 
Ответить с цитированием

  #5  
Старый 07.05.2025, 11:56
koekaker
Новичок
Регистрация: 06.05.2025
Сообщений: 0
С нами: 540389

Репутация: 0
По умолчанию

А подобного разбора патча massgrave никто не делал?
 
Ответить с цитированием

  #6  
Старый 18.05.2025, 11:21
Don Reverso
Новичок
Регистрация: 17.05.2025
Сообщений: 0
С нами: 524585

Репутация: 0
По умолчанию

Бомба =]
 
Ответить с цитированием

  #7  
Старый 01.06.2025, 14:07
ROP
Новичок
Регистрация: 27.08.2019
Сообщений: 0
С нами: 3533622

Репутация: 0
По умолчанию

Цитата:

UBUNTUM сказал(а):

Ссылка на Reddit не актуальна!

Спасибо, что написал! Всё руки не доходили заменить(
Нашёл у себя файлы GenP из статьи. Ссылка ниже

Скачать (Mega.nz)

Либо можно скачать со сторонних сайтов, но проверяйте хеш-суммы.

Рекомендую запускать в образовательных целях из исходника, как в статье, а не EXE. Скомпилированный EXE не разобран в статье.
 
Ответить с цитированием

  #8  
Старый 15.01.2026, 08:44
kerikush
Новичок
Регистрация: 14.01.2026
Сообщений: 0
С нами: 176261

Репутация: 0
По умолчанию

на момент 2026 года у тебя остался только хеш-суммы приложений.
 
Ответить с цитированием

  #9  
Старый 15.01.2026, 08:48
kerikush
Новичок
Регистрация: 14.01.2026
Сообщений: 0
С нами: 176261

Репутация: 0
По умолчанию

Цитата:

kerikush сказал(а):

на момент 2026 года у тебя остался только хеш-суммы приложений.

или сделай подробный разбор Release GenP 3,7,1 · Mojszli/GenP
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.