Приветствую всех! В данной статье мы будем учиться взламывать программы. Защита сегодняшнего софта не представляет из себя что-то сверхъестественное, но для тренировки подойдёт.

Обзор программы

Саму программу вы можете скачать здесь. (пароль от архива: crackmes.one). Её суть заключается в том, что она требует имя пользователя и пароль. Если имя пользователя для нас не очень важно, то вот пароль влияет на то, что выведет программа в итоге.

Как видите программа выводит надпись "Bad". Давайте это исправлять.

Как будем взламывать

Наша задача - сделать так, чтобы программа выводила "Good" в независимости от того, что пользователь ввёл в поле пароля. Если вы захотели декомпилировать данную программу, закинув EXE-файл в программу по типу dotPeek или ILSpy, то у вас ничего не выйдет. Ведь данная программа написана не на C#, исходный код которого можно легко посмотреть, а на C++, декомпилировать который нельзя.

Итак, если декомпилировать программу нельзя, значит мы будем её дизассемблировать, то есть изменять код ассемблера. Я не буду сильно углубляться в тему ассемблера, но если кратко, Assembler - это низкоуровневый язык программирования, приближенный к машинному коду. Когда вы запускаете какую-либо программу, неважно на каком языке она написана, в любом случае её исходный код будет переведён на язык ассемблера, а потом в машинный код.

Требуемое ПО

Чтобы взломать программу, нам понадобится следующее ПО:

  1. WinHex. Это шестнадцатеричный редактор, с помощью которого можно просматривать и изменять различные файлы.

  2. IDA Pro. Это тот самый дизассемблер, с помощью которого можно изучать исходный ассемблерный код программы.

Данные программы бесплатны, скачать их можно с официальных сайтов.

Взлом программы

Итак, запускаем IDA Pro и видим вот такую картину:

Нажимаем New, выбираем EXE-файл, у вас откроется вот такое окно:

Нажимаем OK, в следующем окне нажимаем No. Теперь у вас откроется ассемблерный код программы в виде графов. Нажмите ПКМ, а затем в появившемся окне на Text View, чтобы исходный код отобразился в виде текста, так удобнее.

Если пролистнуть немного вниз, то можно увидеть очень интересную область кода:

.text:000000014000F1E8
.text:000000014000F1E8 loc_14000F1E8:                          ; CODE XREF: main+124↓j
.text:000000014000F1E8                 movsx   ecx, byte ptr [rax]
.text:000000014000F1EB                 add     rax, 1
.text:000000014000F1EF                 add     edx, ecx
.text:000000014000F1F1
.text:000000014000F1F1 loc_14000F1F1:                          ; CODE XREF: main+113↑j
.text:000000014000F1F1                 cmp     rax, r8
.text:000000014000F1F4                 jnz     short loc_14000F1E8
.text:000000014000F1F6                 cmp     [rsp+0C8h+var_9C], edx
.text:000000014000F1FA                 jz      short loc_14000F216
.text:000000014000F1FC                 lea     rcx, aBad       ; "Bad\n"
.text:000000014000F203                 call    _Z6printfPKcz   ; printf(char const*,...)
.text:000000014000F208
.text:000000014000F208 loc_14000F208:                          ; CODE XREF: main+152↓j
.text:000000014000F208                 xor     eax, eax
.text:000000014000F20A                 add     rsp, 0A8h
.text:000000014000F211                 pop     rbx
.text:000000014000F212                 pop     rsi
.text:000000014000F213                 pop     rdi
.text:000000014000F214                 pop     rbp
.text:000000014000F215                 retn
.text:000000014000F216 ; ---------------------------------------------------------------------------
.text:000000014000F216
.text:000000014000F216 loc_14000F216:                          ; CODE XREF: main+12A↑j
.text:000000014000F216                 lea     rcx, aGood      ; "Good\n"
.text:000000014000F21D                 call    _Z6printfPKcz   ; printf(char const*,...)
.text:000000014000F222                 jmp     short loc_14000F208
.text:000000014000F222 main            endp
.text:000000014000F222

Нас интересуют следующие строчки:

.text:000000014000F1FA                 jz      short loc_14000F216
.text:000000014000F1FC                 lea     rcx, aBad       ; "Bad\n"
.text:000000014000F203                 call    _Z6printfPKcz   ; printf(char const*,..)

На первой строчке происходит перемещение в область кода с проверкой флага Z в регистре EFLAGS процессора. После данной проверки выводится надпись "Bad". Первая строчка перемещает в область кода, где выводится надпись "Good". То есть, скорее всего, первая строчка и проверяет корректность пароля. Нам остаётся изменить её на команду непроверяемого перехода, то есть jmp.

Переходим на строчку проверки и запоминаем смещение:

Смещение равно E7FA. Открываем WinHex, в нём открываем EXE-файл. В меню сверху переходим в пункт Navigation, нажимаем Go To Offset вводим E7FA и нажимаем OK. Программа переместит вас на место данной команды, теперь мы должны поменять код 74 на EB, потому что EB - это шестнадцатеричный аналог команды jmp в ассемблере.

Теперь сохраняем изменённый файл и тестируем.

Ура! Мы взломали программу. Поздравляю!

Да, я многое не объяснил, потому что одной статьи точно не хватит. Тренируйтесь и изучайте новые способы взлома. Удачи!

