· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.UNIX —› Кто тут крутой? Неплохой тест для вас!

<< . 1 . 2 . 3 . >>

Посл.отвђт Сообщенiе


Дата: Апр 16, 2004 03:00:31

volodya

Лестно :-) Осталось только учредить компанию.
А имел ли право компилятор так поступать, можно развить дискуссию. Только дождемся вечера 8-)


Дата: Апр 16, 2004 03:14:18

ушло минут 20, хотя можно быстрее,
(см reversing :) )

зато разобрал все :)


Дата: Апр 16, 2004 06:20:46

Funbit

В разборе есть ошибки. См. письмо. В главном не ошибся, в мелочах напортачил.


Дата: Апр 16, 2004 11:56:00

2Володя:
хм. на реверсинге у RElf'a, такая же как и у меня точка зрения по поводу начала for(;;). Один в один.
(он на пару команд выше, чем то, где идет непосредственный loop)


Дата: Апр 16, 2004 17:14:34

volodya
исправился :)


Дата: Апр 16, 2004 18:09:30

Ну что ж. Коль я открыл эту тему, то и время собирать камни. Итак.
Народу участвовало много и мне очень приятно, что заинтересовалось столь большое количество людей. Отдельное спасибо dragon.
Самый лучший результат (со слов, понятное дело, однако я склонен доверять этим словам) показал Harmer - 3 минуты. Потом Relf - 4 минуты на полное реверсирование. (это ребята с reversing.net - старый сайт и сильные участники).

Все остальные уложились минут в 15-20 на причину + еще минут 15 на полное реверсирование, включая определение границ for(;;). Однако в последнем случае мнения всех разошлись. Сразу скажу, что с Relf я не согласен.

Начнем с начала :)
Все участники асболютно правы, называя причиной

tmp = tmp->next

Ассемблерная строчка находится примерно за 3 секунды. Причина сбоя - память не доступна для чтения. Процесс соотнесения ассемблерного кода с сишной строчкой у каждого участника занял разное количество времени. Теперь давайте посмотрим на границы for(;;). Еще раз взглянем на сишный код:
for (;;) 
{
   break;
   continue;
   continue;
   continue;
   continue;
   continue;
   return;  //#1
}
return;  //#2


Видно, что есть один-единственный break, тут же выбрасывающий нас из for(;;) прямо на return #2. Если внимательно посмотреть ассемблерный код, видно, что на роль этого break тянет ТОЛЬКО ОДИН jcc -
c015b787:	0f 84 a1 00 00 00    	je     c015b82e <d_lookup+0x10e>


(кстати, до него есть js, но он никаким боком к for(;;) не относится - система многопроцессорная, поэтому это spin_lock).
Итак, с break мы определились. Но есть еще одна вещь. Рассмотрим все continue.
c015b79a:	0f 85 82 00 00 00    	jne    c015b822 <d_lookup+0x102>

c015b7a7:	75 79                	jne    c015b822 <d_lookup+0x102>

c015b7ce:	eb 52                	jmp    c015b822 <d_lookup+0x102>

c015b7d7:	75 49                	jne    c015b822 <d_lookup+0x102>

c015b7ef:	75 31                	jne    c015b822 <d_lookup+0x102>

c015b822:	3b 2c 24             	cmp    (%esp,1),%ebp
c015b825:	8d 5d f0             	lea    0xfffffff0(%ebp),%ebx
c015b828:	0f 85 62 ff ff ff    	jne    c015b790 <d_lookup+0x70>


Т.е. видно, что имеем пять переходов к одной метке, и jne на этой метке и ведет НА НАЧАЛО for(;;). Следовательно, for(;;) начинается с c015b790, а вовсе не с c015b782, как утверждает (хе, ну, сами знаете кто утверждает).

Как это выглядит на уровне C-кода? А вот тут уже непоняток чуть больше. Очевидно,
struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);


более не располагается на должном месте, она была перенесена. Далее, if (tmp==head) break, вероятно, ВСТРЕЧАЕТСЯ ДВАЖДЫ:
c015b782: 39 d5 cmp %edx,%ebp
c015b784: 8d 5d f0 lea 0xfffffff0(%ebp),%ebx


и тут:
c015b822: 3b 2c 24 cmp (%esp,1),%ebp
c015b825: 8d 5d f0 lea 0xfffffff0(%ebp),%ebx
c015b828: 0f 85 62 ff ff ff jne c015b790 <d_lookup+0x70>


