Сейчас на форуме: zds, tyns777, JustLife, 2nd, morgot, Rio, CDK123 (+4 невидимых)

 eXeL@B —› Программирование —› Программно отличить реальный код от мусора, как?
<< . 1 . 2 .
Посл.ответ Сообщение

Ранг: 28.1 (посетитель)
Активность: 0.010
Статус: Участник

Создано: 25 декабря 2008 14:59
· Личное сообщение · #1

Доброе время!

Вот такой сабжевый вопрос назрел собственно.

К примеру - процедура поксорена одним значением, и чтобы подобрать это значение, нужно как-то идентифицироать "хороший" код от мусора.

Может, что посоветуете?

Спасибо.

Правда, сомневаюсь в существовании каких-либо эффективных методов




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 26 декабря 2008 17:30
· Личное сообщение · #2

Что-то тут стали очень активно говорить про брут закриптованного простым ксором кода, а также про то, что лучший способ проверить, расшифрован он или нет - это запустить его. Это фигня, т.к. до того, как можно будет получить такой код, который бы работал, придётся много раз получать тот, который работать не будет, а будет генерировать исключения, да подчас такие, что никакие сехи и вехи не спасут прогу, более того, в случае неправильной расшифровки нужно будет код опять менять на первоначальный, и такой брут займёт много времени. Не думаю, что это реально, но всё зависит, от размера закриптованного кода. Плюс при многократном выполнении есть вероятность повредить встроенный в процесс брутфорсер, испортить данные, с которыми программа должна работать, и тогда можно получить исключение даже в нормально расшифрованном коде, так что это мечты.

-----
Stuck to the plan, always think that we would stand up, never ran.





Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 26 декабря 2008 17:36
· Личное сообщение · #3

Еще один демон. А кто говорил про запуск кода? я говорил про дизасм длин.

-----
have a nice day





Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 26 декабря 2008 17:43
· Личное сообщение · #4

rep0A пишет:
Поксореный код отличается от мусора тем что он запускается =)
Как вариант попробовать эту функу просто позапускать, если знаешь аргументы.

Nimnul
Вот кто говорил про запуск.
А дизасм длин - ну и что? Толку-то с него? Будем раскриптовывать код и смотреть на длину команд, и что это даст?

-----
Stuck to the plan, always think that we would stand up, never ran.





Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 26 декабря 2008 17:49 · Поправил: Nimnul
· Личное сообщение · #5

там же стоит смайлик, воспринимается как шутка. А дизасм длин даст валидность кода. если там 1 1 1 1 1 то фтопку ;). если в коде ниразу не встретился выход или условие (а там всяко условие должно быть), тогда не валидный, и вобще может мне весь алго здесь написать

-----
have a nice day





Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 26 декабря 2008 17:53
· Личное сообщение · #6

Nimnul
На шутку мало похоже, он, походу, серьёзно. А про валидность длин - если только код Визуал Сишный, то ещё ладно, да и то если реализован через асемблерные вставки или не stdcall соглашением о вызовах, то 11111 ещё ничего не значит - это мечта так мусор анализировать.

-----
Stuck to the plan, always think that we would stand up, never ran.





Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 26 декабря 2008 17:56
· Личное сообщение · #7

ага покажи мне валидный код где встречается пять команд подряд с длиной 1.

-----
have a nice day





Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 26 декабря 2008 18:30
· Личное сообщение · #8

Nimnul
Я тебе с одним только инкрементом могу их тьму написать, это при том, что остальные,типа nop и прочей бесполезности применяться не будут.

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: 101.0 (ветеран), 344thx
Активность: 1.150
Статус: Участник

Создано: 26 декабря 2008 19:22
· Личное сообщение · #9

Nimnul пишет:
ага покажи мне валидный код где встречается пять команд подряд с длиной 1

Code:
  1. push ebx
  2. push ecx
  3. push edx
  4. push edi
  5. push esi






Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 26 декабря 2008 19:29
· Личное сообщение · #10

