Сейчас на форуме: rmn, exp50848 (+7 невидимых)

 eXeL@B —› Основной форум —› Transmission Control Block(TCB) формат
Посл.ответ Сообщение


Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 08 августа 2011 15:20 · Поправил: DenCoder
· Личное сообщение · #1

Не первый раз исследую крэш-дамп, вызванный в tcpip.sys. Но на этот раз основательно (т.к. баги с консолями пока заснули ). Оказывается, многим обладателям различных версий WinXP SP3 x86 известен такой баг как tcpip!ReadNextTCB + 0xd2, гугл выдаёт сотни форумов с такими дампами. Исходя из названия функции очевидно, что ф-ция читает некие блоки TCB, имеющие определённую структуру. Но самого описания структуры под таким названием я нигде не нашёл.

До чего удалось самому догадаться
1)
Code:
  1. 00 A8 длина блока
  2. 04 05 ???
  3. 08 0100007F IpAddr1 127.0.0.1
  4. 0C 0000bb3A IpPort1 15035
  5. 10 0100007F IpAddr2 127.0.0.1
  6. 14 00008E77 IpPort2 30606 - порт http-фильтра NOD32
  7. 18 000008a8 ProcessId
  8. 1C 0334540f 00000000 00000000
  9. похоже на данные, только в странном формате
  10. 28 71a36a32 00000000
  11. 30 71a3542d 00000000
  12. 38 71a94a5a 00000000
  13. 40 67319fd7 00000000 
  14. ..................................


Начало чем-то похоже на TDI_PNP_CONTEXT:
Code:
  1. struct _TDI_PNP_CONTEXT {
  2.   USHORT  ContextSize;
  3.   USHORT  ContextType;
  4.   UCHAR  ContextData[1];
  5. } TDI_PNP_CONTEXT, *PTDI_PNP_CONTEXT;


Но второе слово, равное 5 выходит за рамки enum TDI_PNP. Значит либо не описанный тип контекста, либо структура другая

2) После ReadNextTCB идёт вызов CopyFlatToNdis->TdiCopyBufferToMdl
Code:
  1. NTSTATUS 
  2.   TdiCopyBufferToMdl(
  3.     IN PVOID  SourceBuffer,
  4.     IN ULONG  SourceOffset,
  5.     IN ULONG  SourceBytesToCopy,
  6.     IN PMDL  DestinationMdlChain,
  7.     IN ULONG  DestinationOffset,
  8.     IN PULONG  BytesCopied
  9.     );


SourceBuffer как раз указывает на TCB. Информация по функции есть в WDK, но опять ничего про TCB.

На xakep.ru гугл нашёл всего одну страницу по возможному описанию TCB, но отображать её не хочет.

-----
IZ.RU




Ранг: 137.9 (ветеран), 45thx
Активность: 0.080
Статус: Участник

Создано: 08 августа 2011 15:31
· Личное сообщение · #2

То что на хакере лежит --> Link <--




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 08 августа 2011 16:37 · Поправил: DenCoder
· Личное сообщение · #3

Code:
  1. LISTEN STATE
  2.  
  3.       Return "state = LISTEN", and the TCB pointer.
  4.  
  5.     SYN-SENT STATE
  6.  
  7.       Return "state = SYN-SENT", and the TCB pointer.
  8.  
  9.     SYN-RECEIVED STATE
  10.  
  11.       Return "state = SYN-RECEIVED", and the TCB pointer.
  12.  
  13.     ESTABLISHED STATE
  14.  
  15.       Return "state = ESTABLISHED", and the TCB pointer.
  16.  
  17.     FIN-WAIT-1 STATE
  18.  
  19.       Return "state = FIN-WAIT-1", and the TCB pointer.
  20.  
  21.     FIN-WAIT-2 STATE
  22.  
  23.       Return "state = FIN-WAIT-2", and the TCB pointer.
  24.  
  25.     CLOSE-WAIT STATE
  26.  
  27.       Return "state = CLOSE-WAIT", and the TCB pointer.
  28.  
  29.     CLOSING STATE
  30.  
  31.       Return "state = CLOSING", and the TCB pointer.
  32.  
  33.     LAST-ACK STATE
  34.  
  35.       Return "state = LAST-ACK", and the TCB pointer.


