如何解码视图状态

Posted

技术标签:

【中文标题】如何解码视图状态【英文标题】:How to decode viewstate 【发布时间】:2010-09-06 13:45:59 【问题描述】:

我需要查看 asp.net 页面的视图状态的内容。我寻找了一个视图状态解码器,找到了Fridz Onion's ViewState Decoder,但它要求一个页面的 url 来获取它的视图状态。由于我的视图状态是在回发后形成的,并且是由于更新面板中的操作而产生的,因此我无法提供 url。我需要复制并粘贴视图状态字符串并查看里面的内容。是否存在可以帮助查看 viewstate 内容的工具或网站?

【问题讨论】:

不就是序列化数据的base 64编码版本吗? 很晚,但很好奇这是否有帮助string str = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(txtViewState.Text)); 确保您的 ViewState 设置为 not encrypted,否则这些工具(答案)都不起作用。 将此添加到 web.config:<pages viewStateEncryptionMode="Never"> 以根据@David Rogers 评论禁用 ViewState 加密。 【参考方案1】:

这是一个在线 ViewState 解码器:

http://ignatu.co.uk/ViewStateDecoder.aspx

编辑:不幸的是,上面的链接已失效 - 这是另一个 ViewState 解码器(来自 cmets):

http://viewstatedecoder.azurewebsites.net/

【讨论】:

+1 在线视图状态解码器的良好链接,易于使用和工作。感谢您的回答 如果这告诉您序列化数据无效,请尝试使用viewstatedecoder.azurewebsites.net:处理此解码器出错的问题。 Format marker: C9 , Unknown format marker, exiting! 如果我粘贴了一个 6M 长的视图状态字符串,viewstatedecoder.azurewebsites.net 给了我一个 YSOD。 viewstatedecoder.azurewebsites.net 给我一个服务器错误【参考方案2】:

使用Fiddler 并在响应中抓取视图状态并将其粘贴到左下角的文本框中然后解码。

【讨论】:

如果不想安装 Fiddler,也可以使用 Firefox 的 HttpFox 插件:addons.mozilla.org/en-US/firefox/addon/6647 我猜有些东西已经改变了——左下角的文本框是某种命令提示符,在视图状态中粘贴没有任何用处。我看不到它去了哪里 - 它还在当前版本中吗? 对于那些使用当前版本的 Fiddler (2.5.1) 的用户,现在可以通过单击顶部菜单中的 TextWizard 选项找到此答案中描述的文本框(或 工具 > 文本向导 Ctrl+E)。将 ViewState 粘贴到顶部框中,然后将 Transform 更改为“From Base64”。 @Chris HttpFox 插件与 Firefox Quantum 不兼容。你还知道其他插件吗?【参考方案3】:

这是来自Scott Mitchell's article on ViewState(25 页)的 ViewState 可视化工具的源代码

using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Web.UI;