progopis
+1
Nimnul
А даже если и так, представим, что нету таких пяти однобайтовых команд, ну, вот возбмём и представим. Что толку, есть валидные двухбайтовые, трёхбайтовые рядом стоящие. Короче, этот твой метод можно засунуть в и повернуть там два раза, извини, что так резко, но эта чушь мне уже надоела

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: 101.0 (ветеран), 344thx
Активность: 1.150
Статус: Участник

Создано: 26 декабря 2008 19:43 · Поправил: progopis
· Личное сообщение · #11

Блин и никто не заметил:
temp пишет:
длина ключа на самом деле = DWORD = 64 бит


DWORD=32 бит, ну так, если что...

temp пишет:
не миллионы, а ~50 суток, на одной машине

Какой молодец! Как же ты подсчитал, если у тебя даже алго ещё нет для определения валидности кода (а это и будет самая по времени)? На счёт моего предложения: "выклянчивать помощь не в моих правилах" - я тебе её сам предлагаю, это раз. Второе: выклянчивание - это соседний топик (запросы на взлом). Я тебе просто ключ предлагал приобрести.
P.S. Без обид.



Ранг: 28.1 (посетитель)
Активность: 0.010
Статус: Участник

Создано: 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. Без обид.


да какие такие обиды




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 26 декабря 2008 20:26
· Личное сообщение · #13

temp
1 милисекунда? А чё прям уж так долго-то?

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: 28.1 (посетитель)
Активность: 0.010
Статус: Участник

Создано: 26 декабря 2008 20:30 · Поправил: temp
· Личное сообщение · #14

ARCHANGEL пишет:
1 милисекунда? А чё прям уж так долго-то?


ну эт конечно грубовато, но лучше сразу быть готовым к худшему варианту
ведь декрипт+дизасм+фильтр-отсеиватель будет нехило тормозить перебор, да еще и в зависимости от длины процедуры будет меняться скорость




Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 27 декабря 2008 01:28
· Личное сообщение · #15

ARCHANGEL пишет:
А даже если и так, представим, что нету таких пяти однобайтовых команд, ну, вот возбмём и представим. Что толку, есть валидные двухбайтовые, трёхбайтовые рядом стоящие. Короче, этот твой метод можно засунуть в и повернуть там два раза, извини, что так резко, но эта чушь мне уже надоела



Сначало пропусти дизасм на испорченном коде, посмотри на него, а потом включи образное мышление ;). Надоело тебя никто не просит свой песемизм растряхивать на окружающих. Если мне надо будет, я смогу написать алго, который будет проверять на валидность код. И основываться этот алго будет на дизасме длин. Самое простое дизасм может не войти в те байты, которые отведены функции и если он подумает, что 0xCC или 0x00 (которые обычно идут сразу за ret что впрочем не важно) входят в последнюю команду, значит валидацию не прошел. Этот метод отсеет 80% остальное отсеят другие методы. Если тебе не дано это осилить, не надо говорить что тебе это надоело, иди четай ксакеп, там много инфы для тебя.

-----
have a nice day




Ранг: 101.0 (ветеран), 344thx
Активность: 1.150
Статус: Участник

Создано: 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:
  1. Call 0FD89AC12h; ни разу не валидный адрес
  2. JMP 0F23h; тоже не очень





Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 27 декабря 2008 14:50
· Личное сообщение · #17

progopis пишет:
Ловить конец такого кода бесполезно. За ret'ом имею полное право ставить что хочу.


Найти длину зашифрованной функции можно в отладке, скормив проге не правильный код, она будет пытаться расшифровывать функцию определенной длинны... Кроме того как прога сама определяет правильный ключ или нет? Не думаю что она тупо расшифровывает и запускает, ибо может легко упасть. Значит есть какая то сигнатура или контрольная сумма, она где то храниться, здесь и есть ключ к победе.

-----
have a nice day