RFC793:
A transmission control block (TCB) is created and partially
filled in with data from the OPEN command parameters.


yanus0, спасибо! Но, блин, саму структуру нигде не хотят описывать И даже ида не знает... Может имеет какое-то другое название?

RFC2140 уже более конкретно что-то даёт:
Code:
  1. The TCB can be
  2.    summarized as containing [9]:
  3.  
  4.  
  5.         Local process state
  6.  
  7.             pointers to send and receive buffers
  8.             pointers to retransmission queue and current segment
  9.             pointers to Internet Protocol (IP) PCB
  10.  
  11.         Per-connection shared state
  12.  
  13.             macro-state
  14.  
  15.                 connection state
  16.                 timers
  17.                 flags
  18.                 local and remote host numbers and ports
  19.  
  20.             micro-state
  21.  
  22.                 send and receive window state (size*, current number)
  23.                 round-trip time and variance
  24.                 cong. window size*
  25.                 cong. window size threshold*
  26.                 max windows seen*
  27.                 MSS#
  28.                 round-trip time and variance#


rfc675:
Code:
  1. The TCB contains the following information (field sizes
  2.    are notional only and may vary from one implementation to another):
  3.  
  4.       16 bits: Local connection name
  5.       48 bits: Local socket
  6.       48 bits: Foreign socket
  7.       16 bits: Receive window size in octets
  8.       32 bits: Receive left window edge (next sequence number expected)
  9.       16 bits: Receive packet buffer size of TCB (may be less than window)
  10.       16 bits: Send window size in octets
  11.       32 bits: Send left window edge (earliest unacknowledged octet)
  12.       32 bits: Next packet sequence number
  13.       16 bits: Send packet buffer size of TCB (may be less than window)
  14.       8 bits: Connection state
  15.          E/- 1 if TCP has been synchronized at least once (i.e. has
  16.          been established, else O, meaning it is closed; this bit is
  17.          reset after FINS are exchanged and the user has done a CLOSE).
  18.          The bit is not reset if the connection is only desynchronized
  19.          on send or receive or both directions.
  20.  
  21.          SS - SYNCed on send side (if set) else desynchronized
  22.          SR - SYNCed on receive side (if set, else desynchronized)
  23.  
  24.    16 bits: Special flags
  25.       S1 - SYN sent if set
  26.       S2 - SYN verified if set
  27.       R - SYN received if set
  28.       Y - FIN sent if set
  29.       C - CLOSE from local user received if set
  30.       U - Foreign socket unspecified if set
  31.       SDS - Send side DSN sent if set
  32.       SDV - Send side DSN verified if set
  33.       RDR - Receive side DSN received if set
  34.  
  35.    Initially, all bits are off [no pun intended] (i.e. SS, SR, E/C, S1,
  36.    S2, R, F, C, SDS, SDV, RDR =0). When R is set, so is SR. When S1 and
  37.    S2 are both set, so is SS. SR is reset when RDR is set. SS is reset
  38.    when both SDS and SDV are set. These bits are used to keep track of
  39.    connection state and to aid in arriving packet processing (e.g. Can
  40.    sequence number be validated? Only if SR is set.).
  41.  
  42.    16 bits: Retransmission timeout (in eighths of a second#]
  43.    16 bits: Head of Send buffer queue [buffers SENT from user to TCP, but not packetized]
  44.    16 bits: Tail of Send buffer queue
  45.    16 bits: Pointer to last octet packetized in partially packetized buffer (refers to the buffer at the head of the queue)
  46.  
  47.    16 bits: Head of Send packet queue
  48.    16 bits: Tail of Send packet queue
  49.    16 bits: Head of Packetized buffer Queue
  50.    16 bits: Tail of Packetized buffer queue
  51.    16 bits: Head of Retransmit packet queue
  52.    16 bits: Tail of Retransmit packet queue
  53.    16 bits: Head of Receive buffer queue [queue of buffers given by user  to RECEIVE letters, but unfilled]
  54.    16 bits: Tail of Receive buffer queue
  55.    16 bits: Head of Receive packet queue
  56.    16 bits: Tail of receive packet queue
  57.    16 bits: Pointer to last contiguous receive packet
  58.    16 bits: Pointer to last octet filled in partly filled buffer
  59.    16 bits: Pointer to next octet to read from partly emptied packet
  60.       [Note: The above two pointers refer to the head of the receive
  61.       buffer and receive packet queues respectively]
  62.  
  63.    16 bits: Forward TCB pointer
  64.    16 bits: Backward TCB pointer

.....

Ааа, кажется, понял: TdiCopyBufferToMdl уже копирует распарсенный TCB, указатель на который принимает ReadNextTCB вторым аргументом. Сама TCB заключена внутри некоего контейнера, который передаётся первым аргументом... Буду дальше реверсить...

Ничего похожего, по крайней мере, в порядке, в каком указано в rfc675, не нашёл.
Возникают вопросы: что за распарсенная структура вида как в первом посте? Что за контейнер?

Следующее, что я обнаружил:
указатель на некую структуру содержится в pContainer->pStruct->pNext [[Arg1 + 8]]
так перечисляются все структуры, пока не нуль
но если нуль, то берётся переменная _TWTCBTable, о которой можно найти только на --> китайском сайте <-- под заголовком Rootkit с китайским названием.

Неужели никто больше не проводил исследования в этой области? Что внутри tcpip.sys, известно только m$ и не публикующимся исследователям?

Ну да ладно. _TWTCBTable что-то вроде списка списков TCB с головой, который у меня на момент креша оказался пустым, т.е. указывал только на себя. Используется он, только если пакетов в очереди, чем 512...
У меня на момент креша было 223 пакета в очереди...
Все списки TCB можно перечислить по переменной TCB* _TCBTable[]. TCB отличается от структуры в первом посте и имеет примерно такую структуру:
Code:
  1. 00 pNext
  2. 04 pSpinLock
  3. 08 Reserved
  4. //входящие и исходяшие, только кто из них входящий?
  5. //в сетевом порядке, Big-endian
  6. 0C IpAddr2
  7. 10 IpAddr1
  8. 14 Port2
  9. 16 Port1
  10. 18 ProcessId
  11. 1C 4 - возможно версия IP
  12. ...
  13. 80 pFunc = IndicateData или PendData(во всех TCB, что я нашёл, IndicateData) - зависит от условия,
  14.  упрощённый вариант -> if(pTcb + D4 != 0) pTcb->pFunc = IndicateData
  15. ...
  16. С8 pConn - указатель на структуру CONNECTION *
  17. ...
  18. D4 как-то связано с соединением


* - название условно, может измениться

Из дампа видно, что сами структуры могут повторять информацию о соединении, так что возможно присутствует и информация о самом трафике...
Подхожу к логическому концу: к бсоду мой комп привело непонятное стечение обстоятельств, из-за которых в одной из структур TCB по смещению 0xC8 нулевой указатель. То ли не заполнилось поле в следствие непродуманности алгоритма, то ли обнулилось, может следствие плохой синхронизации... гадать можно долго... Структура выше получается из массива по адресу [[[pTCB + 0xC8] + 0x0C] + 0x160]

Код, приведший к бсоду
Code:
  1. .text:A94C0FA3 014 8B 86 C8 00 00 00             mov     eax, [esi+0C8h] ; [88efd0d0]
  2. .text:A94C0FA9 014 8B 40 0C                      mov     eax, [eax+0Ch]


-----
IZ.RU





Ранг: 527.7 (!), 381thx
Активность: 0.160.09
Статус: Участник
Победитель турнира 2010

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





Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 08 августа 2011 21:34 · Поправил: DenCoder
· Личное сообщение · #5

Если это TCB, то тогда у меня ни одна из структур - не TCB Спасибо! Пойду посмотрю структуры на ReactOS...


Самое интересное, что в ReadNextTCB ниже "бсодного" кода

Code:
  1. .text:A94C0FA3 014 8B 86 C8 00 00 00             mov     eax, [esi+0C8h]
  2. .text:A94C0FA9 014 8B 40 0C                      mov     eax, [eax+0Ch]; <- здесь BSOD у многих счастливых обладателей WinXP SP3
  3.  
  4. A94C0FAC 014 8B 90 60 01 00 00             mov     edx, [eax+160h]


делается проверка
Code:
  1. .text:A94C0FEF 014 8B 8E C8 00 00 00             mov     ecx, [esi+0C8h]
  2. .text:A94C0FF5 014 33 DB                         xor     ebx, ebx
  3. .text:A94C0FF7 014 3B CB                         cmp     ecx, ebx
  4. .text:A94C0FF9 014 74 05                         jz      short loc_A94C1000


то есть всё же m$ допускают, что [esi + 0xC8] может быть равно нулю
Только совсем непонятна логика дальше
Code:
  1. .text:A94C0FFB 014                 mov     ecx, [ecx+28h]
  2. .text:A94C0FFE 014                 jmp     short loc_A94C1002
  3. .text:A94C1000     ; ---------------------------------------------------------------------------
  4. .text:A94C1000
  5. .text:A94C1000     loc_A94C1000:                           ; CODE XREF: .text:A94C0FF9j
  6. .text:A94C1000 014                 xor     ecx, ecx
  7. .text:A94C1002
  8. .text:A94C1002     loc_A94C1002:                           ; CODE XREF: .text:A94C0FFEj
  9. .text:A94C1002 014                 cmp     edx, ebx 

Допустим в [esi + 0xC8] нуль и каким-то фантастическим образом миновали бсодный участок. Но чему будет при этом равен edx? Я скажу, что он будет равен 0xA8.

Такое чувство, что вырезана/закомментирована часть кода. Причём m$ не смотрела её как минимум года 3. И весело и печально...

-----
IZ.RU





Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 08 августа 2011 22:29
· Личное сообщение · #6

и на sp2 точно такой же код
но ниукого ничего не падает(вроде?), может проблему искать в другой плоскости?
например установленных дополнительных драйверов левого софта?




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 08 августа 2011 22:35 · Поправил: DenCoder
· Личное сообщение · #7

reversecode пишет:
но ниукого ничего не падает(вроде?)

--> ReadNextTcb <--
Хорошее обилие дампов? Не падает, если не мониторить. На WinXP используется TDI для этого, начиная с Висты используется уже другая технология. Хотя есть и те, у кого и без мониторинга падает...

Вообще, проблема не в этой функции, не в ReadNextTcb. По смещению 0xC8 всё же не должно быть нуля...

UPDATED.
Читал, что на ReactOS, хоть они ковыряются в винде, но чтобы не вызвать возмущения, немного изменяют то, что на ковыряли. Поэтому, видать, не сходятся структуры. Вообще, то, что привёл OKOB с ReactOS не сходится с тем, что я скачал. Ну ладно, структуры в постах выше обновил тем, что ещё удалось наковырять. И новое:

Code:
  1. _TWTCBTable разделы таблиц TCB
  2. _TCBTable таблица списков TCB
  3. _NumTcbTablePartitions число разделов, по умолчанию 4
  4. _MaxHashTableSize макс число списков TCB, по умолчанию 0x200... почему там слово Hash - непонятно )