Теперь прерываюсь на какое-то время и жду пинков в свой адрес или посыпаний головы пеплом :)


Дата: Апр 16, 2004 18:38:57

Дождались разрешения, можно писать :)

struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);

По моему скромному и наверняка ошибочному мнению, struct dentry не может быть переменной, а может быть только типом данных. Значит, list_entry не может быть функцией, зато вполне может быть макросом. А что делает этот макрос, никто не знает, поэтому при неполном анализе его можно игнорировать :)

Что же касается полного анализа, на него я забил еще в самом начале, когда увидел shr $0x5,%edx. Да и обилие глобальных переменных меня тоже сильно смутило - в сишном коде я смог заметить только одну, а в асмовом штук пять.

P.S. Сорри, что не подписал письмо с результатом - так "разогнался", что даже при написании письма торопился, и даже оговорок в письме наделал - пришлось еще одно письмо вдогонку отправлять :-D


Дата: Апр 16, 2004 18:43:05

гм... перечитал еще раз "окончательный результат", и понял, что я ни при анализе не заметил, ни сейчас не могу понять, откуда известно, что "память недоступна для чтения"?

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


Дата: Апр 16, 2004 18:54:03

А что делает этот макрос, никто не знает

Ехали-ехали, приехали :)
#define list_entry(ptr, type, member) \
  ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))



Дата: Апр 16, 2004 19:29:21

Вот теперь посыпаю голову пеплом :(
Зря я слово "никто" написал. Я не знаю. Что, кстати, мне не сильно помешало в данной задаче :)

Да, вот только я сделал поиск по vc98\include и по Microsoft SDK\include - они тоже не знают...
Сделал поиск в /usr/include, потом в / - тоже пусто. Ну, не совсем пусто, часто встречаются вещи типа list_entry le, но это явно не то. Поискал в ISO-стандартах C и C++ - тоже нет таких вещей.

То ли я искать не умею, то ли это не такая уж и элементарная вещь... Скажи хоть, что цитируешь?

P.S. Кстати, если посмотреть на твой макрос, то можно сделать вывод, что это и есть та штуковина, которая встречается дважды, а именно lea 0xfffffff0(%ebp),%ebx.


Дата: Апр 16, 2004 19:33:58

Цитирую я сорцы ядра Linux как легко догадаться, глядя на дамп.

У меня вопрос к аудитории. Господа, порча поинтера отнюдь не тривиальна. Простой проверкой, типа if(tmp) tmp = tmp->next или еще как-нибудь в этом же духе тут явно не обойтись :) Мне вот очень любопытно было бы обсудить возможные меры противодействия и возможные меры отладки.
В винде есть IsBadxxxPtr, что хорошо. Есть Soft-Ice с его bpm, которую можно поставить на этот поинтер и, потеряв пару дней, разобраться, кто его нагло перетирает и почему так, а вот как это дело можно подолбать в линуксе?
Вводить нечто вроде CRC в структуры?


Дата: Апр 16, 2004 20:27:19

хотел бы немножко поспорить с началом цикла for(;;)

мой вариант, c015b782, который признался неверным :)

хочу отметить, что адрес этот я написал с сознанием того, что сам цикл (именно луп кусок) начинался с c015b790. дело в том, что все равно ведь этот кусок относится к for циклу, т.к. если мы гипотетически уберем его из С исходника и скомпилируем, то получим тот же asm код (если конечно компилятор не выкинет часть из-за оптимизаций..), кроме куска:
c015b782-c015b82e (с нижним краем могу ошибаться..)

ну, в общем, вы меня поняли :)


Дата: Апр 16, 2004 20:29:04

Еще раз повторяю, что я не могу что-то признать или не признать верным или неверным. Просто потому, что точного ответа не имею и сам. Я могу ПОЛАГАТЬ с той или иной степенью уверенности. :)


Дата: Апр 16, 2004 20:49:04

возлагаем это на работодателя :)
что, кстати, он думает по этому поводу ? :)


Дата: Апр 16, 2004 20:51:35

Хе, ты что, подумал, что это я на работу нанимаюсь?
На хрен мне это не надо сейчас. Во-первых, есть у меня уже работа, а во вторых, хочу вообще не работать :)))

<< . 1 . 2 . 3 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.046