![]() |
eXeL@B —› Программирование —› Программно отличить реальный код от мусора, как? |
<< . 1 . 2 . |
Посл.ответ | Сообщение |
|
Создано: 25 декабря 2008 14:59 · Личное сообщение · #1 |
|
Создано: 26 декабря 2008 17:30 · Личное сообщение · #2 Что-то тут стали очень активно говорить про брут закриптованного простым ксором кода, а также про то, что лучший способ проверить, расшифрован он или нет - это запустить его. Это фигня, т.к. до того, как можно будет получить такой код, который бы работал, придётся много раз получать тот, который работать не будет ![]() ![]() ----- Stuck to the plan, always think that we would stand up, never ran. ![]() |
|
Создано: 26 декабря 2008 17:36 · Личное сообщение · #3 |
|
Создано: 26 декабря 2008 17:43 · Личное сообщение · #4 rep0A пишет: Поксореный код отличается от мусора тем что он запускается =) Как вариант попробовать эту функу просто позапускать, если знаешь аргументы. Nimnul Вот кто говорил про запуск. А дизасм длин - ну и что? Толку-то с него? Будем раскриптовывать код и смотреть на длину команд, и что это даст? ----- Stuck to the plan, always think that we would stand up, never ran. ![]() |
|
Создано: 26 декабря 2008 17:49 · Поправил: Nimnul · Личное сообщение · #5 |
|
Создано: 26 декабря 2008 17:53 · Личное сообщение · #6 Nimnul На шутку мало похоже, он, походу, серьёзно. А про валидность длин - если только код Визуал Сишный, то ещё ладно, да и то если реализован через асемблерные вставки или не stdcall соглашением о вызовах, то 11111 ещё ничего не значит - это мечта так мусор анализировать. ----- Stuck to the plan, always think that we would stand up, never ran. ![]() |
|
Создано: 26 декабря 2008 17:56 · Личное сообщение · #7 |
|
Создано: 26 декабря 2008 18:30 · Личное сообщение · #8 |
|
Создано: 26 декабря 2008 19:22 · Личное сообщение · #9 |
|
Создано: 26 декабря 2008 19:29 · Личное сообщение · #10 progopis +1 Nimnul А даже если и так, представим, что нету таких пяти однобайтовых команд, ну, вот возбмём и представим. Что толку, есть валидные двухбайтовые, трёхбайтовые рядом стоящие. Короче, этот твой метод можно засунуть в ![]() ![]() ----- Stuck to the plan, always think that we would stand up, never ran. ![]() |
|
Создано: 26 декабря 2008 19:43 · Поправил: progopis · Личное сообщение · #11 Блин и никто не заметил: temp пишет: длина ключа на самом деле = DWORD = 64 бит DWORD=32 бит, ну так, если что... ![]() temp пишет: не миллионы, а ~50 суток, на одной машине Какой молодец! Как же ты подсчитал, если у тебя даже алго ещё нет для определения валидности кода (а это и будет самая ![]() P.S. Без обид. ![]() |
|
Создано: 26 декабря 2008 20:23 · Поправил: temp · Личное сообщение · #12 progopis пишет: DWORD=32 бит, ну так, если что... +1 мая ашипка ![]() а так матчасть учили: 1байт=8 бит DWORD = 4 байта = 32 бита считал во как: допустим, что у нас 1 значение за милисекунду проверяется: 1 час = 3600000 ms; 4294967296(всего вариантов 256^4)/3600000=1193,0464711; делим это на сутки: 1193,0464711/24=49,710269629~50 cуток progopis пишет: P.S. Без обид. да какие такие обиды ![]() ![]() |
|
Создано: 26 декабря 2008 20:26 · Личное сообщение · #13 |
|
Создано: 26 декабря 2008 20:30 · Поправил: temp · Личное сообщение · #14 |
|
Создано: 27 декабря 2008 01:28 · Личное сообщение · #15 ARCHANGEL пишет: А даже если и так, представим, что нету таких пяти однобайтовых команд, ну, вот возбмём и представим. Что толку, есть валидные двухбайтовые, трёхбайтовые рядом стоящие. Короче, этот твой метод можно засунуть в и повернуть там два раза, извини, что так резко, но эта чушь мне уже надоела Сначало пропусти дизасм на испорченном коде, посмотри на него, а потом включи образное мышление ;). Надоело тебя никто не просит свой песемизм растряхивать на окружающих. Если мне надо будет, я смогу написать алго, который будет проверять на валидность код. И основываться этот алго будет на дизасме длин. Самое простое дизасм может не войти в те байты, которые отведены функции и если он подумает, что 0xCC или 0x00 (которые обычно идут сразу за ret что впрочем не важно) входят в последнюю команду, значит валидацию не прошел. Этот метод отсеет 80% остальное отсеят другие методы. Если тебе не дано это осилить, не надо говорить что тебе это надоело, иди четай ксакеп, там много инфы для тебя. ----- have a nice day ![]() |
|
Создано: 27 декабря 2008 07:17 · Личное сообщение · #16 Nimnul Если язык был высокоуровневый, а наверно это так, и наша задача расшифровать именно процедуру, то ловить надо конструкции типа leave/retn (leave/retf), push ebp/mov ebp,esp и прочие, а также, как было правильно кем-то замечено выше, push XXX/pop XXX. В этом случае не надо придумывать хитро ![]() Скорее всего, там не всё так просто. Код в идеале должен быть разбавлен мусором, что увеличивает его размер, затем зашифрован и вынесен в отдельную секцию. Тогда дизасм длин едет лесом. Ловить конец такого кода бесполезно. За ret'ом имею полное право ставить что хочу. Ещё один возможный метод - попытка выполнения этого кода. НО! Очень осторожно! Поставив жёсткие ограничения на страницы памяти (чтобы левые прыжки и call'ы мочить), на вызовы API, расставив SEH (а лучше VEH). Если там есть ret и он вернул нам EIP сразу после CALL - то всё ок (первая проверка пройдена). Вот только реализовывать такое говно я бы не хотел (объём работ слишком велик). Да и за скорость метода не ручаюсь. Во время обмозговывания предыдущего метода вспомнил ещё один трюк. За частую при попытке дизасмить то, что кодом не является возникает проблема "левых" адресов. Я имею в виду вот что: Code:
![]() |
|
Создано: 27 декабря 2008 14:50 · Личное сообщение · #17 progopis пишет: Ловить конец такого кода бесполезно. За ret'ом имею полное право ставить что хочу. Найти длину зашифрованной функции можно в отладке, скормив проге не правильный код, она будет пытаться расшифровывать функцию определенной длинны... Кроме того как прога сама определяет правильный ключ или нет? Не думаю что она тупо расшифровывает и запускает, ибо может легко упасть. Значит есть какая то сигнатура или контрольная сумма, она где то храниться, здесь и есть ключ к победе. ----- have a nice day ![]() |
|
Создано: 27 декабря 2008 15:22 · Личное сообщение · #18 Nimnul пишет: Не думаю что она тупо расшифровывает и запускает, ибо может легко упасть. Значит есть какая то сигнатура или контрольная сумма, она где то храниться, здесь и есть ключ к победе. а почему бы через SEH не отлавить момент падения и не подменить данные на какое-нить гавно? я бы так и сделал ![]() ----- все багрепорты - в личные сообщения ![]() |
|
Создано: 27 декабря 2008 15:28 · Личное сообщение · #19 |
|
Создано: 27 декабря 2008 15:42 · Личное сообщение · #20 Nimnul не всегда так бывает! ![]() вот если взять пример с Sentinel, то там ситуация очень похожа на ту которую описал автор. т.е. идет код push ebp mov ebp,esp . . CALL Decrypt_Code -> в котором идет связь с ключем и получение констаты типа для "ксора". DWORD Len_Encrypt_Code /// /// Encrypt Function Code /// /// CALL Encrypt_Code mov esp,ebp pop ebp retn так вот, там нет проверки на то что код успешно раскриптован, т.к. есть проверка на наличие и валидность ключа в порте! если ее подменить, но константа будет неверная прога просто упадет. имхо как один из способов усложнить жизнь реверсеру. ![]() |
|
Создано: 27 декабря 2008 16:50 · Поправил: Nimnul · Личное сообщение · #21 HandMill А прога может не упасть на исключении. представь если будет что то вроде push xxxx; ret где адрес xxxx функции удаления ветки реестра или файла. За такое на западе подадут в суд. Прикольно юзер ошибся при вводе ключа и прога падает с исключением или удаляет ветку реестра, или циклится на какой нибудь шняге. Поэтому имхо разработчики прота, этого не могли допустить, а значит в проте предусмотрен метод валидации расшифрованного кода, его и нужно реверсить, а потом брут с этим методом. RSI наверно я что то пропустил, но если там есть железка которая все защищает, тогда это меняет дело. Она может принимать ключ и будет отдавать значение для расшифровки. В этом случае нужно самому придумывать метод валидации, о чем я говорил в других постах, простой ксор не является крипто стойким, поэтому ломануть реально. И в то же время я думаю, что разработчики железки не могли так лохануться и там какое нибудь серьезное крипто. ----- have a nice day ![]() |
|
Создано: 27 декабря 2008 17:46 · Поправил: progopis · Личное сообщение · #22 Nimnul пишет: пытаться расшифровывать функцию определенной длинны... Ещё раз говорю - после ret'а могу оставить любое гов*о. Раскриптовывать буду кусок чего-то. Не давая реверсеру понять, какая длина. Вот например раскриптованный текст: Code:
Ну как? Пример кода - вполне реальный. Мой способ определением leave/retn, push XXX/pop XXX тоже идёт лесом. Только если байты 5x, 6A YY (КОПы push'ей перед call'ами) искать подряд идущие. Короче по ходу надо крекми писать - посмотрим как ты его ломанёшь... Нет, я не пытаюсь вызов сделать ("Ну докажи что ты реально крут, парень!"), просто, видимо, на словах сложно объяснить что я имею в виду. Nimnul пишет: Значит есть какая то сигнатура или контрольная сумма А вот это +1. Если прогер не дурак - проверка должна быть. Но опять же я это могу обойти - проверять буду большой ключ и его CRC, а уже из него делать ключ для дешифровки. Вряд ли пользователь угадает ключ, а на реверсера мне пофиг - пусть у него всё вылеатает... ![]() |
|
Создано: 27 декабря 2008 18:00 · Поправил: Nimnul · Личное сообщение · #23 progopis пишет: Не давая реверсеру понять, какая длина. Ты читал не внимательно длинну функции мы узнаем точно не по коду а по буферу который должен быть расшифрован. Я согласен с тобой, что закинули мусор в конец и писец. Тема конечно интересная, но я не буду думать за других. пусть temp придумывает алго, это его тема. но заметь если в функции нет ни одной команды выхода (ret, call, jmp), тогда функция не валидная, если придумать два десяка таких проверок, тогда я думаю можно из всех возможных вариантов отсеять 99.99%. останется пара десятков, которые можно глазом пробежать и все будет ясно. А теперь посмотри на реальный мусор, неужели сразу не видишь, как его отсеить. Code:
----- have a nice day ![]() |
|
Создано: 27 декабря 2008 18:02 · Поправил: progopis · Личное сообщение · #24 Nimnul Я-то вижу. Надо алго написать, который видит ![]() Ты опять меня не понял... Я сначала зашифрую кусок кода, больший чем сама функа, предварительно добавив в конец мусора... И соответственно расшифровывать буду кусок, больший чем сама функа. И кстати не всегда есть ret в функциях (хотя это не противоречит тому, что ты сказал)... Пример: Code:
Demon666 +1 ![]() |
|
Создано: 27 декабря 2008 18:15 · Личное сообщение · #25 progopis пишет: Короче по ходу надо крекми писать - посмотрим как ты его ломанёшь... Гы, да че его писать - он давно написан ;) Второй эбайт у TEplus в моем плуге Там ксорится 20 байт двордом(хеш от ключа) Если ключа в ини-файле нет то и расшифровки не будет ;) только функционал плуга порезан будет, гы-гы Попробуйте сбрутить кодес(20 байт валидного кода) чтоле, ну естественно только по-честному;) Не смотря на решения которые там выложили, уровень срякми там низкий ;)) http://exelab.ru/f/action=vthread&forum=12&topic=12567 Проще скардить и "если есть привязка" сделать копипаст кода и неипаццо!!! Тобишшш progopis пишет: Если что, скардить можно будет, а всякие там бруты по миллионы лет - не наш метод. +1 ----- ЗЫ: истЕна где-то рядом, Welcome@Google.com ![]() |
|
Создано: 27 декабря 2008 18:50 · Поправил: Nimnul · Личное сообщение · #26 progopis пишет: И кстати не всегда есть ret в функциях Nimnul пишет: нет ни одной команды выхода (ret, call, jmp) progopis пишет: Ты опять меня не понял... Я сначала зашифрую кусок кода, больший чем сама функа, предварительно добавив в конец мусора... Nimnul пишет: Я согласен с тобой, что закинули мусор в конец и писец. progopis пишет: Я-то вижу. Надо алго написать, который видит Если видишь значит алго написать возможно. ----- have a nice day ![]() |
<< . 1 . 2 . |
![]() |
eXeL@B —› Программирование —› Программно отличить реальный код от мусора, как? |