Эта структура передаётся в ReadNextTCB и ValidateTCBContext
Code:
  1. struct TCB_GROUP - тот самый контейнер, про который писал
  2. {
  3.   int TcbNum;//номер Tcb из таблицы _TCBTable, TcbNum < _MaxHashTableSize
  4.   int TcbSize;//0xA8, контейнер используется не только для TCB, а также и для AO, размер к-рого может
  5.  быть другим. Что это такое и с чем его едят, пока не знаю - по его вине не было бсодов, но парсится и 
  6. укладывается в MDL он также как и TCB в TdiQueryInformationEx. Структура в первом посте при этом - 
  7. некая промежуточная (позже объединю всё вместе)
  8.   TCB* pCurTcb;//курсор, указывает на текущий Tcb
  9. ....
  10. };


-----
IZ.RU





Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 09 августа 2011 16:11 · Поправил: reversecode
· Личное сообщение · #8

по +С8 хранится Conn (Connection)
заполняется _например_ от сюда TdiConnect
Code:
  1. .text:0001C8DD                 mov     [esi+0C8h], edi

берется от сюда GetConnFromConnID

приблизительно так
Code:
  1. tcb = AllocTCB();
  2. ....
  3. conn = GetConnFromConnID(??? итд)
  4. .....
  5. tcb->conn = conn;