namespace ViewStateArticle.ExtendedPageClasses

    /// <summary>
    /// Parses the view state, constructing a viaully-accessible object graph.
    /// </summary>
    public class ViewStateParser
    
        // private member variables
        private TextWriter tw;
        private string indentString = "   ";

        #region Constructor
        /// <summary>
        /// Creates a new ViewStateParser instance, specifying the TextWriter to emit the output to.
        /// </summary>
        public ViewStateParser(TextWriter writer)
        
            tw = writer;
        
        #endregion

        #region Methods
        #region ParseViewStateGraph Methods
        /// <summary>
        /// Emits a readable version of the view state to the TextWriter passed into the object's constructor.
        /// </summary>
        /// <param name="viewState">The view state object to start parsing at.</param>
        public virtual void ParseViewStateGraph(object viewState)
        
            ParseViewStateGraph(viewState, 0, string.Empty);    
        

        /// <summary>
        /// Emits a readable version of the view state to the TextWriter passed into the object's constructor.
        /// </summary>
        /// <param name="viewStateAsString">A base-64 encoded representation of the view state to parse.</param>
        public virtual void ParseViewStateGraph(string viewStateAsString)
        
            // First, deserialize the string into a Triplet
            LosFormatter los = new LosFormatter();
            object viewState = los.Deserialize(viewStateAsString);

            ParseViewStateGraph(viewState, 0, string.Empty);    
        

        /// <summary>
        /// Recursively parses the view state.
        /// </summary>
        /// <param name="node">The current view state node.</param>
        /// <param name="depth">The "depth" of the view state tree.</param>
        /// <param name="label">A label to display in the emitted output next to the current node.</param>
        protected virtual void ParseViewStateGraph(object node, int depth, string label)
        
            tw.Write(System.Environment.NewLine);

            if (node == null)
            
                tw.Write(String.Concat(Indent(depth), label, "NODE IS NULL"));
             
            else if (node is Triplet)
            
                tw.Write(String.Concat(Indent(depth), label, "TRIPLET"));
                ParseViewStateGraph(((Triplet) node).First, depth+1, "First: ");
                ParseViewStateGraph(((Triplet) node).Second, depth+1, "Second: ");
                ParseViewStateGraph(((Triplet) node).Third, depth+1, "Third: ");
            
            else if (node is Pair)
            
                tw.Write(String.Concat(Indent(depth), label, "PAIR"));
                ParseViewStateGraph(((Pair) node).First, depth+1, "First: ");
                ParseViewStateGraph(((Pair) node).Second, depth+1, "Second: ");
            
            else if (node is ArrayList)
            
                tw.Write(String.Concat(Indent(depth), label, "ARRAYLIST"));

                // display array values
                for (int i = 0; i < ((ArrayList) node).Count; i++)
                    ParseViewStateGraph(((ArrayList) node)[i], depth+1, String.Format("(0) ", i));
            
            else if (node.GetType().IsArray)
            
                tw.Write(String.Concat(Indent(depth), label, "ARRAY "));
                tw.Write(String.Concat("(", node.GetType().ToString(), ")"));
                IEnumerator e = ((Array) node).GetEnumerator();
                int count = 0;
                while (e.MoveNext())
                    ParseViewStateGraph(e.Current, depth+1, String.Format("(0) ", count++));
            
            else if (node.GetType().IsPrimitive || node is string)
            
                tw.Write(String.Concat(Indent(depth), label));
                tw.Write(node.ToString() + " (" + node.GetType().ToString() + ")");
            
            else
            
                tw.Write(String.Concat(Indent(depth), label, "OTHER - "));
                tw.Write(node.GetType().ToString());
            
        
        #endregion

        /// <summary>
        /// Returns a string containing the <see cref="IndentString"/> property value a specified number of times.
        /// </summary>
        /// <param name="depth">The number of times to repeat the <see cref="IndentString"/> property.</param>
        /// <returns>A string containing the <see cref="IndentString"/> property value a specified number of times.</returns>
        protected virtual string Indent(int depth)
        
            StringBuilder sb = new StringBuilder(IndentString.Length * depth);
            for (int i = 0; i < depth; i++)
                sb.Append(IndentString);

            return sb.ToString();
        
        #endregion

        #region Properties
        /// <summary>
        /// Specifies the indentation to use for each level when displaying the object graph.
        /// </summary>
        /// <value>A string value; the default is three blank spaces.</value>
        public string IndentString
        
            get
            
                return indentString;
            
            set
            
                indentString = value;
            
        
        #endregion
    

这是一个简单的页面,用于从文本框中读取视图状态并使用上面的代码绘制图表

private void btnParse_Click(object sender, System.EventArgs e)
        
            // parse the viewState
            StringWriter writer = new StringWriter();
            ViewStateParser p = new ViewStateParser(writer);

            p.ParseViewStateGraph(txtViewState.Text);
            ltlViewState.Text = writer.ToString();
        

【讨论】:

代码对我有用,但我确实必须添加对实际参与生成视图状态的程序集之一的引用 如果您将其粘贴到控制台应用程序中,您需要在项目中包含对“System.Web”的引用。否则它不会构建...【参考方案4】:

正如另一个人刚刚提到的,它是一个 base64 编码的字符串。过去,我使用这个网站对其进行解码:

http://www.motobit.com/util/base64-decoder-encoder.asp

【讨论】:

是base64编码的序列化对象,所以解码后的数据不是特别有用。最好使用适当的 View State 解码器。 使用其他解码器时,我不断收到解码错误。这是第一种真正适合我的方法。诚然,它只是一个直接的字符串解码而不是一个视图状态解码器,但它让我走得更远。 +1 非常感谢!!【参考方案5】:

这是另一个在 2014 年运行良好的解码器:http://viewstatedecoder.azurewebsites.net/

这适用于 Ignatu 解码器因“序列化数据无效”而失败的输入(尽管它使 BinaryFormatter 序列化数据未解码,仅显示其长度)。

【讨论】:

【参考方案6】:

javascript-ViewState-Parser:

http://mutantzombie.github.com/JavaScript-ViewState-Parser/ https://github.com/mutantzombie/JavaScript-ViewState-Parser/

解析器应该适用于大多数未加密的视图状态。它没有 处理 .NET 版本 1 使用的序列化格式,因为 版本非常过时,因此不太可能 在任何实际情况中遇到。

http://deadliestwebattacks.com/2011/05/29/javascript-viewstate-parser/


解析 .NET ViewState

深入了解 ViewState,第一部分:

http://deadliestwebattacks.com/2011/05/13/a-spirited-peek-into-viewstate-part-i/

深入了解 ViewState,第二部分:

http://deadliestwebattacks.com/2011/05/25/a-spirited-peek-into-viewstate-part-ii/


【讨论】:

这个在 Firefox 中对我有用,即使其他视图状态解析器没有。文章的链接也很受欢迎。【参考方案7】:

这是一种将 ViewState 从字符串转换为 StateBag 的“原生”.NET 方式 代码如下:

