eXeL@B —› Основной форум —› Transmission Control Block(TCB) формат |
Посл.ответ | Сообщение |
|
Создано: 08 августа 2011 15:20 · Поправил: DenCoder · Личное сообщение · #1 Не первый раз исследую крэш-дамп, вызванный в tcpip.sys. Но на этот раз основательно (т.к. баги с консолями пока заснули ). Оказывается, многим обладателям различных версий WinXP SP3 x86 известен такой баг как tcpip!ReadNextTCB + 0xd2, гугл выдаёт сотни форумов с такими дампами. Исходя из названия функции очевидно, что ф-ция читает некие блоки TCB, имеющие определённую структуру. Но самого описания структуры под таким названием я нигде не нашёл. До чего удалось самому догадаться 1) Code:
Начало чем-то похоже на TDI_PNP_CONTEXT: Code:
Но второе слово, равное 5 выходит за рамки enum TDI_PNP. Значит либо не описанный тип контекста, либо структура другая 2) После ReadNextTCB идёт вызов CopyFlatToNdis->TdiCopyBufferToMdl Code:
SourceBuffer как раз указывает на TCB. Информация по функции есть в WDK, но опять ничего про TCB. На xakep.ru гугл нашёл всего одну страницу по возможному описанию TCB, но отображать её не хочет. ----- IZ.RU |
|
Создано: 08 августа 2011 15:31 · Личное сообщение · #2 |
|
Создано: 08 августа 2011 16:37 · Поправил: DenCoder · Личное сообщение · #3 Code:
RFC793: A transmission control block (TCB) is created and partially filled in with data from the OPEN command parameters. yanus0, спасибо! Но, блин, саму структуру нигде не хотят описывать И даже ида не знает... Может имеет какое-то другое название? RFC2140 уже более конкретно что-то даёт: Code:
rfc675: Code:
..... Ааа, кажется, понял: TdiCopyBufferToMdl уже копирует распарсенный TCB, указатель на который принимает ReadNextTCB вторым аргументом. Сама TCB заключена внутри некоего контейнера, который передаётся первым аргументом... Буду дальше реверсить... Ничего похожего, по крайней мере, в порядке, в каком указано в rfc675, не нашёл. Возникают вопросы: что за распарсенная структура вида как в первом посте? Что за контейнер? Следующее, что я обнаружил: указатель на некую структуру содержится в pContainer->pStruct->pNext [[Arg1 + 8]] так перечисляются все структуры, пока не нуль но если нуль, то берётся переменная _TWTCBTable, о которой можно найти только на Неужели никто больше не проводил исследования в этой области? Что внутри tcpip.sys, известно только m$ и не публикующимся исследователям? Ну да ладно. _TWTCBTable что-то вроде списка списков TCB с головой, который у меня на момент креша оказался пустым, т.е. указывал только на себя. Используется он, только если пакетов в очереди, чем 512... У меня на момент креша было 223 пакета в очереди... Все списки TCB можно перечислить по переменной TCB* _TCBTable[]. TCB отличается от структуры в первом посте и имеет примерно такую структуру: Code:
* - название условно, может измениться Из дампа видно, что сами структуры могут повторять информацию о соединении, так что возможно присутствует и информация о самом трафике... Подхожу к логическому концу: к бсоду мой комп привело непонятное стечение обстоятельств, из-за которых в одной из структур TCB по смещению 0xC8 нулевой указатель. То ли не заполнилось поле в следствие непродуманности алгоритма, то ли обнулилось, может следствие плохой синхронизации... гадать можно долго... Структура выше получается из массива по адресу [[[pTCB + 0xC8] + 0x0C] + 0x160] Код, приведший к бсоду Code:
----- IZ.RU |
|
Создано: 08 августа 2011 18:23 · Поправил: OKOB · Личное сообщение · #4 Есть только такая шняга из ReactOS TCP/IP protocol driver /* Transport connection context structure A.K.A. Transmission Control Block (TCB) in TCP terminology. The FileObject->FsContext2 field holds a pointer to this structure */ typedef struct _CONNECTION_ENDPOINT { LIST_ENTRY ListEntry; /* Entry on list */ LIST_ENTRY AddrFileEntry; /* Entry on address file list */ KSPIN_LOCK Lock; /* Spin lock to protect this structure */ ULONG RefCount; /* Number of references to this object */ PVOID ClientContext; /* Pointer to client context information */ PADDRESS_FILE AddressFile; /* Associated address file object (NULL if none) */ CONNECTION_STATE State; /* Connection state */ PIP_ADDRESS LocalAddress; /* Pointer to local IP address */ USHORT LocalPort; /* Local port number */ PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */ USHORT RemotePort; /* Remote port number */ /* Send sequence variables */ ULONG SendUnacknowledged; /* Highest sequence number that is acknowledged */ ULONG SendNext; /* Sequence number of last data block sent */ ULONG SendWindow; /* Maximum allowed number of octets in a segment */ ULONG SendUrgentPointer; /* Sequence number of start of urgent data */ ULONG SendWL1; /* Sequence number used for last window update */ ULONG SendWL2; /* Acknowledgment number used for last window update */ ULONG SendISS; /* Initial send sequence number */ /* Receive sequence variables */ ULONG RecvNext; /* Sequence number of last data block received */ ULONG RecvWindow; /* Maximum allowed number of octets in a segment */ ULONG RecvUrgentPointer; /* Sequence number of start of urgent data */ ULONG RecvIRS; /* Initial receive sequence number */ /* Statistics for computing the retransmission timeout */ ULONG TimestampSend; /* Timestamp when sending a segment */ ULONG TimestampAck; /* Timestamp when receiving acknowledgment */ } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT; ----- 127.0.0.1, sweet 127.0.0.1 |
|
Создано: 08 августа 2011 21:34 · Поправил: DenCoder · Личное сообщение · #5 Если это TCB, то тогда у меня ни одна из структур - не TCB Спасибо! Пойду посмотрю структуры на ReactOS... Самое интересное, что в ReadNextTCB ниже "бсодного" кода Code:
делается проверка Code:
то есть всё же m$ допускают, что [esi + 0xC8] может быть равно нулю Только совсем непонятна логика дальше Code:
Допустим в [esi + 0xC8] нуль и каким-то фантастическим образом миновали бсодный участок. Но чему будет при этом равен edx? Я скажу, что он будет равен 0xA8. Такое чувство, что вырезана/закомментирована часть кода. Причём m$ не смотрела её как минимум года 3. И весело и печально... ----- IZ.RU |
|
Создано: 08 августа 2011 22:29 · Личное сообщение · #6 |
|
Создано: 08 августа 2011 22:35 · Поправил: DenCoder · Личное сообщение · #7 reversecode пишет: но ниукого ничего не падает(вроде?) Хорошее обилие дампов? Не падает, если не мониторить. На WinXP используется TDI для этого, начиная с Висты используется уже другая технология. Хотя есть и те, у кого и без мониторинга падает... Вообще, проблема не в этой функции, не в ReadNextTcb. По смещению 0xC8 всё же не должно быть нуля... UPDATED. Читал, что на ReactOS, хоть они ковыряются в винде, но чтобы не вызвать возмущения, немного изменяют то, что на ковыряли. Поэтому, видать, не сходятся структуры. Вообще, то, что привёл OKOB с ReactOS не сходится с тем, что я скачал. Ну ладно, структуры в постах выше обновил тем, что ещё удалось наковырять. И новое: Code:
Эта структура передаётся в ReadNextTCB и ValidateTCBContext Code:
----- IZ.RU |
|
Создано: 09 августа 2011 16:11 · Поправил: reversecode · Личное сообщение · #8 по +С8 хранится Conn (Connection) заполняется _например_ от сюда TdiConnect Code:
берется от сюда GetConnFromConnID приблизительно так Code:
вообще начиная c разбора AllocTCB(), где этот TCB аллоцируется и заполняется , дальше все очень легко разбирается дальше если прыгать в каждую функцию которая вызывает этот AllocTCB | Сообщение посчитали полезным: DenCoder |
|
Создано: 09 августа 2011 17:11 · Поправил: DenCoder · Личное сообщение · #9 Да, верно. Только у меня смещение другое, но не столь важно... Спасибо ;) Значит, раз к моменту вызова ReadNextTCB уже есть IP-адреса и порты, но pTcb->pConn вдруг 0, то где-то между инициализацией и парсингом происходит обнуление... Может в TdiReceive или TdiSend? А может какой-то редкий протокол вмешивается в работу? Попробуем найти в стеке вызовов, но скорей всего вряд ли там можно найти - здесь пахнет, что из другого потока было изменение. Нечто вроде потери соединения в момент запроса информации о TCB... tcpip, кстати, несмотря на то, что он так назван обрабатывает ещё много протоколов, не связанных с IP... ----- IZ.RU |
|
Создано: 09 августа 2011 17:51 · Поправил: reversecode · Личное сообщение · #10 http://rghost.ru/17359841 (AllocTCB) есть в обеих вариантах pdb с M$ полистай IDA там есть места когда TCB алоцирует и добавляется в очередь(хеш), но не инициализирует C8h(conn) вообщем я как и всегда смотрю скептически на анализ такой проблемы без полного разбора tcpip.sys а разбирать его я особой выгоды не для кого не вижу ну получим мы к примеру tcpip.sys в исходниках, ....? найдем проблему, дальше нужно будет подписывать этот драйвер разве что результат продать разрабам ReactOS ;)) единственная польза, это разве что удовольствие от красоты архитектурной реализации tcpip.sys в майкрософте.. |
|
Создано: 09 августа 2011 18:06 · Поправил: DenCoder · Личное сообщение · #11 Да нашёл AllocTCB. Сразу же, просто у меня Code:
намного ниже от InitTCBFromConn, чем ожидал. reversecode пишет: а разбирать его я особой выгоды не для кого не вижу да, он огромен, и одному его практически не разобрать. Собственно, выгода - узнать причину краха и по возможности устранить. По крайней мере снизить риски порчи информации. Например, реверс с консолями помог снять "висячую" консоль. Кроме того, польза в понятии принципов работы сетевого стека ----- IZ.RU |
|
Создано: 09 августа 2011 18:11 · Поправил: reversecode · Личное сообщение · #12 DenCoder пишет: да, он огромен, и одному его практически не разобрать. 300 кил не много.. а причину краша может и не найдешь можно ведь только по одному трейсу выйти что там TdiQueryInformation вызывается а самого процесса прокрутки того что творилось с TCB нет add пример вызова чего либо по таймеру, где по таймеру к примеру функция меняет этот TCB стектрейса не будет, ничего в дампе не будет по этому поводу а потому уже где то когда то вызовется какой нибудь send() с userlevel и все упадет в прочтении TCB->Conn и вот такие моменты поиска кто кого где менял и почему, без реверса не обойтись |
|
Создано: 09 августа 2011 18:55 · Поправил: DenCoder · Личное сообщение · #13 1) можно старт всех потоков выяснить, кем были стартованы и для чего... 2) в самом tcpip обнаружить создание потоков 3) выявить все места по шаблонам mov [reg1 + 0xC8], reg2 mov [reg + 0xC8], 0 lea reg1, [reg2 + const] mov [reg1 + 0xC8 - const], 0 reversecode пишет: 300 кил ну я 7 лет назад хернёй страдал - просто копипастил из дизасма в блокнот, в день больше, чем 6 кб не получалось )) а тут ещё и реверсить... reversecode пишет: можно ведь только по одному трейсу выйти что там TdiQueryInformation вызывается ну не только вот стандартный трейс от WinDbg Code:
Но странно, что WinDbg не показывет дальше Code:
----- IZ.RU |
eXeL@B —› Основной форум —› Transmission Control Block(TCB) формат |