Получить содержимое сеанса из дампа процесса ASP.net 3.5 в Windbg

Я сделал дамп процесса W3wp.exe и пытаюсь получить содержимое сеанса с помощью Windbg. Мое тестовое приложение — ASP.net 3.5, работающее в 64-разрядной версии Windows 7, и сеанс находится в процессе. Я могу получить содержимое различных других объектов, но не могу найти, где находится содержимое сеанса.

Да, я знаю, что хранить вещи в сеансе плохо, но мне это нужно, чтобы помочь отладить проблему на клиентском сайте.

Я нашел отличный пост Тесс Феррендес (http://blogs.msdn.com/b/tess/archive/2007/09/18/debugging-script-dumping-out-asp-net-session-contents.aspx), который описывает создание сценария для повторения всего в сеансе.

Однако я подозреваю, что это было нацелено на предыдущую версию IIS (и, возможно, .net и 32bit), поскольку сценарий Тесс ищет объекты InProcSessionState, которых, похоже, нет в моем дампе.

Любые идеи, как получить содержимое сеанса из дампа?

Спасибо,

Алекс


person alexmac    schedule 17.10.2010    source источник


Ответы (1)


Это решение предназначено для сброса объектов сеанса x64 asp.net.

Вот пример кода, который я использовал для добавления элементов в сеанс.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.Session.Add("Name", "Test");
        this.Session.Add("Name1", "Test1");
    }
}

Вот скрипт для получения содержимого объекта HttpSession

  .foreach ($obj {!dumpheap -mt ${$arg1} -short}) 
{
   $$ The !dumpheap -short option has last result as --------------- and 
   $$ this .if is to avoid this
   .if ($spat ("${$obj}","------------------------------")) 
     {} 
   .else 
     {
        $$ $t5 contains refernce to the array which has key and value for the
        $$ session contents

        r$t5 = poi(poi(poi(poi(${$obj}+0x8)+0x10)+0x8)+0x8);
         r$t1 = 0
        .for (r $t0=0; @$t0 < poi(@$t5+0x8); r$t0=@$t0+1 ) 
        {
          .if(@$t0 = 0) 
          { 
            $$ First occurence of the element in the array would be in the 20 offset
             r$t1=20
          }
          .else 
           { 
            $$ the rest of the elements would be in the 8th offset
            r$t1= 20+(@$t0*8)
           };

          $$ Check for null before trying to dump          

          .if (poi((@$t5-0x8)+@$t1) = 0 )
           {
              .continue
           } 
          .else
           {              
               .echo ************;
               ? @$t0
               $$ Session Key
               .printf "Session Key is :- "; !ds poi(poi((@$t5-0x8)+@$t1)+0x8);
               $$ Session value
               .printf "Session value is :- ";!ds poi(poi((@$t5-0x8)+@$t1)+0x10)
           }
        }
      }
}

Скопируйте приведенный выше сценарий в файл и вызовите сценарий, подобный этому $$>a<"c:\temp\test.txt" 000007fef4115c20, в Windbg. Передача MT System.Web.SessionState.HttpSessionState в качестве аргумента скрипта.

А вот вывод скрипта

************ 
Evaluate expression: 0 = 00000000`00000000 
Session Key is :- Name  
Session value is :- Test 
************ 
Evaluate expression: 1 = 00000000`00000001 
Session Key is :- Name1  
Session value is :- Test1

Я использую псевдоним !ds для вывода строк вместо !dumpobj. Чтобы создать псевдоним, используйте эту команду as !ds .printf "%mu \n", 10+

Сценарий немного загадочен, если только вы не привыкли писать сценарии Windbg.

Вот краткое объяснение скрипта

  1. $t5 — содержит ссылку на массив типа System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry
  2. Вложенный цикл .for предназначен для перебора элементов массива. Я написал об этом в блоге, если вам интересно понять пользовательский дамп-параметр.
  3. Оператор .if во вложенном цикле for .if (poi((@$t5-0x8)+@$t1) = 0) проверяет, является ли элемент нулевым, прежде чем сбрасывать содержимое с помощью команды !ds.
  4. !ds poi(poi((@$t5-0x8)+@$t1)+0x8): ключевая строка сеанса. Пример Name
  5. !ds poi(poi((@$t5-0x8)+@$t1)+0x10) : — Значение сеанса. Пример Test

ХТН

РЕДАКТИРОВАТЬ: - Также здесь есть независимый от платформы скрипт. Это должно работать для x86 и x64

r $t9 = @$ptrsize;
$$ $t8 register contains the next offset of the variable 
$$ $t7 register contains array start address 
.if (@$ptrsize = 8)
{ 
  r $t8 = 10
  r $t7 = 20
  r $t6 = 10
} 
.else 
{
  r $t8 = 6
  r $t6 = 8
  r $t7 = 10
}  
.foreach ($obj {!dumpheap -mt ${$arg1} -short}) 
{
   $$ The !dumpheap -short option has last result as --------------- and 
   $$ this .if is to avoid this
   .if ($spat ("${$obj}","------------------------------")) 
     {} 
   .else 
     {
        $$ $t5 contains refernce to the array which has key and value for the
        $$ session contents

         r$t5 = poi(poi(poi(poi(${$obj}+@$t9)+@$t6)+@$t9)+@$t9);
        .for (r $t0=0; @$t0 < poi(@$t5+@$t9); r$t0=@$t0+1 ) 
        {
          .if(@$t0 = 0) 
          { 
            $$ First occurence of the element in the array would be in the 20 offset
             r$t1=@$t7
          }
          .else 
           { 
            $$ the rest of the elements would be in the 8th offset
            r$t1= @$t7+(@$t0*@$t9)
           };
          $$ Check for null before trying to dump          
          .if (poi((@$t5-@$t9)+@$t1) = 0 )
           {
              .continue
           } 
          .else
           {              
               .echo ************;
               ? @$t0
               $$ Session Key
               .printf "Session Key is :- "; !ds poi(poi((@$t5-@$t9)+@$t1)+@$t9);
               $$ Session value
               .printf "Session value is :- ";!ds poi(poi((@$t5-@$t9)+@$t1)+@$t6)
           }
        }
      }
}
person Naveen    schedule 17.10.2010
comment
Привет, Навин, большое спасибо за рассмотрение этой проблемы, однако я получаю следующую ошибку: Ошибка доступа к памяти в ')+0x4)+0x4); .for (r $t0=0; @$t0 ‹ poi(@$t5+0x4); r$t0=@$t0+1 ) ;{ r$t1 = 0; .if(@$t0 = 0) { r$t1=10} .else { r$t1= 10+ @$t0*4};.echo ************; .if (poi((@$t5-0x4)+@$t1) =0) {} .else {!ds poi(poi((@$t5-0x4)+@$t1)+0x4);!ds poi (poi((@$t5-0x4)+@$t1)+0x8)} }'. Я заменил адрес после переключателя -mt на адрес HttpSessionState MT. Вы запускаете это на 64-битном дампе, поскольку адреса выглядят по-другому? - person alexmac; 18.10.2010
comment
Привет Alexmac, извините за то, что я использовал x86 вместо x64. Я исправил скрипт для x64 и обновил ответ. - person Naveen; 18.10.2010