Сейчас на форуме: zds, kris_sexy, ==DJ==[ZLO] (+7 невидимых) |
eXeL@B —› Крэки, обсуждения —› Java crackme / proof of concept |
Посл.ответ | Сообщение |
|
Создано: 20 июня 2006 17:00 · Личное сообщение · #1 Небольшой crackme на Яве, использованы идеи из второй, еще не выложенной, части Unsafe Java. Основная цель - проверить работоспособность и оценить смысл более широкого применения подобных приемов. Поэтому был бы рад увидеть не просто сообщение о том, что взломан, но и хотя бы краткое мнение вместе с описанием процесса. Если у кого-то не запускается или обваливается, пишите с указанием версии Явы и параметров, с которыми пытались вызвать. Задание - написать генератор ключей, хотя желающие в принципе могут и патчить. Алгоритм проверки ключа сам по себе примитивный, в одну строчку. Обфускатором не обработано, декомпилируется без проблем. Рассчитано на виртуальную машину Sun, проверял с версиями от 1.4.2_08 до 1.5.0_07 включительно. Если кому-то нужна совместимость с более старой версией 1.4.x - пишите, сделаю. С 1.3.x и старше связываться не буду, ими пусть занимаются историки Должно работать в режиме как клиента, так и сервера (ключ -server). Главный класс - ValidatorMain, ожидает два параметра: имя и ключ. Для проверки можно использовать пару Stiver и 161052, то есть вызвать java ValidatorMain Stiver 161052 Если ключ подходит к имени, должно появиться сообщение "Validation successful!". В противном случае программа просто молча завершится. P.S. Некоторое время пытался понять, в какой раздел форума нужно постить crackme. Нельзя ли где-нибудь (в правилах например) поместить соответствующее указание? Сейчас они примерно равномерно рассеяны почти по всем подфорумам. 95d1_20.06.2006_CRACKLAB.rU.tgz - java_crackme.zip |
|
Создано: 20 июня 2006 22:02 · Личное сообщение · #2 BSL//ZcS 380000 ключ + сумма кодов букв имени в кубе должны делиться на 11 имхо, селфмод на жабе - вещь на практике малоприменимая. хотя бы потому, что jit-компиляция его внятно не жрёт. например, поставь три вызова твоего патченного метода подряд, и позапускай с ключом -XX:CompileThreshold=2 и без него. |
|
Создано: 21 июня 2006 16:53 · Личное сообщение · #3 BSL//ZcS BSL//ZcS 380000 ключ + сумма кодов букв имени в кубе должны делиться на 11 Замечательно например, поставь три вызова твоего патченного метода подряд, и позапускай с ключом -XX:CompileThreshold=2 и без него. Если просто вызовы, то все будет нормально. Ты наверное имеешь в виду изменение байт-кода после того, как по нему прошелся JIT компилятор? Тогда нужно в структуре функции просто обнулять указатель на native code и компилятор переведет ее заново. Я это делать поленился, так как вызов всего один. Посмотри пример в аттаче, он будет давать правильный результат для любого значения CompileThreshold. По крайней мере для любого >1, с ключом -XX:CompileThreshold=1 конца компиляции я так и не дождался 73c6_21.06.2006_CRACKLAB.rU.tgz - test_CompileThreshold.zip |
|
Создано: 21 июня 2006 18:33 · Личное сообщение · #4 |
|
Создано: 21 июня 2006 19:59 · Личное сообщение · #5 wormking хм, а смысл использовать что-то, что может перестать работать. Сложный вопрос, попробуй задать его читателям(и писателям) различных книг и статей типа "Undocumented Windows". Ведь тоже никакой гарантии, что в следующей версии Windows или даже после следующего Service Pack'a все точно так же работать будет. |
|
Создано: 21 июня 2006 20:20 · Личное сообщение · #6 Stiver Ты наверное имеешь в виду изменение байт-кода после того, как по нему прошелся JIT компилятор? вообще-то, я имел в виду другое. в самом твоём крякми модифицируемый метод после компиляции перестаёт отрабатывать как должен. особо я с этим не разбирался. может это, конечно, из-за того, что я криво патчил. хотя я вроде несколькими способами делал, с одинаковым результатом. в общем, попробуй то, что я написал, на своём крякми. Тогда нужно в структуре функции просто обнулять указатель на native code и компилятор переведет ее заново. А если этот метод заинлайнен где-нить в другом месте? Опять же, с исконно жабьей кросс-платформенностью проблемы. Как я понимаю, на машинах с другим размером слова или порядком байт этот код работать не будет. с ключом -XX:CompileThreshold=1 конца компиляции я так и не дождался по-моему оно вообще так не компилирует, а намертво зацикливается. во всяком случае, по ключу -XX:+PrintCompilation оно ни одного скомпилированного метода не сообщает. |
|
Создано: 22 июня 2006 18:38 · Личное сообщение · #7 BSL//ZcS в самом твоём крякми модифицируемый метод после компиляции перестаёт отрабатывать как должен. Конечно перестает, ведь я заменяю edtb() на Math.pow(), а при компиляции он снова берет "правильную" edtb. Поэтому при нескольких вызовах надо сбрасывать результаты компиляции. Посмотри переделанный crackme в аттаче, там я вставил 5 вызовов в цикле и они дают правильный результат для любого CompileThreshold благодаря
Счетчик вызовов лучше тоже обнулять, чтобы не создавать противоречивых данных. Кстати серверная VM интерпретирует CompileThreshold как ей бог на душу положит, чаще всего просто игнорирует. А если этот метод заинлайнен где-нить в другом месте? Точно, такое может случиться, тогда в этом месте будет вызываться старая версия. Правда это может произойти только с очень маленькими функциями (граница по умолчанию вроде около 36 байт была) или если кто-то вручную -XX:MaxInlineSize увеличит. Опять же, с исконно жабьей кросс-платформенностью проблемы. Как я понимаю, на машинах с другим размером слова или порядком байт этот код работать не будет. Да нет, думаю при желании можно и так написать, что везде работать будет. Размер адреса получим через Unsafe.addressSize(), порядок байт можно вычислить, если надо. Хотя вряд ли надо, все putXXX и getXXX и так работают независимо от порядка. 7096_22.06.2006_CRACKLAB.rU.tgz - java_crackme_5.zip |
|
Создано: 23 июня 2006 12:29 · Личное сообщение · #8 Stiver я заменяю edtb() на Math.pow(), а при компиляции он снова берет "правильную" edtb. примерно это я и имел в виду, когда говорил, что компиляция селфмод внятно не жрёт. при нескольких вызовах надо сбрасывать результаты компиляции. кстати, а куда девается память, в которой они находятся? течёт, видимо? я вставил 5 вызовов в цикле и они дают правильный результат если модифицированный код нельзя вызывать без специальных ухищрений - это весьма существенное ограничение. теряется возможность формировать код, вызываемый из других мест, например из библиотек. может, можно сделать выносной механизм, который бы чистил те поля вызвавшему его методу, и впатчивать его вызов в начало каждого метода, вызываемого извне? хотя, конечно, тормозить это будет непомерно. да и место дополнительное искать под это придётся. это может произойти только с очень маленькими функциями (граница по умолчанию вроде около 36 байт была) ну, это достаточно распространённый вариант. на жабе традиционно используется масса всяких мелких методов. те же аксессоры... все putXXX и getXXX и так работают независимо от порядка я не знаю как именно ведут себя эти методы, отражают они всегда жабий порядок байт или пользуют системный, но один из вариантов использования с другим порядком, видимо, будет неправильным. либо ксорка, либо адресная арифметика, судя по всему, отвалится. |
|
Создано: 23 июня 2006 18:24 · Личное сообщение · #9 Stiver ~/java_crackme> java ValidatorMain Stiver 161052 # # An unexpected error has been detected by HotSpot Virtual Machine: # # SIGSEGV (0xb) at pc=0xfe6a7568, pid=22326, tid=1 # # Java VM: Java HotSpot(TM) Server VM (1.5.0_04-b05 mixed mode) # Problematic frame: # V [libjvm.so+0x6a7568] # # An error report file with more information is saved as hs_err_pid22326.log # # If you would like to submit a bug report, please visit: # java.sun.com/webapps/bugreport/crash.jsp # Abort (core dumped) |
|
Создано: 24 июня 2006 10:24 · Поправил: Stiver · Личное сообщение · #10 BSL//ZcS кстати, а куда девается память, в которой они находятся? течёт, видимо? Хм, хороший вопрос, не задумывался. Наверное действительно течет. Беда в том, что проверить сложно, но я попробую. Правда на фоне тех сотен мегабайт, которые Ява и так берет и не отдает, эта пара килобайт особо погоды не делает. если модифицированный код нельзя вызывать без специальных ухищрений - это весьма существенное ограничение. Погоди, мы здесь имеем дело с двумя совершенно разными манипуляциями. Первое - изменение байт-кода (там где ксорится). При вызове измененного кода никаких ухищрений не надо, один раз изменил и вызывай как хочешь, смотри пример в моем втором посте. Второе - перенаправление функции (edtb() на Math.pow()). Тут я код не трогаю, а заменяю указатель в кэше методов. При компиляции этот кэш высчитывается заново, отсюда и необходимость сброса компиляции при вызове. Опять же я не настаиваю, что этот способ замены функции единственно правильный вполне могут быть и другие, более универсальные. Моей целью было в том числе и подтолкнуть народ к их поискам, но похоже здесь Явой мало кто занимается, оставили тебя одного ветерана за всех отдуваться ;) либо ксорка, либо адресная арифметика, судя по всему, отвалится Адресная арифметика будет работать всегда, так как getAddress и остальные учитывают системный порядок байт. XOR тоже будет работать всегда, если читать и ксорить побайтово (то есть через getByte, а не getAddress), так как байт-код хранится независимо от системы в big-endian формате. ssx А можно уточнить операционную систему? Судя по libjvm.so какой-то Unix или Solaris? |
|
Создано: 24 июня 2006 21:49 · Личное сообщение · #11 |
|
Создано: 25 июня 2006 22:54 · Личное сообщение · #12 |
eXeL@B —› Крэки, обсуждения —› Java crackme / proof of concept |