Ранг: 222.2 (наставник), 115thx
Активность: 0.140.01
Статус: Участник

Создано: 27 декабря 2008 15:22
· Личное сообщение · #18

Nimnul пишет:
Не думаю что она тупо расшифровывает и запускает, ибо может легко упасть. Значит есть какая то сигнатура или контрольная сумма, она где то храниться, здесь и есть ключ к победе.

а почему бы через SEH не отлавить момент падения и не подменить данные на какое-нить гавно? я бы так и сделал

-----
все багрепорты - в личные сообщения




Ранг: 28.1 (посетитель)
Активность: 0.010
Статус: Участник

Создано: 27 декабря 2008 15:28
· Личное сообщение · #19

Nimnul пишет:
Не думаю что она тупо расшифровывает и запускает


В моем случае именно тупая расшифровка



Ранг: 284.8 (наставник), 6thx
Активность: 0.150
Статус: Участник

Создано: 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

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




Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 27 декабря 2008 16:50 · Поправил: Nimnul
· Личное сообщение · #21

HandMill

А прога может не упасть на исключении. представь если будет что то вроде push xxxx; ret где адрес xxxx функции удаления ветки реестра или файла. За такое на западе подадут в суд. Прикольно юзер ошибся при вводе ключа и прога падает с исключением или удаляет ветку реестра, или циклится на какой нибудь шняге. Поэтому имхо разработчики прота, этого не могли допустить, а значит в проте предусмотрен метод валидации расшифрованного кода, его и нужно реверсить, а потом брут с этим методом.

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

-----
have a nice day




Ранг: 101.0 (ветеран), 344thx
Активность: 1.150
Статус: Участник

Создано: 27 декабря 2008 17:46 · Поправил: progopis
· Личное сообщение · #22

Nimnul пишет:
пытаться расшифровывать функцию определенной длинны...

Ещё раз говорю - после ret'а могу оставить любое гов*о. Раскриптовывать буду кусок чего-то. Не давая реверсеру понять, какая длина. Вот например раскриптованный текст:
Code:
  1. mov     eax, [esi+30h]
  2. push    edi
  3. mov     edi, [esi+34h]
  4. add     eax, eax
  5. add     eax, eax
  6. push    eax
  7. push    0
  8. push    edi
  9. call    _memset
  10. push    edi
  11. call    j_j__free
  12. mov     ecx, [esi+1Ch]
  13. mov     edi, [esi+20h]
  14. add     ecx, ecx
  15. add     ecx, ecx
  16. ...
  17. push    edi
  18. call    j_j__free
  19. ...
  20. add     edx, edx
  21. push    edx
  22. push    0
  23. push    edi
  24. call    _memset
  25. push    edi
  26. call    j_j__free
  27. add     esp, 30h
  28. mov     eax, esi
  29. pop     edi
  30. retn
  31. db 45h
  32. db 0F2h
  33. db 0xCCh

Ну как? Пример кода - вполне реальный. Мой способ определением leave/retn, push XXX/pop XXX тоже идёт лесом. Только если байты 5x, 6A YY (КОПы push'ей перед call'ами) искать подряд идущие.

Короче по ходу надо крекми писать - посмотрим как ты его ломанёшь... Нет, я не пытаюсь вызов сделать ("Ну докажи что ты реально крут, парень!"), просто, видимо, на словах сложно объяснить что я имею в виду.

Nimnul пишет:
Значит есть какая то сигнатура или контрольная сумма

А вот это +1. Если прогер не дурак - проверка должна быть. Но опять же я это могу обойти - проверять буду большой ключ и его CRC, а уже из него делать ключ для дешифровки. Вряд ли пользователь угадает ключ, а на реверсера мне пофиг - пусть у него всё вылеатает...




Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 27 декабря 2008 18:00 · Поправил: Nimnul
· Личное сообщение · #23

progopis пишет:
Не давая реверсеру понять, какая длина.


