从 Windbg 中 ASP.net 3.5 进程的转储中检索会话内容

发布于 2024-09-27 15:17:58 字数 491 浏览 2 评论 0原文

我已经转储了 W3wp.exe 进程,并尝试使用 Windbg 检索会话的内容。我的测试应用程序是在 Windows 7 64 位上运行的 ASP.net 3.5,会话正在进行中。我可以检索各种其他对象的内容,但很难找到会话内容所在的位置。

是的,我知道在会话中存储内容是不好的,但我需要它来帮助调试客户端站点上的问题。

我发现 Tess Ferrendez 发表了一篇很棒的文章 (http://blogs.msdn.com/b/tess/archive/2007/09/18/debugging-script-dumping-out-asp-net-session-contents.aspx)描述创建一个脚本来迭代会话中的所有内容。

然而,我怀疑这是针对以前版本的 IIS(可能还有 .net 和 32 位),因为 Tess 的脚本查找似乎不存在于我的转储中的 InProcSessionState 对象。

有什么想法如何从转储中获取会话的内容吗?

谢谢,

亚历克斯

I have taken a dump of W3wp.exe process and am trying to retrieve the contents of session using Windbg. My test application is ASP.net 3.5 running on Windows 7 64 bit and the session is inprocess. I can retrieve the contents of various other objects but am struggling to find where session contents is located.

Yes I know storing stuff in session is bad but I need this to help debug an issue at a clients site.

I found a great post by Tess Ferrendez (http://blogs.msdn.com/b/tess/archive/2007/09/18/debugging-script-dumping-out-asp-net-session-contents.aspx) that describes creating a script to iterate through everything in session.

I suspect however that this was aimed at a previous version of IIS (and possibly .net & 32bit) as Tess's script looks for InProcSessionState objects which dont seem to exist in my dump.

Any ideas how to get at the contents of session from a dump?

Thanks,

Alex

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟酒忠诚 2024-10-04 15:17:58

此解决方案用于转储 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 内。将 System.Web.SessionState.HttpSessionState 的 MT 作为脚本参数传递。

这是脚本的输出,

************ 
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. 嵌套 for 循环中的 .if 语句 .if (poi((@$t5-0x8)+@$t1) = 0) 检查之前该项是否为 null使用 !ds 命令转储内容。
  4. !ds poi(poi((@$t5-0x8)+@$t1)+0x8)
    :- 会话的密钥字符串。示例 Name
  5. !ds poi(poi((@$t5-0x8)+@$t1)+0x10) :- 会话值。示例测试

HTH

编辑:- 这里还有一个独立于平台的脚本。这应该适用于 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)
           }
        }
      }
}

This solution is for dumping x64 asp.net session objects.

Here is the sample code i used to add the items to session.

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");
    }
}

Here is the script to get the contents of the HttpSession object

  .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)
           }
        }
      }
}

Copy the above script in to a file and invoke the script like this $$>a<"c:\temp\test.txt" 000007fef4115c20 within Windbg. Passing the MT of System.Web.SessionState.HttpSessionState as the script argument.

And here is the output from the script

************ 
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

I use the alias !ds for dumping strings instead of using !dumpobj. To create the alias use this command as !ds .printf "%mu \n", 10+

The script is little bit arcane unless you are used to writing windbg scripts.

Here is a brief explanation of the script

  1. $t5 - Contains reference to the array of type System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry
  2. The nested .for loop is to iterate through the array items. I have blogged about the same if you are interested in understanding custom dumparray
  3. The .if statement within the nested for loop .if (poi((@$t5-0x8)+@$t1) = 0) checks if the item is null before dumping the contents using !ds command.
  4. !ds poi(poi((@$t5-0x8)+@$t1)+0x8)
    :- The key string for the session . Example Name
  5. !ds poi(poi((@$t5-0x8)+@$t1)+0x10) :- The session value . Example Test

HTH

EDIT:- Also here is a platform independent script . This should work for x86 and 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)
           }
        }
      }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文