Комментарии (14)


  1. fransua
    06.05.2024 13:09
    +2

    Интересно, как защищаются от такой модфиикации настоящие программы? Они наверное подписывают свои файлы сертификатами, или даже через TPM во время установки?


    1. DizelNo
      06.05.2024 13:09
      +1

      Видел что-то подобное с хэшем. То есть, если изменить байт программы, то у нее изменится хэш. Программа видела это и не работала.


    1. YouROK
      06.05.2024 13:09
      +4

      Лет 15-20 назад занимался такими вещами. Подпись ничего не даст, кроме как проверки в винде на то что файл не модифицированный и эту подпись можно было легко снять. Но были тогда и другие способы защитить свою программу. Самые хорошие способы это так сказать самому придумывать способ защиты на ассемблере и внедрять его в свою программу. Еще один способ это использовать защитники для программ. Сейчас это Denuvo и подобные. А тогда самой хорошей защитой была программа themida, она обфусцировала код и шифровала. Точно не помню как она работала, но помню люди обсуждали на crack.exe, что она по мере исполнения расшифровывает кусок кода, выполняет его, снова зашифровывает и так далее. Был и есть еще такой инструмент как upx, это архиватора, но только для запускаемых файлов, делаешь простую защиту как в статье, архивируешь upx и при запуске ты не найдешь код как автор, так как он будет архивирован, только начальный загрузчик upx понятен будет. В этом случае можно было воспользоваться тем же самым upx для разархивирования, но это не всегда помогало. Если не помогло и инструменты для взлома тоже не помогли, то вручную, был у меня один раз такой случай.
      Запускаешь программу, до момента когда upx загрузчик выполнит все действия в памяти и программа будет нормально, смотришь где так сказать начало программы и делаешь дамп. Далее в дампе меняешь pe и начало программы на то самое место и начинаешь искать строки и тд.

      Были другие протекторы, но я уже не помню как они взламывались и работали. В основном помогает софт антипротекторы для взлома первой стадии, потом руками ищешь где что.

      Еще бы сказал что для новичков ida pro слишком сложная, я ее в редких случаях использовал. Есть так сказать дебагер для кряка, это ollydbg, хз вторая версия вышла или нет. Им проще всего и она запоминает бряки от предыдущего запуска и комменты ставить можно, плюс интерфейс мне больше нравился.

      Такие программы как в статье называются crackme, есть сайты где выкладывают их и есть уровни, для новичков и выше. Но советовали первым делом сломать winrar, так как там чуть больше защита чем в программе из статьи, но такая же, поменять на jmp в нескольких местах


      1. mlnw
        06.05.2024 13:09
        +2

        ollydbg

        Она вроде так в x64 и не шмагла, т.ч. давно стала нерелевантной. Поправьте если что изменилось.

        Но советовали первым делом сломать winrar

        Сначала подумал, что кто-то сломал винрарные пароли на архивах (до сих пор лежит собственный архив с утерянным лет 15 назад паролем в ожидании лучших времен), потом понял, что речь о самом архиваторе, которым, наверное, уже лет 10 как никто не пользуется.


        1. rst10h
          06.05.2024 13:09

          там где то недавно статья была о том, что можно подключить GPU к этому делу, скорее всего уже есть готовый софт, может помочь)


    1. XenRE
      06.05.2024 13:09

      Большинство - никак. Даже если приложение платное и там какая-нибудь активация. Особо упоротые вешают всякие протекторы типа денувы, но по итогу кому надо - все равно взломает, а легальные пользователи страдают. В особо запущенных случаях бывает даже покупают лицензию но потом ставят кряк.


  1. Shulbert
    06.05.2024 13:09
    +1

    А можно lea rcx, aBad заменить на lea rcx, aGood ?


    1. Xbrome Автор
      06.05.2024 13:09
      +2

      В данном случае можно, но если в секции вывода "Good" кроме помещения адреса переменной aGood в регистр RCX будет ещё, например, открытие какого-либо окна, то твой метод не сработает. Хоть у нас и выведется надпись "Good" код продолжит выполняться в секции вывода "Bad", т. к. условие cmp [rsp+0C8h+var_9C], edx выдало ложь, и переход на секцию loc_14000F216 не случился.


  1. lisitsinyr
    06.05.2024 13:09

    Ломать не строить!


  1. NutsUnderline
    06.05.2024 13:09
    +3

    C++, декомпилировать который нельзя

    смущает меня эта фраза


  1. RemB
    06.05.2024 13:09

    Зачем так грубо, тут же все просто:

    username = 'test'
    passwd = 0
    for i in range(len(username)):
        passwd = passwd + (ord(username[i:i+1]))
    print ('Password: ' , passwd)


  1. AlexSky
    06.05.2024 13:09

    Как-то очень просто. Лет 20 назад делал очень наивную защиту от неавторизованного запуска для одной тулзы. Но и тогда там была и привязка к железу, и размазанные по коду проверки, причём не просто if, а подмешивание к математике тулзы частей ключа, плюс автоматически сгенерированные сотни ложных обращений к ключу. Развлекался, как мог.

    У конкурентов появилось только когда кто-то слил генератор ключей.


  1. SSranked
    06.05.2024 13:09
    +1

    Название статьи несколько ложно, ведь, как следует из статьи, предполагалось, что «первый» будет относиться к «взлому», а не к «программе»: «Ваш первый взлом программы».


  1. NONAMEMACHINE
    06.05.2024 13:09

    Слишком сложное решение для поставленной задачи. "Наша задача - сделать так, чтобы программа выводила "Good" в независимости от того, что пользователь ввёл в поле пароля. "
    Открываем Hex редактор,

    меняем строку Bad на Good,

    получаем результат