public static StateBag LoadViewState(string viewState)
    
        System.Web.UI.Page converterPage = new System.Web.UI.Page();
        HiddenFieldPageStatePersister persister = new HiddenFieldPageStatePersister(new Page());
        Type utilClass = typeof(System.Web.UI.BaseParser).Assembly.GetType("System.Web.UI.Util");
        if (utilClass != null && persister != null)
        
            MethodInfo method = utilClass.GetMethod("DeserializeWithAssert", BindingFlags.NonPublic | BindingFlags.Static);
            if (method != null)
            
                PropertyInfo formatterProperty = persister.GetType().GetProperty("StateFormatter", BindingFlags.NonPublic | BindingFlags.Instance);
                if (formatterProperty != null)
                
                    IStateFormatter formatter = (IStateFormatter)formatterProperty.GetValue(persister, null);
                    if (formatter != null)
                    
                        FieldInfo pageField = formatter.GetType().GetField("_page", BindingFlags.NonPublic | BindingFlags.Instance);
                        if (pageField != null)
                        
                            pageField.SetValue(formatter, null);
                            try
                            
                                Pair pair = (Pair)method.Invoke(null, new object[]  formatter, viewState );
                                if (pair != null)
                                
                                    MethodInfo loadViewState = converterPage.GetType().GetMethod("LoadViewStateRecursive", BindingFlags.Instance | BindingFlags.NonPublic);
                                    if (loadViewState != null)
                                    
                                        FieldInfo postback = converterPage.GetType().GetField("_isCrossPagePostBack", BindingFlags.NonPublic | BindingFlags.Instance);
                                        if (postback != null)
                                        
                                            postback.SetValue(converterPage, true);
                                        
                                        FieldInfo namevalue = converterPage.GetType().GetField("_requestValueCollection", BindingFlags.NonPublic | BindingFlags.Instance);
                                        if (namevalue != null)
                                        
                                            namevalue.SetValue(converterPage, new NameValueCollection());
                                        
                                        loadViewState.Invoke(converterPage, new object[]  ((Pair)((Pair)pair.First).Second) );
                                        FieldInfo viewStateField = typeof(Control).GetField("_viewState", BindingFlags.NonPublic | BindingFlags.Instance);
                                        if (viewStateField != null)
                                        
                                            return (StateBag)viewStateField.GetValue(converterPage);
                                        
                                    
                                
                            
                            catch (Exception ex)
                            
                                if (ex != null)
                                

                                
                            
                        
                    
                
            
        
        return null;
    

【讨论】:

【参考方案8】:

您可以忽略 URL 字段,只需将视图状态粘贴到视图状态字符串框中。

看起来你有一个旧版本; ASP.NET 2.0 中的序列化方法发生了变化,所以抓住2.0 version

【讨论】:

【参考方案9】:

python 中最好的方法是使用这个link。

用于解码 ASP.NET 视图状态的小型 Python 3.5+ 库。

首先安装那个:pip install viewstate

>>> from viewstate import ViewState
>>> base64_encoded_viewstate = '/wEPBQVhYmNkZQ9nAgE='
>>> vs = ViewState(base64_encoded_viewstate)
>>> vs.decode()
('abcde', (True, 1))

【讨论】:

【参考方案10】:

Lachlan Keown 制作的在线 Viewstate Viewer:

http://lachlankeown.blogspot.com/2008/05/online-viewstate-viewer-decoder.html

【讨论】:

虽然这可能会回答问题,但it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。 @bluefeet 还有什么要补充的?唯一重要的部分是解码器本身。其他两个回答者做了同样的事情,只发布了链接。【参考方案11】:

通常,如果您拥有机器密钥,ViewState 应该是可解密的,对吧?毕竟 ASP.net 需要解密,这当然不是黑匣子。

【讨论】:

当然,你是对的。我的意思是,如果它是加密的,你将无法轻松地解码它 以防万一有人偶然发现这个答案...... ViewState 永远不会加密。它只是 base64 编码的。不需要钥匙。 @Rap 在 .NET 4.5 中我不能简单地对它进行 base64 解码。不仅如此。在线工具只是返回一个空字符串,而 ViewState 解码器会抛出某种错误。这导致人们相信,即使它本身没有加密,它编码超过 base64。 @ahwm 真实故事。 .Net 4.5 正在加密 ViewState。 16 个月前我写评论的时候不是这样,但现在是这样。你是对的。 @Rap 感谢您的澄清。这是有道理的,为什么它对我不起作用,但是有关于如何解码它的帖子和帖子。以为我快疯了,或者我们内部的 CMS 正在做奇怪的事情。

以上是关于如何解码视图状态的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHP 中 JSON 编码/解码后维护对象状态

如何防止 SKAction 序列在解码后重新启动?

如何在原生 iOS 应用程序中过滤 WebRTC 编解码器

MySql笔记-基础篇-编码解码与乱码

在 R 中解码 sl2 文件的声纳视图的探测数据

《概率统计》14.状态解码:隐马尔科夫模型隐含状态揭秘