Ты читал не внимательно длинну функции мы узнаем точно не по коду а по буферу который должен быть расшифрован.
Я согласен с тобой, что закинули мусор в конец и писец. Тема конечно интересная, но я не буду думать за других. пусть temp придумывает алго, это его тема. но заметь если в функции нет ни одной команды выхода (ret, call, jmp), тогда функция не валидная, если придумать два десяка таких проверок, тогда я думаю можно из всех возможных вариантов отсеять 99.99%. останется пара десятков, которые можно глазом пробежать и все будет ясно.

А теперь посмотри на реальный мусор, неужели сразу не видишь, как его отсеить.
Code:
  1.  FF                           ???
  2.  D8FF                         fdivr       st(0),st(7)
  3.  E000                         loopne      000000005 --&#8595;1
  4.  104A46                      1adc         [edx][46],cl
  5.  49                           dec         ecx
  6.  46                           inc         esi
  7.  0001                         add         [ecx],al
  8.  0101                         add         [ecx],eax
  9.  006000                       add         [eax][00],ah
  10.  60                           pushad
  11.  0000                         add         [eax],al
  12.  FFE1                         jmp         ecx
  13.  3A4245                       cmp         al,[edx][45]
  14.  7869                         js          000000084 --&#8595;2
  15.  660000                       add         [eax],al
  16.  49                           dec         ecx
  17.  49                           dec         ecx
  18.  2A00                         sub         al,[eax]
  19.  0800                         or          [eax],al
  20.  0000                         add         [eax],al
  21.  1200                         adc         al,[eax]
  22.  0E                           push        cs
  23.  0102                         add         [edx],eax


-----
have a nice day




Ранг: 101.0 (ветеран), 344thx
Активность: 1.150
Статус: Участник

Создано: 27 декабря 2008 18:02 · Поправил: progopis
· Личное сообщение · #24

Nimnul
Я-то вижу. Надо алго написать, который видит

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

И кстати не всегда есть ret в функциях (хотя это не противоречит тому, что ты сказал)... Пример:
Code:
  1. mov     ecx, [ecx+14h]
  2. mov     eax, [ecx]
  3. mov     eax, [eax+30h]
  4. jmp     eax

Demon666
+1



Ранг: 213.5 (наставник)
Активность: 0.120
Статус: Участник
забанен

Создано: 27 декабря 2008 18:15
· Личное сообщение · #25

progopis пишет:
Короче по ходу надо крекми писать - посмотрим как ты его ломанёшь...

Гы, да че его писать - он давно написан ;)
Второй эбайт у TEplus в моем плуге
Там ксорится 20 байт двордом(хеш от ключа)
Если ключа в ини-файле нет то и расшифровки не будет ;) только функционал плуга порезан будет, гы-гы
Попробуйте сбрутить кодес(20 байт валидного кода) чтоле, ну естественно только по-честному;)
Не смотря на решения которые там выложили, уровень срякми там низкий ;))
http://exelab.ru/f/action=vthread&forum=12&topic=12567

Проще скардить и "если есть привязка" сделать копипаст кода и неипаццо!!!
Тобишшш
progopis пишет:
Если что, скардить можно будет, а всякие там бруты по миллионы лет - не наш метод.

+1

-----
ЗЫ: истЕна где-то рядом, Welcome@Google.com





Ранг: 218.9 (наставник), 42thx
Активность: 0.160
Статус: Участник
dotnet

Создано: 27 декабря 2008 18:50 · Поправил: Nimnul
· Личное сообщение · #26

progopis пишет:
И кстати не всегда есть ret в функциях

Nimnul пишет:
нет ни одной команды выхода (ret, call, jmp)


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

Nimnul пишет:
Я согласен с тобой, что закинули мусор в конец и писец.


progopis пишет:
Я-то вижу. Надо алго написать, который видит


Если видишь значит алго написать возможно.

-----
have a nice day



<< . 1 . 2 .
 eXeL@B —› Программирование —› Программно отличить реальный код от мусора, как?
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати