# Часть 18

[\[Используемые материалы\]](https://github.com/yutewiyof/intro-rev-ida-pro/tree/e1367e11cc661f3d69c02ae5f733b7dd168bc5ab/.gitbook/assets/files/18.zip)

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

Хорошо помнить, что для статического анализа нет необходимости распаковывать файл. Нам просто нужно получить **OEP** и сделать **TAKE MEMORY SNAPSHOT**. Затем, нужно скопировать файл **.IDB** в другое место и открыть его там. Этого бы хватило, чтобы анализировать его статически, но хорошо иметь распакованный файл, это позволит отлаживать файл и может иногда помогать.

Я открываю распакованный файл в **IDA**, и первое, на что я обращаю внимание - это строки.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGXNVpL8zlsp6Pd1%2F18-01.png?generation=1563215345339905\&alt=media)

Хорошо, мы знаем, что первое, что делаем программа после запуска - это печатает строку "**Pone un user"**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu47mboqhh8teppHH%2F02.png?generation=1563265893274475\&alt=media)

Поэтому, я делаю двойной щелчок на этой строке в **IDA** и попадаю сюда.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu48LpXjiN3AJV2bb%2F03.png?generation=1563265891557139\&alt=media)

И ищу перекрёстную ссылку с помощью клавиши **X**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu48dlvBXL4bEva56%2F04.png?generation=1563265892901554\&alt=media)

Видно, что ссылка нашлась. Теперь можно перейти по ней.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu48oBelc26aC9zK6%2F05.png?generation=1563265901564367\&alt=media)

Давайте будем статически реверсить начинаю отсюда.

В функциях, основанных на **EBP**, мы сказали, что сначала, в стек, с помощью инструкции **PUSH EBP** сохраняется **EBP** функции, которую я вызвал, и, затем, исполняется инструкция **MOV EBP**, **ESP** для установки **EBP** как опорного значения для этой функции, откуда будут вычисляться позиции изменяемых аргументов и буферов.

Видно, что программа резервирует **0x94** байта для локальных переменных и буферов, начиная с базового значения **EBP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu493LawjCpyXLalp%2F06.png?generation=1563265893962396\&alt=media)

Хорошо, делая двойной щелчок на любой переменной или аргументе, **ЗАГРУЗЧИК** показывает статическое представление стека.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu49BKlpRyycvvPAu%2F07.png?generation=1563265891915940\&alt=media)

Здесь видим, что эта функция без аргументов, потому что сначала в стек помещаются аргументы с помощью инструкции **PUSH** перед вызовом функции и они были бы ниже адреса возврата **R**. В нашем случае, ниже **R** ничего такого нет, поэтому это функция без аргументов.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu49KSdpvrPQ9Rymv%2F08.png?generation=1563265901626836\&alt=media)

Это тот же самый случай, как и в прошлый раз. Это функция **MAIN** и она имеет такие аргументы: **ARGV** и **ARGC** и т.д. Но, так как она не использует их внутри функции, то **IDA** не учитывает эти аргументы.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu49ZxpLvgWva22SV%2F09.png?generation=1563265897727488\&alt=media) ![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu49sXXtSTwVCBlN7%2F10.png?generation=1563265894033857\&alt=media)

Давайте переименуем эту функцию в **MAIN**, и **IDA** добавит мне автоматически три аргумента.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGXvBaxyNwIT6cNA%2F18-11.png?generation=1563215346404667\&alt=media)

Также, если мы нажмём клавишу **X** на любом из трёх аргументов.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGXxjPGm5Y40I61B%2F18-12.png?generation=1563215345291630\&alt=media)

Увидим, что аргументы не используются, так что они не очень важны для нас.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGXz1ch3oGbauIk9%2F18-13.png?generation=1563215345207237\&alt=media)

Возвращаясь к статическому представлению стека, видим, что ниже адреса возврата, как и положено, есть аргументы. Затем идёт буква **S**, что означает **STORED EBP**. Как мы сказали, это значение хранит **EBP** предыдущей функции, которое помещается в стек с помощью инструкции **PUSH EBP** и выше есть место для переменных, которое обычно имеет переменную **VAR\_4**, которая нужна для защиты стека от переполнения буфера.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4AZFAT8phBdKHKW%2F14.png?generation=1563265891810226\&alt=media)

Эта переменная имеет две перекрёстные ссылки. Одну в начале функции, когда программа сохраняет значение **SECURITY COOKIE(Печеньки безопасности. Прим. Яши)** в стек.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4AhHUI8xtySC_08%2F15.png?generation=1563265893114214\&alt=media)

Вышеупомянутое значение - это случайное значение, которое **XOR**'ится с помощью **EBP** и сохраняется в переменную **VAR\_4** в начале функции. А другая ссылка находиться здесь.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4ArAMUFFLRkw2uM%2F16.png?generation=1563265892659856\&alt=media)

Где программа восстанавливает исходное сохраненное значение и **XOR**ит его с помощью **EBP** для восстановления исходного значение в **ECX**, и внутри этого **CALL**, программа проверяет это значение.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4B3hmdAw_TqXpxD%2F17.png?generation=1563265897470366\&alt=media)

Если всё нормально, программа будет возвращаться, но если **ECX** не имеет первоначального значения **\_\_SECURITY\_COOKIE**, программа перейдёт в **JMP**, который ведёт на **ВЫХОД** и не позволит Вам достигнуть **RET** функции.

Плохой вариант может случиться и программа пойдёт на **ВЫХОД**, если произойдёт **ПЕРЕПОЛНЕНИЕ**, которое перезаписывает значение **VAR\_4** внутри функции. Сейчас давай переименуем **VAR\_4** в **CANARY(КАНАРЕЙКА)** или **SECURITY COOKIE**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGY8LOQHpH77yjFK%2F18-18.png?generation=1563215345700052\&alt=media)

Сейчас, листинг выглядит более красиво и читаемо.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYA4uJ-76ksKrYM%2F18-19.png?generation=1563215346204817\&alt=media)

Затем, видим две переменные, о которых мы ещё ничего не знаем и о которых мы ещё не говорили, как они используются. Они инициализируются нулями. Также есть переменная, которая уже имеет имя **SIZE** и инициализируется числом **8**.

Если посмотрим перекрёстные ссылки для переменной **VAR\_7D**, увидим, что она используется здесь.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYCkhuFp9tmi8qX%2F18-20.png?generation=1563215347489102\&alt=media)

Программа сохраняет значение **AL** в эту переменную при возврате из **CALL** и затем перемещает этот байт в регистр **EDX**, для того, чтобы проверить равен он нулю или нет, чтобы сделать вывод о том, хорошие мы реверсеры или плохие. Так что, это переменная одного байта или флаг. Следовательно, мы можем переименовать её в **FLAG**\_**EXITO**.

Мы проверяем в статическом представлении стека, что **IDA** определила переменную как байт.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYEcNBwaC0Naq3j%2F18-21.png?generation=1563215346474851\&alt=media)

Нужно поменять ей имя с помощью клавиши **N**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4CCrTazAmOLTvJA%2F22.png?generation=1563265896727159\&alt=media)

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

Очевидно, если бы нам нужно было просто пропатчить этот переход **JZ**, это было бы то место, где нужно было это сделать, но мы будем стараться решить этот крекми правильным способом.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4CMa9kHFB3ABQFP%2F23.png?generation=1563265901495281\&alt=media)

Мы видим, что другая переменная **VAR\_90**, которая тоже обнуляется в начале, складывает байты, которые читаются из буфера **BUF** один за другим и помещает их в регистр **EDX** по адресу **0x231109**, а затем прибавляет его к нулю в первом цикле, и **EDX** всегда накапливает сумму всех байтов. Мы увидим, что он содержит буфера **BUF**, который он читает. Давайте продолжать расследование.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYK8gQqYolxfrjE%2F18-24.png?generation=1563215345591004\&alt=media)

Видно, что **VAR\_84** - это счетчик этого **ЦИКЛА**, который складывает значения. Но видно, что цикл складывает только первые четыре байта, потому что он выходит, когда это значение больше или равно **4**.

Здесь видно этот **СЧЁТЧИК** и как он увеличивается.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYMvhT_PsaKoZg-%2F18-25.png?generation=1563215345894019\&alt=media)

Очевидно, этот счётчик также присутствует по адресу **0x231109** для чтения буфера **BUF** с самого начала и нужен для сложения его следующих байтов.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4DFoeq3otG0_2sS%2F26.png?generation=1563265892897418\&alt=media)

Хорошо, мы уже видели, что этот **ЦИКЛ** читает байты из буфера **BUF**, затем суммирует их и сохраняет эту сумму в **SUMATORIA**. Теперь давайте посмотрим, что находится в **BUF**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4DTFTPhbYUaXnkn%2F27.png?generation=1563265893256408\&alt=media)

Видно, что размер **BUF** равен **8** байтами и это максимальная длина для имени пользователя. Функция **GETS\_S** используется для получения данных с клавиатуры.

Нам нужно поменять функцию по адресу **0x002310A0** на **PRINTF**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4Dh2JB7l023WoVD%2F28.png?generation=1563265891472774\&alt=media)

Готово.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYUZ6EsXPei2bmP%2F18-29.png?generation=1563215345572979\&alt=media)

Также, в статическом представлении стека мы видим длину буфера **BUF** с помощью правого щелчка и выбора пункта **ARRAY**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4EYPcv0Hq3vqciB%2F30.png?generation=1563265895379963\&alt=media)

Размер совпадает с исходным кодом.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4ExuseO-8hIoJ81%2F31.png?generation=1563265893251399\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4FJ-qGp9YCctHjb%2F32.png?generation=1563265893828772\&alt=media)

Представление стек становится для нас более ясным.

После получения данных в буфер **BUF**, программа передаёт их в функцию **STRLEN**, чтобы узнать длину данных, которые были введены.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4FYn6nCNJwOP4UR%2F33.png?generation=1563265893627745\&alt=media)

Следовательно, **VAR**\_**88** это количество байт, которые мы вводим.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4Fkab32XMiSY1UU%2F34.png?generation=1563265895283538\&alt=media)

И если длина буфера меньше чем **4**, программа идет на **ВЫХОД**.

Из всего этого, уже можно сделать вывод, что этот **ЦИКЛ** складывает первые четыре байта пользователя, которые мы ввели. Поэтому давайте перегруппируем блоки, для того чтобы они не мешались и смотрелись лучше. Щелкаем в панели каждого блока зажав **CTRL**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYfnKlpobfgJj0I%2F18-35.png?generation=1563215345316263\&alt=media)

Сейчас выглядит намного лучше. С помощью правого щелчка **GROUP NODES** и выбора пункта **UNGROUP** я могу разгруппировать блоки, если нам это понадобится.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYhUL-ooIdA9rEm%2F18-36.png?generation=1563215345189406\&alt=media)

Видно, что цикл снова использует тот же буфер **BUF**, чтобы получить пароль, поскольку он уже сохранил сумму первых **4** байт пользователя.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYjVZp4IUoe_aTc%2F18-37.png?generation=1563215347668405\&alt=media)

Снова программа использует функцию **STRLEN**, чтобы узнать размер буфера и если он меньше чем **4**, программа отправляет нас на **ВЫХОД**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4GspyHyzuegSkbE%2F38.png?generation=1563265892958753\&alt=media)

Если размер буфера равен или больше **4**, программа продолжит выполнение с зеленого блока.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4H5iLaswPJIR9aE%2F39.png?generation=1563265897733809\&alt=media)

Затем, она берет пароль и конвертирует его в **HEX** значение с помощью функции **ATOI**. В **PYTHON** для этой же цели можно использовать функцию **HEX**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4HX2d-lZMRh0Er3%2F40.png?generation=1563265894895158\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYr94SLji4IEVz3%2F18-41.png?generation=1563215347420766\&alt=media)

Здесь видно, что пароль **XOR**ится в **HEX** представление с помощью ключа **0x1234** и программа сохраняет его снова в ту же переменную.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4INdZnhqpvq0z9M%2F42.png?generation=1563265893882347\&alt=media)

Мы видим, что программа будет сравнивать сумму первых **4** байт пользователя и **HEX** значение пароля обработанное операцией **XOR** с ключом **0x1234** в этой функции, которую мы назовём **CHEQUEO\_EXITO**. Результат функции определит переход программы в хорошее сообщение или плохое.

Здесь, мы видим два аргумента. **ARG\_4** будет тем, который помещается первым.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYv0eAOn3cveGSD%2F18-43.png?generation=1563215345213378\&alt=media)

Так что давайте переименуем внутри функции оба этих аргумента.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4InlPa59dIoQjVj%2F44.png?generation=1563265895305852\&alt=media)

Пришло время правильно настроить аргументы для этой функции, для этого делаем правый щелчок и выбираем **SET TYPE**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGYzHoNLfAmEt96p%2F18-45.png?generation=1563215345946122\&alt=media)

Смотрим на результат после проделанной операции.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZ00s_ZTx7JIP-s%2F18-46.png?generation=1563215346921416\&alt=media)

Смотрим, распространились ли теперь ссылки?

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4J_NERTZpjg3785%2F47.png?generation=1563265897923466\&alt=media)

Видно, что синие сообщения, которые появились при распространении имён, соответствуют именам в ссылке, так что всё сработало правильно.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4Jnt2dnX3Jd8P2S%2F48.png?generation=1563265894953839\&alt=media)

Я вижу, что перед сравнением значений, программа делает **SHL EAX**, **1** что равносильно умножению аргумента на **2**.

Значит, если они равны, программа перейдёт в зеленый блок, где она поместит **1** в регистр **AL**, и она будет возвращать значение как флаг **FLAG\_EXITO**, который должен определить, хорошие мы реверсеры или плохие.

Обобщим всё это.