вообще начиная c разбора AllocTCB(), где этот TCB аллоцируется и заполняется , дальше все очень легко разбирается дальше
если прыгать в каждую функцию которая вызывает этот AllocTCB

| Сообщение посчитали полезным: DenCoder


Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 09 августа 2011 17:11 · Поправил: DenCoder
· Личное сообщение · #9

Да, верно. Только у меня смещение другое, но не столь важно... Спасибо ;)
Значит, раз к моменту вызова ReadNextTCB уже есть IP-адреса и порты, но pTcb->pConn вдруг 0, то где-то между инициализацией и парсингом происходит обнуление...

Может в TdiReceive или TdiSend? А может какой-то редкий протокол вмешивается в работу? Попробуем найти в стеке вызовов, но скорей всего вряд ли там можно найти - здесь пахнет, что из другого потока было изменение. Нечто вроде потери соединения в момент запроса информации о TCB...

tcpip, кстати, несмотря на то, что он так назван обрабатывает ещё много протоколов, не связанных с IP...

-----
IZ.RU





Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 09 августа 2011 17:51 · Поправил: reversecode
· Личное сообщение · #10

http://rghost.ru/17359841 (AllocTCB) есть в обеих вариантах pdb с M$
полистай IDA
там есть места когда TCB алоцирует и добавляется в очередь(хеш), но не инициализирует C8h(conn)

