如何解码viewstate

我需要看到一个asp.net页面的视图状态的内容。 我查找了一个视图状态解码器,发现Fridz Onion的ViewState解码器,但它要求页面的URL来获取其视图状态。 由于我的viewstate是在回发之后形成的,并且是在更新面板中的一个操作的结果,所以我无法提供一个url。 我需要复制并粘贴viewstatestring,看看里面有什么。 有没有工具或网站可以帮助查看viewstate的内容?

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

这是一个在线的ViewState解码器:

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

编辑:不幸的是,上面的链接是死的 – 这是另一个ViewState解码器(从评论):

http://viewstatedecoder.azurewebsites.net/

以下是Scott Mitchell关于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(); } 

正如另一个人刚刚提到的,这是一个base64编码的string。 在过去,我用这个网站来解码它:

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

这是2014年的另一个解码器: http : //viewstatedecoder.azurewebsites.net/

这对Ignatu解码器在“串行化数据无效”(尽pipe它保留BinaryFormatter序列化的数据未解码,仅显示其长度)的input工作。

JavaScript的ViewState的parsing器:

parsing器应该可以处理大多数未encryption的ViewState。 它不处理由.NET版本1使用的序列化格式,因为该版本严重过时,因此在任何实际情况下都不太可能遇到。

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


parsing.NET ViewState


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

它看起来像你有一个旧版本; 在ASP.NET 2.0中更改了序列化方法,因此请抓取2.0版本

这是有点“本地”.NET的方式转换ViewState从string到StateBag代码如下:

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

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