Программа берет первые **4** байта имени **ПОЛЬЗОВАТЕЛЯ** и складывает их.

**ПАРОЛЬ** переводится в **HEX** и он **XOR**ится с помощью ключа **0x1234** и затем умножается на **2**.

Теперь будем делать формулу, предполагая, что мы знаем имя **ПОЛЬЗОВАТЕЛЯ**, так как кейген основан на знании этого имени. С помощью определённого имени **ПОЛЬЗОВАТЕЛЯ**, кейген будет находить соответствующий пароль.

**X = ПАРОЛЬ** конвертируется в \*\*HEX

(X ^ 0x1234) \* 2 = СУММА\*\*

Если поделим на \*\*2

X ^ 0x1234= (СУММА/2)\*\*, то получится так

**X = (СУММА/2) ^ 0x1234**

Функция **XOR** обратима и она работает с членами так:

\*\*A ^ B = C

A = B ^ C\*\*

Хорошо, значение **X**, которое нужно найти, рассчитывается по следующей формуле

**X = (СУММА/2) ^ 0x1234**

Если моё имя было бы например **pepe**, которое действительно, потому что оно меньше чем **8** байт, сумма байтов рассчитывалась бы так.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZ6v7j54YGrEXhg%2F18-49.png?generation=1563215345276813\&alt=media)

Здесь, мы получили сумму для моего пользователя **pepe**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZ8pme38pp1q_-s%2F18-50.png?generation=1563215347049348\&alt=media)

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4KnQJ9dRtYAWGxy%2F51.png?generation=1563265891952407\&alt=media)

Скрипт теперь выглядит лучше, потому что он проверяет, что имя больше или равно **4** как того просит программа.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZCfnLeCfZni-lg%2F18-52.png?generation=1563215345321253\&alt=media)

Видно, что используя **RAW**\_**INPUT(Считывает и возвращает строку входных данных. Прим. Яши)** мы получаем всё, что мы печатаем через консоль.

Результат для **pepe** схожий. Сумма равна **0x1AA**. Но я могу получить её и для любого пользователя, например **fiaca**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4LOsdQpBsrgLtoi%2F53.png?generation=1563265895912380\&alt=media)

Мы получаем такую формулу:

**X = (СУММА/2) ^ 0x1234**

Поэтому сумма должна делиться на **2** и **XOR**иться с помощью ключа **0x1234**, чтобы находить пароль в **HEX** виде.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4LZijxlejSngOXF%2F54.png?generation=1563265895733131\&alt=media)

Если я пробую это значение, которое подсчитал нам скрипт.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZIUK_fMsaSedjp%2F18-55.png?generation=1563215346071776\&alt=media)

Теперь у нас есть кейген. Сейчас, нам не нужно делать преобразование пароля из **HEX** в десятичное значение, потому что **PYTHON** всегда печатает в десятичном формате по умолчанию.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4LxfrGP066dLFHl%2F56.png?generation=1563265892727627\&alt=media)

Мы видим, что скрипт складывает только первые **4** символа имени пользователя. Имя не имеет значения, если пароль больше, но **4** начальных символа похожи.

Поэтому приложение падает при вводе **8** символов, так как имя должно состоять из **8** символов, включая завершающий нуль в конце строки.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4MB_kkVbLwFGGPk%2F57.png?generation=1563265892955907\&alt=media)

До **7** символов программа функционирует хорошо.

Только в ней есть одна проблема, когда сумма получается нечётной.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZOcQgHOaWJukOS%2F18-58.png?generation=1563215346206421\&alt=media)

Уравнение не имеет решения, так как пароль заканчивается умножением на **2** и является умножением целочисленных целых чисел, он никогда не будет нечетным, так что мы добавляем эту проверку в скрипт.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjqtEP2kV1qNtJHVrED%2F-LjqtGZQD6VylLrfyGP1%2F18-59.png?generation=1563215346177719\&alt=media)

Здесь, мы проверяем остаток от деления на два. Если он равен нулю, это пара не имеет решения.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljtu4MqHmsaimjyJbGi%2F60.png?generation=1563265898401175\&alt=media)

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

До встрече в **19**-й части.

Автор оригинального текста — Рикардо Нарваха.

Перевод и адаптация на английский язык — IvinsonCLS.

Перевод и адаптация на русский язык — Яша Яшечкин.

Перевод специально для форума системного и низкоуровневого программирования - WASM.IN

15.10.2017

[**Источник: ricardonarvaja.info**](http://ricardonarvaja.info/WEB/IDA%20DESDE%20CERO/CURSO%20DE%20IDA%20TUTES/18-INTRODUCCION%20AL%20REVERSING%20CON%20IDA%20PRO%20DESDE%20CERO.docx)