вообщем я как и всегда смотрю скептически на анализ такой проблемы без полного разбора tcpip.sys
а разбирать его я особой выгоды не для кого не вижу
ну получим мы к примеру tcpip.sys в исходниках, ....?
найдем проблему, дальше нужно будет подписывать этот драйвер
разве что результат продать разрабам ReactOS ;))

единственная польза, это разве что удовольствие от красоты архитектурной реализации tcpip.sys в майкрософте..




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 09 августа 2011 18:06 · Поправил: DenCoder
· Личное сообщение · #11

Да нашёл AllocTCB. Сразу же, просто у меня

Code:
  1. A94943BD 038 89 BE C8 00 00 00             mov     [esi+0C8h], edi

намного ниже от InitTCBFromConn, чем ожидал.

reversecode пишет:
а разбирать его я особой выгоды не для кого не вижу

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

Кроме того, польза в понятии принципов работы сетевого стека

-----
IZ.RU





Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 09 августа 2011 18:11 · Поправил: reversecode
· Личное сообщение · #12

DenCoder пишет:
да, он огромен, и одному его практически не разобрать.

300 кил не много..

а причину краша может и не найдешь
можно ведь только по одному трейсу выйти что там TdiQueryInformation вызывается
а самого процесса прокрутки того что творилось с TCB нет

add
пример вызова чего либо по таймеру, где по таймеру к примеру функция меняет этот TCB
стектрейса не будет, ничего в дампе не будет по этому поводу
а потому уже где то когда то вызовется какой нибудь send() с userlevel
и все упадет в прочтении TCB->Conn

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




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 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:
  1. a883e7ec a94c0fa9 badb0d00 00000004 00000963 nt!KiTrap0E+0x238
  2. a883e870 a94b1b5e 0272fb78 a883ea10 88a68c58 tcpip!ReadNextTCB+0xd2
  3. 80702830 05c7fffe fffe0080 00000041 0f04eac1 tcpip!TdiQueryInformationEx+0x7e5


Но странно, что WinDbg не показывет дальше
Code:
  1. TCPQueryInformationEx(x,x)+17D
  2. TCPDispatchDeviceControl(x,x)+3B
  3. TCPDispatch(x,x)+74
  4. IopfCallDriver(x,x)+27
  5. ...


-----
IZ.RU



 eXeL@B —› Основной форум —› Transmission Control Block(TCB) формат
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


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